[GRASS-dev] Modified i.rgb.his

Nikos Alexandris nik at nikosalexandris.net
Sat Aug 27 06:54:27 PDT 2016


Attached here-in a slightly updated diff (from the last diff attached in
#774) for i.rgb.his.

I need time to learn/understand things (in C). Yet, I tested the "new"
version and it works for me.

I would like to push this version into SVN myself. Thus, I'd like to ask
(in the grass-psc list) for commit access. However, I can just submit
another, updated, diff, in ticket #774 for someone to take over.

Modifying i.his.rgb, accordingly, is halfway done. I mostly learn how to
use pre-existing C functions, and this is a bit time-consuming.

These modifications would free-up also subsequent modules who use
i.[rgb|his].[his|rgb] to compute maps of more than 8-bit. For example,
i.pansharpen [see tickets #774, #2048]

Thanks for any attention.
Nikos
-------------- next part --------------
Index: closefiles.c
===================================================================
--- closefiles.c	(revision 69246)
+++ closefiles.c	(working copy)
@@ -1,20 +1,18 @@
 #include <stdlib.h>
-#include <grass/gis.h>
-#include <grass/raster.h>
 #include "globals.h"
 
 /* This routine closes up the cell maps, frees up the row buffers and
-   use a less than perfect way of setting the color maps for the output
+   uses a less than perfect way of setting the color maps for the output
    to grey scale.  */
 
 int closefiles(char *h_name, char *i_name, char *s_name,
-	       int fd_output[3], CELL * rowbuf[3])
+	       int fd_output[3], FCELL * rowbuf[3])
 {
     int i;
     struct Colors colors;
-    struct Range range;
+    struct FPRange range;
     struct History history;
-    CELL min, max;
+    DCELL min, max;
     const char *mapset;
 
     for (i = 0; i < 3; i++) {
@@ -25,20 +23,19 @@
     mapset = G_mapset();
 
     /* write colors */
-    /*   set to 0,max_level instead of min,max ?? */
-    Rast_read_range(h_name, mapset, &range);
-    Rast_get_range_min_max(&range, &min, &max);
-    Rast_make_grey_scale_colors(&colors, min, max);
+    Rast_read_fp_range(h_name, mapset, &range);
+    Rast_get_fp_range_min_max(&range, &min, &max);
+    Rast_make_grey_scale_fp_colors(&colors, min, max);
     Rast_write_colors(h_name, mapset, &colors);
 
-    Rast_read_range(i_name, mapset, &range);
-    Rast_get_range_min_max(&range, &min, &max);
-    Rast_make_grey_scale_colors(&colors, min, max);
+    Rast_read_fp_range(i_name, mapset, &range);
+    Rast_get_fp_range_min_max(&range, &min, &max);
+    Rast_make_grey_scale_fp_colors(&colors, min, max);
     Rast_write_colors(i_name, mapset, &colors);
 
-    Rast_read_range(s_name, mapset, &range);
-    Rast_get_range_min_max(&range, &min, &max);
-    Rast_make_grey_scale_colors(&colors, min, max);
+    Rast_read_fp_range(s_name, mapset, &range);
+    Rast_get_fp_range_min_max(&range, &min, &max);
+    Rast_make_grey_scale_fp_colors(&colors, min, max);
     Rast_write_colors(s_name, mapset, &colors);
 
     /* write metadata */
@@ -46,6 +43,7 @@
     Rast_command_history(&history);
     Rast_write_history(h_name, &history);
     Rast_put_cell_title(h_name, "Image hue");
+    Rast_write_units(h_name, "degrees");
 
     Rast_short_history(i_name, "raster", &history);
     Rast_command_history(&history);
@@ -59,4 +57,3 @@
 
     return 0;
 }
-
Index: globals.h
===================================================================
--- globals.h	(revision 69246)
+++ globals.h	(working copy)
@@ -4,12 +4,13 @@
 #include <grass/raster.h>
 
 /* closefiles.c */
-int closefiles(char *, char *, char *, int[3], CELL *[3]);
+int closefiles(char *, char *, char *, int[3], FCELL *[3]);
 
 /* openfiles.c */
 void openfiles(char *, char *, char *, char *, char *, char *,
-	       int[3], int[3], CELL *[3]);
+	       int[3], int[3], DCELL *[3]);
+
 /* rgb2his.c */
-void rgb2his(CELL *[3], int);
+void rgb2his(DCELL *[3], int, double);
 
 #endif /* __GLOBALS_H__ */
Index: main.c
===================================================================
--- main.c	(revision 69246)
+++ main.c	(working copy)
@@ -6,10 +6,10 @@
  * AUTHOR(S):    David Satnik, GIS Laboratory, Central Washington University
  *               with acknowledgements to Ali Vali,
  *               Univ. of Texas Space Research Center, for the core routine. 
- *               
- * PURPOSE:      Red-green-blue (rgb) to hue-intensity-saturation (his) 
- *               raster map color transformation function
  *
+ * PURPOSE:      Previously: Red-green-blue (rgb) to hue-intensity-saturation
+ *               (his) raster map color transformation function
+ *
  * COPYRIGHT:    (C) 2007-2008 by the GRASS Development Team
  *
  *               This program is free software under the GNU General Public
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 #include <grass/gis.h>
 #include <grass/raster.h>
 #include <grass/glocale.h>
@@ -30,13 +31,16 @@
 {
     long i;
     int band, rows, cols;
-    CELL *rowbuffer[3];
+    DCELL *rowbuffer[3];
     struct Option *opt_hue, *opt_red;
-    struct Option *opt_inten, *opt_green;
-    struct Option *opt_sat, *opt_blue;
+    struct Option *opt_intensity, *opt_green;
+    struct Option *opt_saturation, *opt_blue;
+    struct Option *opt_bit_depth;
     struct GModule *module;
     int fd_input[3];
     int fd_output[3];
+    int bit_depth;
+    double max_level;   /* expanded bitdepth (eg 255) */
 
     /* Initialize GIS engine */
     G_gisinit(argv[0]);
@@ -46,11 +50,11 @@
     G_add_keyword(_("imagery"));
     G_add_keyword(_("color transformation"));
     G_add_keyword("RGB");
-    G_add_keyword("HIS");
-    G_add_keyword("IHS");
+    G_add_keyword("HSL");
+    G_add_keyword("HSV");
     module->description =
-	_("Transforms raster maps from RGB (Red-Green-Blue) color space to "
-	  "HIS (Hue-Intensity-Saturation) color space.");
+	_("Transforms raster maps from Red-Green-Blue (RGB) color space to "
+	  "Hue-Saturation-Luminance (HSL) color space.");
 
     /* Define the different options */
     opt_red = G_define_standard_option(G_OPT_R_INPUT);
@@ -69,43 +73,60 @@
     opt_hue->key = "hue";
     opt_hue->description = _("Name for output raster map (hue)");
 
-    opt_inten = G_define_standard_option(G_OPT_R_OUTPUT);
-    opt_inten->key = "intensity";
-    opt_inten->description = _("Name for output raster map (intensity)");
+    opt_intensity = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_intensity->key = "intensity";
+    opt_intensity->description = _("Name for output raster map (intensity)");
 
-    opt_sat = G_define_standard_option(G_OPT_R_OUTPUT);
-    opt_sat->key = "saturation";
-    opt_sat->description = _("Name for output raster map (saturation)");
+    opt_saturation = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_saturation->key = "saturation";
+    opt_saturation->description = _("Name for output raster map (saturation)");
 
+    opt_bit_depth = G_define_option();
+    opt_bit_depth->key = "bit_depth";
+    opt_bit_depth->type = TYPE_INTEGER;
+    opt_bit_depth->required = NO;
+    opt_bit_depth->answer = "8";
+    opt_bit_depth->options = "8-16";
+    opt_bit_depth->description = _("Number of bits in a band");
+
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
 
+    bit_depth = atoi(opt_bit_depth->answer);
+    if (bit_depth <= 0)
+	G_fatal_error(_("Invalid number of levels"));
+    max_level = pow(2, bit_depth) - 1.0;
+    G_debug(1, "%d-bit data has range 0,%.0f", bit_depth, max_level);
+
+
     /* get dimension of the image */
     rows = Rast_window_rows();
     cols = Rast_window_cols();
 
     openfiles(opt_red->answer, opt_green->answer, opt_blue->answer,
-	      opt_hue->answer, opt_inten->answer, opt_sat->answer,
+	      opt_hue->answer, opt_intensity->answer, opt_saturation->answer,
 	      fd_input, fd_output, rowbuffer);
 
     for (i = 0; i < rows; i++) {
-	/* read in a row from each cell map */
-	G_percent(i, rows, 2);
+        /* read in a row from each cell map */
+        G_percent(i, rows, 2);
 
 	for (band = 0; band < 3; band++)
-	    Rast_get_c_row(fd_input[band], rowbuffer[band], i);
+	    /* Rast_get_c_row(fd_input[band], rowbuffer[band], i); */
+	    Rast_get_d_row(fd_input[band], rowbuffer[band], i);
 
 	/* process this row of the map */
-	rgb2his(rowbuffer, cols);
+	rgb2his(rowbuffer, cols, max_level);
 
 	/* write out the new row for each cell map */
 	for (band = 0; band < 3; band++)
-	    Rast_put_row(fd_output[band], rowbuffer[band], CELL_TYPE);
+	    /* Rast_put_row(fd_output[band], rowbuffer[band], CELL_TYPE); */
+	    Rast_put_row(fd_output[band], rowbuffer[band], DCELL_TYPE);
     }
     G_percent(i, rows, 2);
 
-    closefiles(opt_hue->answer, opt_inten->answer, opt_sat->answer,
+    closefiles(opt_hue->answer, opt_intensity->answer, opt_saturation->answer,
 	       fd_output, rowbuffer);
 
 
Index: openfiles.c
===================================================================
--- openfiles.c	(revision 69246)
+++ openfiles.c	(working copy)
@@ -1,13 +1,9 @@
 #include <stdio.h>
-#include <grass/gis.h>
-#include <grass/raster.h>
-#include <grass/glocale.h>
 #include "globals.h"
 
-
 void openfiles(char *r_name, char *g_name, char *b_name,
 	       char *h_name, char *i_name, char *s_name,
-	       int fd_input[3], int fd_output[3], CELL * rowbuf[3])
+	       int fd_input[3], int fd_output[3], DCELL * rowbuf[3])
 {
     fd_input[0] = Rast_open_old(r_name, "");
     fd_input[1] = Rast_open_old(g_name, "");
@@ -14,12 +10,12 @@
     fd_input[2] = Rast_open_old(b_name, "");
 
     /* open output files */
-    fd_output[0] = Rast_open_c_new(h_name);
-    fd_output[1] = Rast_open_c_new(i_name);
-    fd_output[2] = Rast_open_c_new(s_name);
+    fd_output[0] = Rast_open_fp_new(h_name);
+    fd_output[1] = Rast_open_fp_new(i_name);
+    fd_output[2] = Rast_open_fp_new(s_name);
 
     /* allocate the cell row buffer */
-    rowbuf[0] = Rast_allocate_c_buf();
-    rowbuf[1] = Rast_allocate_c_buf();
-    rowbuf[2] = Rast_allocate_c_buf();
+    rowbuf[0] = Rast_allocate_d_buf();
+    rowbuf[1] = Rast_allocate_d_buf();
+    rowbuf[2] = Rast_allocate_d_buf();
 }
Index: rgb2his.c
===================================================================
--- rgb2his.c	(revision 69246)
+++ rgb2his.c	(working copy)
@@ -2,9 +2,7 @@
 /******************************************************************************
 NAME:                         RGB2HIS
  
-PURPOSE    To process red,green,blue bands to hue,intensity,saturation.
- 
-ALGORITHM:
+PURPOSE    To process red,green,blue bands to hue
    Get red, green, blue from input buffer
    Create the HIS bands
    Write to output buffer
@@ -17,109 +15,110 @@
    each band is processed and written out.   CWU GIS Lab: DBS 8/90 */
 
 #include <grass/gis.h>
+#include <grass/glocale.h>
 #include "globals.h"
+#include <math.h>
 
-void rgb2his(CELL * rowbuffer[3], int columns)
+
+/* read in RGB as double precision DCELL? */
+/* or get type automatically? Rast_map_type() */
+
+void rgb2his(DCELL *rowbuffer[3], int columns, double max_level)
 {
     int sample;			/* sample indicator                      */
     double red;			/* the red band output                   */
     double green;		/* the green band output                 */
     double blue;		/* the blue band output                  */
-    double scaler;		/* red value                             */
-    double scaleg;		/* green value                           */
-    double scaleb;		/* blue value                            */
-    double high;		/* maximum red, green, blue              */
-    double low;			/* minimum red, green, blue              */
-    double intens;		/* intensity                             */
-    double sat;			/* saturation                            */
-    double hue = 0.0L;		/* hue                                   */
+    double max;	    	/* maximum red, green, blue              */
+    double min;			/* minimum red, green, blue              */
+    double chroma;
+    double intensity;   /* intensity                             */
+    double saturation;	/* saturation                            */
+    double hue = 0.0L;	/* hue                                   */
 
-    for (sample = 0; sample < columns; sample++) {
-	if (Rast_is_c_null_value(&rowbuffer[0][sample]) ||
-	    Rast_is_c_null_value(&rowbuffer[1][sample]) ||
-	    Rast_is_c_null_value(&rowbuffer[2][sample])) {
-	    Rast_set_c_null_value(&rowbuffer[0][sample], 1);
-	    Rast_set_c_null_value(&rowbuffer[1][sample], 1);
-	    Rast_set_c_null_value(&rowbuffer[2][sample], 1);
-	    continue;
+for (sample = 0; sample < columns; sample++) {
+
+	if (Rast_is_d_null_value(&rowbuffer[0][sample]) ||
+	    Rast_is_d_null_value(&rowbuffer[1][sample]) ||
+	    Rast_is_d_null_value(&rowbuffer[2][sample])) {
+            Rast_set_d_null_value(&rowbuffer[0][sample], 1);
+            Rast_set_d_null_value(&rowbuffer[1][sample], 1);
+            Rast_set_d_null_value(&rowbuffer[2][sample], 1);
+            continue;
+        }
+
+    /* scale r, g, b to [0.0,1.0] */
+
+	red = rowbuffer[0][sample];
+	red /= max_level;
+
+	green = rowbuffer[1][sample];
+	green /= max_level;
+
+	blue = rowbuffer[2][sample];
+	blue /= max_level;
+
+    /* max of {r,g,b} */
+
+	max = red;
+	if (green > max)
+	    max = green;
+
+	if (blue > max)
+	    max = blue;
+
+    /* min of {r,g,b} */
+	
+    min = red;
+	if (green < min)
+	    min = green;
+	
+    if (blue < min)
+	    min = blue;
+
+    chroma = max - min;
+	intensity = ((max + min) / 2.0);
+
+	/* if min = max, then achromatic -- case R = G = B */
+
+	if (chroma == 0.0) {
+
+	    saturation = 0.0;
+
+        /* undefined -- (how to) set to NULL? */
+        hue = 0.0;
+
+	    rowbuffer[0][sample] = (FCELL)hue;
+	    rowbuffer[1][sample] = (FCELL)intensity;
+	    rowbuffer[2][sample] = (FCELL)saturation;
 	}
 
-	scaler = (double)rowbuffer[0][sample];
-	scaler /= 255.0;
-	scaleg = (double)rowbuffer[1][sample];
-	scaleg /= 255.0;
-	scaleb = (double)rowbuffer[2][sample];
-	scaleb /= 255.0;
+	/*  else chromatic */
 
-	high = scaler;
-	if (scaleg > high)
-	    high = scaleg;
-	if (scaleb > high)
-	    high = scaleb;
-	low = scaler;
-	if (scaleg < low)
-	    low = scaleg;
-	if (scaleb < low)
-	    low = scaleb;
-	/*
-	   calculate the lightness (intensity)
-	 */
-	intens = ((high + low) / 2.0);
-	/*
-	   if min = max the achromatic case R=G=B
-	 */
-	if (high == low) {
-	    sat = 0.0;
-	    /*        hue = -1.0; */
-	    hue = 0.0;
-	    rowbuffer[0][sample] = (unsigned char)hue;
-	    rowbuffer[1][sample] = (unsigned char)(intens * 255.);
-	    rowbuffer[2][sample] = (unsigned char)(sat * 255.);
-	}
-	/*
-	   else chromatic case
-	 */
-	else if (high != low) {
-	    if (intens <= 0.5)
-		sat = (high - low) / (high + low);
-	    else
-		/*
-		   sat = (high-low)/(2 - (high-low));
-		 */
-		sat = (high - low) / (2 - high - low);
-	    red = (high - scaler) / (high - low);
-	    green = (high - scaleg) / (high - low);
-	    blue = (high - scaleb) / (high - low);
-	    /*
-	       resulting color between yellow and magenta
-	     */
-	    if (scaler == high)
-		hue = blue - green;
-	    /*
-	       resulting color between cyan and yellow
-	     */
-	    else if (scaleg == high)
-		hue = 2 + red - blue;
-	    /*
-	       resulting color between magenta and cyan
-	     */
-	    else if (scaleb == high)
-		hue = 4 + green - red;
-	    /*
-	       convert to degrees
-	     */
-	    hue *= 60.0;
-	    /*
-	       make nonnegative
-	     */
+	else if (chroma != 0.0) {
+
+        saturation = chroma / (1 - fabs(2.0 * intensity - 1.0));
+
+	    if (red == max)
+    		hue = fmod(((green - blue) / chroma), 6.0);
+
+	    else if (green == max)
+    		hue = ((blue - red) / chroma) + 2.0;
+
+	    else if (blue == max)
+    		hue = ((red - green) / chroma) + 4.0;
+
+	    /* convert hue to degrees */
+   	    hue *= 60.0;
+
+	    /* make nonnegative */
 	    if (hue < 0.0)
-		hue += 360.0;
-	    /*
-	       set the HIS output values
-	     */
-	    rowbuffer[0][sample] = (unsigned char)(255.0 * hue / 360.0 + 0.5);
-	    rowbuffer[1][sample] = (unsigned char)(intens * 255. + 0.5);
-	    rowbuffer[2][sample] = (unsigned char)(sat * 255. + 0.5);
+    		hue += 360.0;
+
+	    /* HIS output values */
+	    rowbuffer[0][sample] = (FCELL)hue;
+	    rowbuffer[1][sample] = (FCELL)intensity;
+	    rowbuffer[2][sample] = (FCELL)saturation;
 	}
-    }
+  }
 }


More information about the grass-dev mailing list