aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2020-06-29 13:55:20 +0200
committerThomas White <taw@physics.org>2020-07-29 18:53:44 +0200
commit6dfea8ddd0b7cb717fc120dc68edc42b0e1fbdd8 (patch)
tree0579adcdcee8bb37c8028c26065b068276868204 /src
parent93be7a848a320d8eaa0966f57aa56b0337525d4c (diff)
Break render.c down and move to geoptimiser and CrystFELImageView
These two functions will diverge in the future. Also, this change removes the last remaining dependency of libcrystfel on Gdk/Gtk-anything.
Diffstat (limited to 'src')
-rw-r--r--src/crystfelimageview.c170
-rw-r--r--src/geoptimiser.c44
2 files changed, 211 insertions, 3 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;
diff --git a/src/geoptimiser.c b/src/geoptimiser.c
index ec4fbcd4..385a85d4 100644
--- a/src/geoptimiser.c
+++ b/src/geoptimiser.c
@@ -59,7 +59,6 @@
#include "crystal.h"
#include "image.h"
#include "utils.h"
-#include "render.h"
#include "colscale.h"
struct imagefeature;
@@ -157,6 +156,49 @@ struct gpanel
};
+static GdkPixbuf *render_get_colour_scale(size_t w, size_t h, int scale)
+{
+ guchar *data;
+ size_t x, y;
+ int max;
+
+ data = malloc(3*w*h);
+ if ( data == NULL ) return NULL;
+
+ max = h-(h/6);
+
+ for ( y=0; y<h; y++ ) {
+
+ double r, g, b;
+ int val;
+
+ val = y-(h/6);
+
+ render_scale(val, max, scale, &r, &g, &b);
+
+ data[3*( 0+w*(h-1-y) )+0] = 0;
+ data[3*( 0+w*(h-1-y) )+1] = 0;
+ data[3*( 0+w*(h-1-y) )+2] = 0;
+ for ( x=1; x<w; x++ ) {
+ data[3*( x+w*(h-1-y) )+0] = 255*r;
+ data[3*( x+w*(h-1-y) )+1] = 255*g;
+ data[3*( x+w*(h-1-y) )+2] = 255*b;
+ }
+
+ }
+
+ y = h/6;
+ for ( x=1; x<w; x++ ) {
+ data[3*( x+w*(h-1-y) )+0] = 255;
+ data[3*( x+w*(h-1-y) )+1] = 255;
+ data[3*( x+w*(h-1-y) )+2] = 255;
+ }
+
+ return gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, FALSE, 8,
+ w, h, w*3, render_free_data, NULL);
+}
+
+
static void compute_x_y(double fs, double ss, struct panel *p,
double *x, double *y)
{