aboutsummaryrefslogtreecommitdiff
path: root/src/imagedisplay.c
diff options
context:
space:
mode:
authortaw27 <taw27@bf6ca9ba-c028-0410-8290-897cf20841d1>2007-08-29 13:52:59 +0000
committertaw27 <taw27@bf6ca9ba-c028-0410-8290-897cf20841d1>2007-08-29 13:52:59 +0000
commit28fe29530075a28f6ac7a2f86628a00c7cb69af9 (patch)
tree3e3d79799930f1cd502a969a24c889ac8110262c /src/imagedisplay.c
parent3bd37169d751c7b5f0b36847ea902735d9234e63 (diff)
Revamp ImageDisplay
git-svn-id: svn://cook.msm.cam.ac.uk:745/diff-tomo/dtr@86 bf6ca9ba-c028-0410-8290-897cf20841d1
Diffstat (limited to 'src/imagedisplay.c')
-rw-r--r--src/imagedisplay.c328
1 files changed, 171 insertions, 157 deletions
diff --git a/src/imagedisplay.c b/src/imagedisplay.c
index b6d8af9..dfe54ca 100644
--- a/src/imagedisplay.c
+++ b/src/imagedisplay.c
@@ -23,21 +23,20 @@
#include "imagedisplay.h"
#include "utils.h"
+#include "control.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) {
+void imagedisplay_rescale(ImageDisplay *imagedisplay, unsigned int v_w, unsigned int v_h) {
- unsigned int w, h, v_w, v_h;
+ unsigned int w, h;
float aspect_image, aspect_window;
-
- w = imagedisplay->width;
- h = imagedisplay->height;
- v_w = imagedisplay->view_width;
- v_h = imagedisplay->view_height;
+
+ w = imagedisplay->imagerecord.width;
+ h = imagedisplay->imagerecord.height;
/* Preserve aspect ratio */
aspect_image = (float)w/h;
@@ -50,47 +49,44 @@ static void imagedisplay_update(ImageDisplay *imagedisplay) {
/* 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));
- }
+ imagedisplay->view_width = v_w;
+ imagedisplay->view_height = v_h;
}
static gboolean imagedisplay_configure_event(GtkWidget *widget, GdkEventConfigure *event, ImageDisplay *imagedisplay) {
- imagedisplay->view_width = event->width;
- imagedisplay->view_height = event->height;
- imagedisplay_update(imagedisplay);
-
+ imagedisplay->drawingarea_width = event->width;
+ imagedisplay->drawingarea_height = event->height;
+ imagedisplay_rescale(imagedisplay, event->width, event->height);
+
return FALSE;
}
-static void imagedisplay_put_data(ImageDisplay *imagedisplay, uint16_t *image16) {
+static void imagedisplay_put_data(ImageDisplay *imagedisplay, ImageRecord imagerecord) {
unsigned int x, y;
unsigned int w, h;
int min, max;
+ double c, scale;
- h = imagedisplay->height;
- w = imagedisplay->width;
+ h = imagerecord.height;
+ w = imagerecord.width;
min = 2<<15; max = 0;
for ( y=0; y<h; y++ ) {
for ( x=0; x<w; x++ ) {
uint16_t val;
- val = image16[x+w*y];
+ val = imagerecord.image[x+w*y];
if ( val > max ) max = val;
if ( val < min ) min = val;
}
}
- printf("min=%i, max=%i\n", min, max);
+
+ c = 0.1;
+ scale = 255.0 / log(1+c*(max-min));
+
/* Turn 16-bit image data into 8-bit display data */
imagedisplay->data = malloc(3*w*h);
for ( y=0; y<h; y++ ) {
@@ -98,8 +94,8 @@ static void imagedisplay_put_data(ImageDisplay *imagedisplay, uint16_t *image16)
uint16_t val16, val8;
- val16 = image16[x+w*y];
- val8 = (255*(val16-min)) / (max-min);
+ val16 = imagerecord.image[x+w*y];
+ val8 = scale * log(1+c*(val16-min));
imagedisplay->data[3*( x+w*(h-1-y) )] = val8;
imagedisplay->data[3*( x+w*(h-1-y) )+1] = val8;
@@ -112,169 +108,187 @@ static void imagedisplay_put_data(ImageDisplay *imagedisplay, uint16_t *image16)
imagedisplay->pixbuf = gdk_pixbuf_new_from_data(imagedisplay->data, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w*3,
(GdkPixbufDestroyNotify)imagedisplay_free_data, imagedisplay);
- imagedisplay_update(imagedisplay);
-
}
static void imagedisplay_close(GtkWidget *widget, ImageDisplay *imagedisplay) {
+
+ ImageDisplayMark *cur;
+
+ if ( imagedisplay->flags & IMAGEDISPLAY_QUIT_IF_CLOSED ) {
+ gtk_exit(0);
+ }
+
+ g_object_unref(G_OBJECT(imagedisplay->gc_centre));
+ g_object_unref(G_OBJECT(imagedisplay->gc_tiltaxis));
+ g_object_unref(G_OBJECT(imagedisplay->gc_marks));
+
+ cur = imagedisplay->marks;
+ while ( cur ) {
+ ImageDisplayMark *next = cur->next;
+ free(cur);
+ cur = next;
+ }
+
free(imagedisplay);
+
}
-/* Display an image */
-ImageDisplay *imagedisplay_open(uint16_t *image, unsigned int width, unsigned int height, const char *title) {
+#define imagedisplay_draw_line(gc,x1,y1,x2,y2) (gdk_draw_line(drawingarea->window,gc, \
+ xoffs+(x1), yoffs+imagedisplay->view_height-(y1), \
+ xoffs+(x2), yoffs+imagedisplay->view_height-(y2)))
- ImageDisplay *imagedisplay;
- GdkGeometry geom;
+static gboolean imagedisplay_redraw(GtkWidget *drawingarea, GdkEventExpose *event, ImageDisplay *imagedisplay) {
- 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);
+ gint xoffs, yoffs;
+ double scale;
+ ImageDisplayMark *cur;
- 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);
+ xoffs = (imagedisplay->drawingarea_width - imagedisplay->view_width) / 2;
+ yoffs = (imagedisplay->drawingarea_height - imagedisplay->view_height) / 2;
+ scale = (double)imagedisplay->view_width/imagedisplay->imagerecord.width;
- gtk_window_set_default_size(GTK_WINDOW(imagedisplay->window), 512, 512);
+ gdk_draw_pixbuf(drawingarea->window, drawingarea->style->bg_gc[GTK_WIDGET_STATE(drawingarea)], imagedisplay->pixbuf_scaled,
+ 0, 0, xoffs, yoffs, imagedisplay->view_width, imagedisplay->view_height,
+ GDK_RGB_DITHER_NONE, 0, 0);
- gtk_widget_show_all(imagedisplay->window);
+ if ( imagedisplay->flags & IMAGEDISPLAY_SHOW_TILT_AXIS ) {
+ imagedisplay_draw_line(imagedisplay->gc_tiltaxis,
+ imagedisplay->imagerecord.x_centre * scale,
+ imagedisplay->imagerecord.y_centre * scale,
+ (imagedisplay->imagerecord.x_centre + imagedisplay->imagerecord.width) * scale,
+ (imagedisplay->imagerecord.y_centre + imagedisplay->imagerecord.width
+ * tan(deg2rad(imagedisplay->imagerecord.omega))) * scale);
+ imagedisplay_draw_line(imagedisplay->gc_tiltaxis,
+ imagedisplay->imagerecord.x_centre * scale,
+ imagedisplay->imagerecord.y_centre * scale,
+ (imagedisplay->imagerecord.x_centre - imagedisplay->imagerecord.width) * scale,
+ (imagedisplay->imagerecord.y_centre - imagedisplay->imagerecord.width
+ * tan(deg2rad(imagedisplay->imagerecord.omega))) * scale);
+ }
- return imagedisplay;
+ if ( imagedisplay->flags & IMAGEDISPLAY_SHOW_CENTRE ) {
+ imagedisplay_draw_line(imagedisplay->gc_centre,
+ imagedisplay->imagerecord.x_centre * scale - 10,
+ imagedisplay->imagerecord.y_centre * scale,
+ imagedisplay->imagerecord.x_centre * scale + 10,
+ imagedisplay->imagerecord.y_centre * scale);
+ imagedisplay_draw_line(imagedisplay->gc_centre,
+ imagedisplay->imagerecord.x_centre * scale,
+ imagedisplay->imagerecord.y_centre * scale - 10,
+ imagedisplay->imagerecord.x_centre * scale,
+ imagedisplay->imagerecord.y_centre * scale + 10);
+ }
-}
+ cur = imagedisplay->marks;
+ while ( cur ) {
+ gdk_draw_arc(drawingarea->window, imagedisplay->gc_marks, FALSE,
+ xoffs + cur->x*scale,
+ yoffs + cur->y*scale,
+ 10, 10, 0, 64*360);
+ cur = cur->next;
+ }
-void imagedisplay_add_tilt_axis(ImageDisplay *imagedisplay, double xc, double yc, double omega) {
+ return FALSE;
- guchar *image_eightbit;
- int w, h;
- double gradient;
+}
- if ( !imagedisplay->pixbuf ) return;
+static gint imagedisplay_realize(GtkWidget *widget, ImageDisplay *imagedisplay) {
- w = imagedisplay->width;
- h = imagedisplay->height; /* Size of pixbuf */
+ GdkColor colour;
+
+ imagedisplay->gc_centre = gdk_gc_new(imagedisplay->drawingarea->window);
+ gdk_color_parse("yellow", &colour);
+ gdk_gc_set_rgb_fg_color(imagedisplay->gc_centre, &colour);
+
+ imagedisplay->gc_tiltaxis = gdk_gc_new(imagedisplay->drawingarea->window);
+ gdk_color_parse("#6600dd", &colour);
+ gdk_gc_set_rgb_fg_color(imagedisplay->gc_tiltaxis, &colour);
- 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 = xc; y = yc;
- 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 = xc; y = yc;
- 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 = xc; ys = yc;
- 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 = xc; ys = yc;
- 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) );
- }
+ imagedisplay->gc_marks = gdk_gc_new(imagedisplay->drawingarea->window);
+ gdk_color_parse("#dd0000", &colour);
+ gdk_gc_set_rgb_fg_color(imagedisplay->gc_marks, &colour);
+
+ return 0;
}
-void imagedisplay_mark_point(ImageDisplay *imagedisplay, unsigned int x, unsigned int y) {
-
- guchar *image_eightbit;
- int xd, yd;
- int w, h;
+/* Display an image */
+ImageDisplay *imagedisplay_open_with_message(ImageRecord imagerecord, const char *title, const char *message,
+ ImageDisplayFlags flags, GCallback mouse_click_func) {
- if ( !imagedisplay->pixbuf ) return;
+ ImageDisplay *imagedisplay;
+ GdkGeometry geom;
- w = imagedisplay->width;
- h = imagedisplay->height;
-
- g_object_get(G_OBJECT(imagedisplay->pixbuf), "pixels", &image_eightbit, NULL);
+ imagedisplay = malloc(sizeof(ImageDisplay));
+ imagedisplay->imagerecord = imagerecord;
+ imagedisplay->view_width = 512;
+ imagedisplay->view_height = 512;
+ imagedisplay->title = strdup(title);
+ imagedisplay->message = message;
+ imagedisplay->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ imagedisplay->mouse_click_func = mouse_click_func;
+ imagedisplay->flags = flags;
+ imagedisplay->marks = NULL;
+ gtk_window_set_title(GTK_WINDOW(imagedisplay->window), imagedisplay->title);
- 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;
- }
+ imagedisplay_put_data(imagedisplay, imagerecord);
+
+ imagedisplay->vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(imagedisplay->window), imagedisplay->vbox);
+
+ if ( message ) {
+ GtkWidget *label;
+ label = gtk_label_new(message);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(imagedisplay->vbox), label, FALSE, TRUE, 3);
}
- 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;
- }
+
+ imagedisplay->drawingarea = gtk_drawing_area_new();
+ gtk_box_pack_start(GTK_BOX(imagedisplay->vbox), imagedisplay->drawingarea, TRUE, TRUE, 0);
+
+ if ( imagedisplay->mouse_click_func ) {
+ gtk_widget_add_events(GTK_WIDGET(imagedisplay->drawingarea), GDK_BUTTON_PRESS_MASK);
+ g_signal_connect(GTK_OBJECT(imagedisplay->drawingarea), "button-press-event",
+ G_CALLBACK(imagedisplay->mouse_click_func), imagedisplay);
}
-
+
+ g_signal_connect(GTK_OBJECT(imagedisplay->drawingarea), "realize", G_CALLBACK(imagedisplay_realize), imagedisplay);
+ g_signal_connect(GTK_OBJECT(imagedisplay->drawingarea), "destroy", G_CALLBACK(imagedisplay_close), imagedisplay);
+ g_signal_connect(GTK_OBJECT(imagedisplay->drawingarea), "configure_event", G_CALLBACK(imagedisplay_configure_event), imagedisplay);
+ g_signal_connect(GTK_OBJECT(imagedisplay->drawingarea), "expose-event", G_CALLBACK(imagedisplay_redraw), imagedisplay);
+
+ geom.min_width = 128; geom.min_height = 128;
+ gtk_window_set_geometry_hints(GTK_WINDOW(imagedisplay->window), GTK_WIDGET(imagedisplay->drawingarea), &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_mark_circle(ImageDisplay *imagedisplay, unsigned int x, unsigned int y) {
+ImageDisplay *imagedisplay_open(ImageRecord image, const char *title, ImageDisplayFlags flags) {
+ return imagedisplay_open_with_message(image, title, NULL, flags, NULL);
+}
- guchar *image_eightbit;
- int xd, yd;
- int w, h;
+void imagedisplay_mark_circle(ImageDisplay *imagedisplay, double x, double y) {
- if ( !imagedisplay->pixbuf ) return;
+ ImageDisplayMark *new;
- w = imagedisplay->width;
- h = imagedisplay->height;
-
- g_object_get(G_OBJECT(imagedisplay->pixbuf), "pixels", &image_eightbit, NULL);
+ new = malloc(sizeof(ImageDisplayMark));
+ new->x = x; new->y = y;
+ new->type = IMAGEDISPLAY_MARK_CIRCLE;
+ new->next = 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) )] = 0;
- imagedisplay->data[3*( xd+w*(h-1-y) )+1] = 255;
- 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) )] = 0;
- imagedisplay->data[3*( x+w*(h-1-yd) )+1] = 255;
- imagedisplay->data[3*( x+w*(h-1-yd) )+2] = 0;
+ if ( !imagedisplay->marks ) {
+ imagedisplay->marks = new;
+ } else {
+ ImageDisplayMark *cur = imagedisplay->marks;
+ while ( cur->next ) {
+ cur = cur->next;
}
+ cur->next = new;
}
}