aboutsummaryrefslogtreecommitdiff
path: root/src/crystfelimageview.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/crystfelimageview.c')
-rw-r--r--src/crystfelimageview.c170
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;