diff options
Diffstat (limited to 'src/crystfelimageview.c')
-rw-r--r-- | src/crystfelimageview.c | 170 |
1 files changed, 168 insertions, 2 deletions
diff --git a/src/crystfelimageview.c b/src/crystfelimageview.c index 35636a73..7cb3f9b6 100644 --- a/src/crystfelimageview.c +++ b/src/crystfelimageview.c @@ -39,7 +39,6 @@ #include <utils.h> #include <detgeom.h> -#include <render.h> #include <colscale.h> #include "crystfelimageview.h" @@ -68,7 +67,6 @@ G_DEFINE_TYPE_WITH_CODE(CrystFELImageView, crystfel_image_view, G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, scroll_interface_init)) - static void redraw(CrystFELImageView *iv) { gint w, h; @@ -676,6 +674,174 @@ static void detgeom_pixel_extents(struct detgeom *det, } +static float *get_binned_panel(struct image *image, int binning, + int pi, double *max, int *pw, int *ph) +{ + float *data; + int x, y; + int w, h; + + struct detgeom_panel *p = &image->detgeom->panels[pi]; + + /* Some pixels might get discarded */ + w = p->w / binning; + h = p->h / binning; + *pw = w; + *ph = h; + + data = malloc(w*h*sizeof(float)); + + *max = 0.0; + for ( x=0; x<w; x++ ) { + for ( y=0; y<h; y++ ) { + + double total; + size_t xb, yb; + int bad = 0; + double val; + + total = 0; + for ( xb=0; xb<binning; xb++ ) { + for ( yb=0; yb<binning; yb++ ) { + + double v; + int fs, ss; + + fs = binning*x+xb; + ss = binning*y+yb; + v = image->dp[pi][fs+ss*p->w]; + total += v; + + if ( (image->bad != NULL) + && (image->bad[pi][fs+ss*p->w]) ) bad = 1; + + } + } + + val = total / ((double)binning * (double)binning); + + if ( bad ) { + data[x+w*y] = -INFINITY; + } else { + data[x+w*y] = val; + if ( val > *max ) *max = val; + } + + } + } + + return data; +} + + +static void render_free_data(guchar *data, gpointer p) +{ + free(data); +} + + +static GdkPixbuf *render_panel(float *hdr, int scale, double max, int w, int h) +{ + guchar *data; + int x, y; + + /* Rendered (colourful) version */ + data = malloc(3*w*h); + if ( data == NULL ) return NULL; + + /* These x,y coordinates are measured relative to the bottom-left + * corner */ + for ( y=0; y<h; y++ ) { + for ( x=0; x<w; x++ ) { + + double val; + double r, g, b; + + val = hdr[x+w*y]; + + if ( val > -INFINITY ) { + + render_scale(val, max, scale, &r, &g, &b); + + /* Stuff inside square brackets makes this pixel go to + * the expected location in the pixbuf (which measures + * from the top-left corner */ + data[3*( x+w*y )+0] = 255*r; + data[3*( x+w*y )+1] = 255*g; + data[3*( x+w*y )+2] = 255*b; + + } else { + + data[3*( x+w*y )+0] = 30; + data[3*( x+w*y )+1] = 20; + data[3*( x+w*y )+2] = 0; + + } + + } + } + + /* Create the pixbuf from the 8-bit display data */ + return gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, FALSE, 8, + w, h, w*3, render_free_data, NULL); + +} + + +/* Render an image into multiple pixbufs according to geometry */ +GdkPixbuf **render_panels(struct image *image, + int binning, int scale, double boost, + int *n_pixbufs) +{ + int i; + int np; + GdkPixbuf **pixbufs; + float **hdrs; + double max; + int *ws, *hs; + + np = image->detgeom->n_panels; + + hdrs = calloc(np, sizeof(float *)); + ws = calloc(np, sizeof(int)); + hs = calloc(np, sizeof(int)); + if ( (hdrs == NULL) || (ws == NULL) || (hs == NULL) ) { + *n_pixbufs = 0; + return NULL; + } + + /* Find overall max value for whole image */ + max = 0.0; + for ( i=0; i<np; i++ ) { + double this_max = 0.0; + hdrs[i] = get_binned_panel(image, binning, i, &this_max, + &ws[i], &hs[i]); + if ( this_max > max ) max = this_max; + } + + max /= boost; + if ( max <= 6 ) { max = 10; } + + pixbufs = calloc(np, sizeof(GdkPixbuf*)); + if ( pixbufs == NULL ) { + *n_pixbufs = 0; + return NULL; + } + + for ( i=0; i<np; i++ ) { + pixbufs[i] = render_panel(hdrs[i], scale, max, ws[i], hs[i]); + free(hdrs[i]); + } + + free(hdrs); + free(ws); + free(hs); + *n_pixbufs = np; + + return pixbufs; +} + + static int reload_image(CrystFELImageView *iv) { if ( iv->dtempl == NULL ) return 0; |