aboutsummaryrefslogtreecommitdiff
path: root/src/imagedisplay.c
diff options
context:
space:
mode:
authortaw27 <taw27@bf6ca9ba-c028-0410-8290-897cf20841d1>2007-02-05 21:12:57 +0000
committertaw27 <taw27@bf6ca9ba-c028-0410-8290-897cf20841d1>2007-02-05 21:12:57 +0000
commit05b5d261682b9136fb46476a64eab6980b0dba64 (patch)
treed7faa450b69cf2104ffff7fc89a95914284d23af /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.c244
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;
+ }
+ }
+
+}