/* * imagedisplay.c * * Show raw and processed images * * (c) 2007 Thomas White * dtr - Diffraction Tomography Reconstruction * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include "imagedisplay.h" #include "utils.h" /* Free pixbuf data when reference count drops to zero */ static void imagedisplay_free_data(guchar *image_eightbit, ImageDisplay *imagedisplay) { free(image_eightbit); } static void imagedisplay_update(ImageDisplay *imagedisplay) { unsigned int w, h, v_w, v_h; float aspect_image, aspect_window; w = imagedisplay->width; h = imagedisplay->height; v_w = imagedisplay->view_width; v_h = imagedisplay->view_height; /* Preserve aspect ratio */ aspect_image = (float)w/h; aspect_window = (float)v_w/v_h; if ( aspect_window > aspect_image ) { v_w = aspect_image*v_h; } else { v_h = v_w/aspect_image; } /* Create the scaled pixbuf from the 8-bit display data */ imagedisplay->pixbuf_scaled = gdk_pixbuf_scale_simple(imagedisplay->pixbuf, v_w, v_h, GDK_INTERP_BILINEAR); /* Create the image with the scaled pixbuf */ if ( !imagedisplay->image ) { imagedisplay->image = gtk_image_new_from_pixbuf(imagedisplay->pixbuf_scaled); gtk_container_add(GTK_CONTAINER(imagedisplay->window), imagedisplay->image); gtk_widget_show(imagedisplay->image); } else { gtk_image_set_from_pixbuf(GTK_IMAGE(imagedisplay->image), GDK_PIXBUF(imagedisplay->pixbuf_scaled)); } } static gboolean imagedisplay_configure_event(GtkWidget *widget, GdkEventConfigure *event, ImageDisplay *imagedisplay) { imagedisplay->view_width = event->width; imagedisplay->view_height = event->height; imagedisplay_update(imagedisplay); return FALSE; } static void imagedisplay_put_data(ImageDisplay *imagedisplay, int16_t *image16) { unsigned int x, y; unsigned int w, h; h = imagedisplay->height; w = imagedisplay->width; /* Turn 16-bit image data into 8-bit display data */ imagedisplay->data = malloc(3*w*h); for ( y=0; y 255 ) { imagedisplay->data[3*( x+w*(h-1-y) )] = 255; imagedisplay->data[3*( x+w*(h-1-y) )+1] = 255; imagedisplay->data[3*( x+w*(h-1-y) )+2] = 255; } else if ( val16 < 0 ) { imagedisplay->data[3*( x+w*(h-1-y) )] = 0; imagedisplay->data[3*( x+w*(h-1-y) )+1] = 0; imagedisplay->data[3*( x+w*(h-1-y) )+2] = 0; } else { imagedisplay->data[3*( x+w*(h-1-y) )] = val16; imagedisplay->data[3*( x+w*(h-1-y) )+1] = val16; imagedisplay->data[3*( x+w*(h-1-y) )+2] = val16; } } } /* Create the pixbuf from the 8-bit display data */ imagedisplay->pixbuf = gdk_pixbuf_new_from_data(imagedisplay->data, GDK_COLORSPACE_RGB, FALSE, 8, w, h, h*3, (GdkPixbufDestroyNotify)imagedisplay_free_data, imagedisplay); imagedisplay_update(imagedisplay); } static void imagedisplay_close(GtkWidget *widget, ImageDisplay *imagedisplay) { free(imagedisplay); } /* Display an image */ ImageDisplay *imagedisplay_open(int16_t *image, unsigned int width, unsigned int height, const char *title) { ImageDisplay *imagedisplay; GdkGeometry geom; imagedisplay = malloc(sizeof(ImageDisplay)); imagedisplay->image = NULL; imagedisplay->width = width; imagedisplay->height = height; imagedisplay->view_width = 512; imagedisplay->view_height = 512; imagedisplay->title = strdup(title); imagedisplay->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(imagedisplay->window), imagedisplay->title); imagedisplay_put_data(imagedisplay, image); g_signal_connect(GTK_OBJECT(imagedisplay->window), "destroy", G_CALLBACK(imagedisplay_close), imagedisplay); g_signal_connect(GTK_OBJECT(imagedisplay->window), "configure_event", G_CALLBACK(imagedisplay_configure_event), imagedisplay); geom.min_width = 128; geom.min_height = 128; gtk_window_set_geometry_hints(GTK_WINDOW(imagedisplay->window), GTK_WIDGET(imagedisplay->image), &geom, GDK_HINT_MIN_SIZE); gtk_window_set_default_size(GTK_WINDOW(imagedisplay->window), 512, 512); gtk_widget_show_all(imagedisplay->window); return imagedisplay; } void imagedisplay_add_tilt_axis(ImageDisplay *imagedisplay, ControlContext *ctx, double omega) { guchar *image_eightbit; int w, h; double gradient; if ( !imagedisplay->pixbuf ) return; w = imagedisplay->width; h = imagedisplay->height; /* Size of pixbuf */ g_object_get(G_OBJECT(imagedisplay->pixbuf), "pixels", &image_eightbit, NULL); gradient = tan(M_PI*omega/180); if ( gradient > 1 ) { double xs; signed int x, y; gradient = 1/gradient; /* Start at the centre and draw a line out in each direction until it hits an edge. This makes the whole thing a lot easier. */ xs = ctx->x_centre; y = ctx->y_centre; do { x = xs; image_eightbit[3*(x+w*(h-1-y))+0] = 255; image_eightbit[3*(x+w*(h-1-y))+1] = 255; image_eightbit[3*(x+w*(h-1-y))+2] = 0; y++; xs += gradient; } while ( (xs=0) && (y>=0) ); xs = ctx->x_centre; y = ctx->y_centre; do { x = xs; image_eightbit[3*(x+w*(h-1-y))+0] = 255; image_eightbit[3*(x+w*(h-1-y))+1] = 255; image_eightbit[3*(x+w*(h-1-y))+2] = 0; y--; xs -= gradient; } while ( (xs=0) && (y>=0) ); } else { double ys; signed int x, y; x = ctx->x_centre; ys = ctx->y_centre; do { y = ys; image_eightbit[3*(x+w*(h-1-y))+0] = 255; image_eightbit[3*(x+w*(h-1-y))+1] = 255; image_eightbit[3*(x+w*(h-1-y))+2] = 0; x++; ys += gradient; } while ( (x=0) && (ys>=0) ); x = ctx->x_centre; ys = ctx->y_centre; do { y = ys; image_eightbit[3*(x+w*(h-1-y))+0] = 255; image_eightbit[3*(x+w*(h-1-y))+1] = 255; image_eightbit[3*(x+w*(h-1-y))+2] = 0; x--; ys -= gradient; } while ( (x=0) && (ys>=0) ); } } void imagedisplay_mark_point(ImageDisplay *imagedisplay, unsigned int x, unsigned int y) { guchar *image_eightbit; int xd, yd; int w, h; if ( !imagedisplay->pixbuf ) return; w = imagedisplay->width; h = imagedisplay->height; g_object_get(G_OBJECT(imagedisplay->pixbuf), "pixels", &image_eightbit, NULL); if ( (y >= 0) && (y < h) ) { for ( xd=biggest(x-3, 0); xd<=smallest(x+3, w-1); xd++ ) { imagedisplay->data[3*( xd+w*(h-1-y) )] = 255; imagedisplay->data[3*( xd+w*(h-1-y) )+1] = 0; imagedisplay->data[3*( xd+w*(h-1-y) )+2] = 0; } } if ( (x >= 0) && (x < w) ) { for ( yd=biggest(y-3, 0); yd<=smallest(y+3, h-1); yd++ ) { imagedisplay->data[3*( x+w*(h-1-yd) )] = 255; imagedisplay->data[3*( x+w*(h-1-yd) )+1] = 0; imagedisplay->data[3*( x+w*(h-1-yd) )+2] = 0; } } }