aboutsummaryrefslogtreecommitdiff
path: root/src/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/render.c')
-rw-r--r--src/render.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/render.c b/src/render.c
new file mode 100644
index 00000000..96e0b906
--- /dev/null
+++ b/src/render.c
@@ -0,0 +1,183 @@
+/*
+ * render.c
+ *
+ * Render a high dynamic range buffer in some sensible way
+ *
+ * (c) 2008-2009 Thomas White <taw27@cam.ac.uk>
+ *
+ * hdfileview - view Ditabis Micron images
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "hdf5-file.h"
+
+/* Set to 1 to measure mean intensity in a rectangle */
+#define MEASURE_INT 0
+
+#define RENDER_RGB \
+ \
+ int s; \
+ float p; \
+ \
+ s = val / (max/6); \
+ p = fmod(val, max/6); \
+ p /= (max/6); \
+ \
+ r = 0; g = 0; b = 0; \
+ \
+ switch ( s ) { \
+ case 0 : { /* Black to blue */ \
+ r = 0; g = 0; b = p*255; \
+ break; \
+ } \
+ case 1 : { /* Blue to green */ \
+ r = 0; g = 255*p; b = (1-p)*255; \
+ break; \
+ } \
+ case 2 : { /* Green to red */ \
+ r =p*255; g = (1-p)*255; b = 0; \
+ break; \
+ } \
+ case 3 : { /* Red to Orange */ \
+ r = 255; g = 127*p; b = 0; \
+ break; \
+ } \
+ case 4 : { /* Orange to Yellow */ \
+ r = 255; g = 127 + 127*p; b = 0; \
+ break; \
+ } \
+ case 5 : { /* Yellow to White */ \
+ r = 255; g = 255; b = 255*p; \
+ break; \
+ } \
+ case 6 : { /* Pixel has hit the maximum value */ \
+ r = 255; g = 255; b = 255; \
+ break; \
+ } \
+ default : { /* Above saturation */ \
+ r = 255; g = 255; b = 255; \
+ break; \
+ } \
+ }
+
+#define RENDER_MONO \
+ float p; \
+ p = (float)val / (float)max; \
+ r = 255.0*p; g = 255.0*p; b = 255.0*p;
+
+/* NB This function is shared between render_get_image() and
+ * render_get_colour_scale() */
+static void render_free_data(guchar *data, gpointer p)
+{
+ free(data);
+}
+
+/* Return a pixbuf containing a rendered version of the image after binning.
+ * This pixbuf might be scaled later - hopefully mostly in a downward
+ * direction. */
+GdkPixbuf *render_get_image(struct hdfile *hdfile, int binning, int boostint,
+ int monochrome)
+{
+ int mw, mh, w, h;
+ guchar *data;
+ uint16_t *hdr;
+ size_t x, y;
+ uint16_t max;
+
+ mw = hdfile_get_width(hdfile);
+ mh = hdfile_get_height(hdfile);
+ w = mw / binning;
+ h = mh / binning;
+
+ /* High dynamic range version */
+ hdr = hdfile_get_image_binned(hdfile, binning, &max);
+ if ( hdr == NULL ) return NULL;
+
+ /* Rendered (colourful) version */
+ data = malloc(3*w*h);
+ if ( data == NULL ) {
+ free(hdr);
+ return NULL;
+ }
+
+ max /= boostint;
+ if ( max <= 0.0 ) { max = 10.0; }
+ /* These x,y coordinates are measured relative to the bottom-left
+ * corner */
+ for ( y=0; y<h; y++ ) {
+ for ( x=0; x<w; x++ ) {
+
+ int val;
+ guchar r, g, b;
+
+ val = hdr[x+w*y];
+ if ( !monochrome ) {
+ RENDER_RGB
+ } else {
+ RENDER_MONO
+ }
+
+ /* 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*(h-1-y) )+0] = r;
+ data[3*( x+w*(h-1-y) )+1] = g;
+ data[3*( x+w*(h-1-y) )+2] = b;
+
+ }
+ }
+
+ /* Finished with this */
+ free(hdr);
+
+ /* 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);
+}
+
+GdkPixbuf *render_get_colour_scale(size_t w, size_t h, int monochrome)
+{
+ guchar *data;
+ size_t x, y;
+ int max;
+
+ data = malloc(3*w*h);
+ if ( data == NULL ) return NULL;
+
+ max = h;
+
+ for ( y=0; y<h; y++ ) {
+
+ guchar r, g, b;
+ int val;
+
+ val = y;
+ if ( !monochrome ) {
+ RENDER_RGB
+ } else {
+ RENDER_MONO
+ }
+
+ 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] = r;
+ data[3*( x+w*(h-1-y) )+1] = g;
+ data[3*( x+w*(h-1-y) )+2] = b;
+ }
+
+ }
+
+ return gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, FALSE, 8,
+ w, h, w*3, render_free_data, NULL);
+}