diff options
Diffstat (limited to 'src/imagedisplay.c')
-rw-r--r-- | src/imagedisplay.c | 328 |
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; } } |