diff options
author | taw27 <taw27@bf6ca9ba-c028-0410-8290-897cf20841d1> | 2007-02-05 21:12:57 +0000 |
---|---|---|
committer | taw27 <taw27@bf6ca9ba-c028-0410-8290-897cf20841d1> | 2007-02-05 21:12:57 +0000 |
commit | 05b5d261682b9136fb46476a64eab6980b0dba64 (patch) | |
tree | d7faa450b69cf2104ffff7fc89a95914284d23af /src/imagedisplay.c |
Initial import
git-svn-id: svn://cook.msm.cam.ac.uk:745/diff-tomo/dtr@1 bf6ca9ba-c028-0410-8290-897cf20841d1
Diffstat (limited to 'src/imagedisplay.c')
-rw-r--r-- | src/imagedisplay.c | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/src/imagedisplay.c b/src/imagedisplay.c new file mode 100644 index 0000000..aaa9bf9 --- /dev/null +++ b/src/imagedisplay.c @@ -0,0 +1,244 @@ +/* + * imagedisplay.c + * + * Show raw and processed images + * + * (c) 2007 Thomas White <taw27@cam.ac.uk> + * dtr - Diffraction Tomography Reconstruction + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtk.h> +#include <gdk-pixbuf/gdk-pixbuf.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <math.h> + +#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<h; y++ ) { + for ( x=0; x<w; x++ ) { + + int16_t val16 = image16[x+w*y]; + if ( val16 > 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<w) && (y<h) && (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<w) && (y<h) && (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<w) && (ys<h) && (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<w) && (ys<h) && (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; + } + } + +} |