[GRASS-SVN] r69364 - in sandbox/alexandris: . i.rgb.his

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Sep 4 06:55:49 PDT 2016


Author: nikosa
Date: 2016-09-04 06:55:49 -0700 (Sun, 04 Sep 2016)
New Revision: 69364

Added:
   sandbox/alexandris/i.rgb.his/
   sandbox/alexandris/i.rgb.his/Makefile
   sandbox/alexandris/i.rgb.his/closefiles.c
   sandbox/alexandris/i.rgb.his/globals.h
   sandbox/alexandris/i.rgb.his/i.rgb.his.diff
   sandbox/alexandris/i.rgb.his/i.rgb.his.html
   sandbox/alexandris/i.rgb.his/main.c
   sandbox/alexandris/i.rgb.his/openfiles.c
   sandbox/alexandris/i.rgb.his/rgb2his.c
Log:
i.rgb.his (sandbox): rgb to hsl

Added: sandbox/alexandris/i.rgb.his/Makefile
===================================================================
--- sandbox/alexandris/i.rgb.his/Makefile	                        (rev 0)
+++ sandbox/alexandris/i.rgb.his/Makefile	2016-09-04 13:55:49 UTC (rev 69364)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../..
+
+PGM = i.rgb.his
+
+LIBES = $(RASTERLIB) $(GISLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: sandbox/alexandris/i.rgb.his/closefiles.c
===================================================================
--- sandbox/alexandris/i.rgb.his/closefiles.c	                        (rev 0)
+++ sandbox/alexandris/i.rgb.his/closefiles.c	2016-09-04 13:55:49 UTC (rev 69364)
@@ -0,0 +1,67 @@
+#include <stdlib.h>
+#include "globals.h"
+
+/* 
+ * free allocated memory (row buffers),
+ * close raster maps
+ * set color table for output maps to grey scale.
+ */
+
+int closefiles(char *hue, char *saturation, char *lightness,
+               int fd_output[3], DCELL * output_rowbuffer[3])
+{
+    int row;
+    struct Colors colors;
+    struct FPRange range;
+    struct History history;
+    double min;
+    double max;
+    const char *mapset;
+
+    for (row = 0; row < 3; row++) {
+
+        /* free allocated memory */
+        G_free(output_rowbuffer[row]);
+
+        /* close raster maps */
+        Rast_close(fd_output[row]);
+    }
+
+    mapset = G_mapset();
+
+    /* write colors */
+    Rast_read_fp_range(hue, mapset, &range);
+    Rast_get_fp_range_min_max(&range, &min, &max);
+    Rast_make_grey_scale_fp_colors(&colors, min, max);
+    Rast_write_colors(hue, mapset, &colors);
+    G_debug(1, "Wrote color table for %s", hue);
+
+    Rast_read_fp_range(lightness, mapset, &range);
+    Rast_get_fp_range_min_max(&range, &min, &max);
+    Rast_make_grey_scale_fp_colors(&colors, min, max);
+    Rast_write_colors(lightness, mapset, &colors);
+
+    Rast_read_fp_range(saturation, mapset, &range);
+    Rast_get_fp_range_min_max(&range, &min, &max);
+    Rast_make_grey_scale_fp_colors(&colors, min, max);
+    Rast_write_colors(saturation, mapset, &colors);
+
+    /* write metadata */
+    Rast_short_history(hue, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(hue, &history);
+    Rast_put_cell_title(hue, "Image hue");
+    Rast_write_units(hue, "degrees");
+
+    Rast_short_history(lightness, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(lightness, &history);
+    Rast_put_cell_title(lightness, "Image lightness");
+
+    Rast_short_history(saturation, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(saturation, &history);
+    Rast_put_cell_title(saturation, "Image saturation");
+
+    return 0;
+}

Added: sandbox/alexandris/i.rgb.his/globals.h
===================================================================
--- sandbox/alexandris/i.rgb.his/globals.h	                        (rev 0)
+++ sandbox/alexandris/i.rgb.his/globals.h	2016-09-04 13:55:49 UTC (rev 69364)
@@ -0,0 +1,34 @@
+#ifndef __GLOBALS_H__
+#define __GLOBALS_H__
+
+#include <grass/raster.h>
+
+/* 
+ * openfiles.c 
+ * red, green, blue
+ * hue, saturation, intensity (lightness),
+ * input file descriptors, output file descriptors
+ * input rowbuffer
+ */
+void openfiles(char *, char *, char *,
+               char *, char *, char *,
+               int[3], int[3],
+               DCELL *[3]);
+
+/*
+ * rgb2his.c
+ * input rowbuffer, columns, maximum range value
+ */
+void rgb2his(DCELL *[3], int, double);
+
+/* 
+ * closefiles.c
+ * hue, saturation, intensity (lightness)
+ * output file descriptors
+ * output rowbuffers
+ */
+int closefiles(char *, char *, char *,
+               int[3],
+               DCELL *[3]);
+
+#endif /* __GLOBALS_H__ */

Added: sandbox/alexandris/i.rgb.his/i.rgb.his.diff
===================================================================
--- sandbox/alexandris/i.rgb.his/i.rgb.his.diff	                        (rev 0)
+++ sandbox/alexandris/i.rgb.his/i.rgb.his.diff	2016-09-04 13:55:49 UTC (rev 69364)
@@ -0,0 +1,485 @@
+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;
+ 	}
+-    }
++  }
+ }

Added: sandbox/alexandris/i.rgb.his/i.rgb.his.html
===================================================================
--- sandbox/alexandris/i.rgb.his/i.rgb.his.html	                        (rev 0)
+++ sandbox/alexandris/i.rgb.his/i.rgb.his.html	2016-09-04 13:55:49 UTC (rev 69364)
@@ -0,0 +1,26 @@
+<h2>DESCRIPTION</h2>
+
+<em>i.rgb.his</em> is an image processing program that
+processes three input raster map layers as red, green, and
+blue components and produces three output raster map layers
+representing the hue, saturation, and lightness of the
+data.  The output raster map layers are created by a
+standard red-green-blue (RGB) to hue-saturation-lightness
+(HSL) color transformation.  Each output raster map layer
+is given a linear gray scale color table.  The current
+geographic region definition and mask settings are
+respected.
+
+<h2>SEE ALSO</h2>
+
+<em><a href="i.his.rgb.html">i.his.rgb</a></em>
+
+<h2>AUTHOR</h2>
+
+David Satnik, GIS Laboratory, 
+Central Washington University, 
+<br>
+with acknowledgements to Ali Vali, Space Research
+Center, for the core routine. 
+
+<p><i>Last changed: $Date: 2016-01-28 12:21:34 +0100 (Thu, 28 Jan 2016) $</i>

Added: sandbox/alexandris/i.rgb.his/main.c
===================================================================
--- sandbox/alexandris/i.rgb.his/main.c	                        (rev 0)
+++ sandbox/alexandris/i.rgb.his/main.c	2016-09-04 13:55:49 UTC (rev 69364)
@@ -0,0 +1,148 @@
+
+/****************************************************************************
+ *
+ * MODULE:       i.rgb.his
+ *
+ * AUTHOR(S):    David Satnik, GIS Laboratory, Central Washington University
+ *               with acknowledgements to Ali Vali,
+ *               Univ. of Texas Space Research Center, for the core routine. 
+ *
+ *               Nikos Alexandris, UNEP/GRID-Geneva (2016)
+ *               Rewrote for RGB to HSL, using part of Hamish Bowman's diff
+ *               submitted in GRASS-GIS' trac ticket #774
+ *
+ * PURPOSE:      Convert Red-Green-Blue (RGB) to Hue-Saturation-Lightness (HSL)
+ *
+ *               Previously: Red-green-blue (rgb) to hue-lightness-saturation
+ *               (his) raster map color transformation function
+ *
+ * COPYRIGHT:    (C) 2007-2016 by the GRASS Development Team
+ *               (C) 2007-2008 by the GRASS Development Team
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "globals.h"
+
+int main(int argc, char **argv)
+{
+    long row;                                /* long is 32-/64-bit, ~4 billion/~18 qunitillion */
+    int band, rows, cols;                    /* input band counter, number of rows, columns */
+    DCELL *rowbuffer[3];
+    struct Option *opt_red;
+    struct Option *opt_green;
+    struct Option *opt_blue;
+    struct Option *opt_hue;
+    struct Option *opt_saturation;
+    struct Option *opt_lightness;
+    struct Option *opt_bit_depth;
+    struct GModule *module;
+    int fd_input[3];                        /* input file descriptors */
+    int fd_output[3];                       /* output file descriptors */
+    int bit_depth;                          /* bitness of input raster maps */
+    double max_level;                       /* maximum level based on input bitness */
+
+    /* Initialize GIS engine */
+    G_gisinit(argv[0]);
+
+    /* Set description */
+    module = G_define_module();
+    G_add_keyword(_("imagery"));
+    G_add_keyword(_("color transformation"));
+    G_add_keyword("RGB");
+    G_add_keyword("HSL");                   /* Lightness, Luminosity or Luminance */
+    module->description =
+	_("Transforms raster maps from Red-Green-Blue (RGB) color space to "
+	  "Hue-Saturation-Lightness (HSL) color space.");
+
+    /* Define the different options */
+    opt_red = G_define_standard_option(G_OPT_R_INPUT);
+    opt_red->key = "red";
+    opt_red->description = _("Red input raster map");
+
+    opt_green = G_define_standard_option(G_OPT_R_INPUT);
+    opt_green->key = "green";
+    opt_green->description = _("Green input raster map");
+
+    opt_blue = G_define_standard_option(G_OPT_R_INPUT);
+    opt_blue->key = "blue";
+    opt_blue->description = _("Blue input raster map");
+
+    opt_hue = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_hue->key = "hue";
+    opt_hue->description = _("Hue output raster map in degrees [0, 360]");
+
+    opt_saturation = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_saturation->key = "saturation";
+    opt_saturation->description = _("Saturation output raster map in % [0, 1]");
+
+    opt_lightness = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_lightness->key = "lightness";
+    opt_lightness->description = _("Lightness output raster map in % [0, 1]");
+
+    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 = _("Bit depth of input maps");
+
+    if (G_parser(argc, argv))
+        exit(EXIT_FAILURE);
+
+
+    /* bit depth, should be > 0 */
+    bit_depth = atoi(opt_bit_depth->answer);
+    if (bit_depth <= 0)
+        G_fatal_error(_("Invalid bit depth definition!"));
+
+    /* open half ended range for maximum level */
+    max_level = pow(2, bit_depth) - 1.0;
+    G_debug(1, "%d-bit data ranging in [0,%.0f)", bit_depth, max_level);
+
+
+    /* get image dimensions */
+    rows = Rast_window_rows();
+    cols = Rast_window_cols();
+
+    /* open files */
+    openfiles(opt_red->answer, opt_green->answer, opt_blue->answer,
+	          opt_hue->answer, opt_saturation->answer, opt_lightness->answer,
+	          fd_input, fd_output, rowbuffer);
+
+    /* read in maps per row*/
+    for (row = 0; row < rows; row++) {
+        G_percent(row, rows, 2);
+
+        /* loop over input ranster maps */
+        for (band = 0; band < 3; band++)
+            Rast_get_d_row(fd_input[band], rowbuffer[band], row);
+
+            /* process row of band */
+            rgb2his(rowbuffer, cols, max_level);
+
+        /* write new row for band */
+        for (band = 0; band < 3; band++)
+            Rast_put_row(fd_output[band], rowbuffer[band], DCELL_TYPE);
+    }
+
+    /* progress */
+    G_percent(row, rows, 2);
+
+    /* close files */
+    closefiles(opt_hue->answer, opt_saturation->answer, opt_lightness->answer,
+	       fd_output, rowbuffer);
+
+    exit(EXIT_SUCCESS);
+}

Added: sandbox/alexandris/i.rgb.his/openfiles.c
===================================================================
--- sandbox/alexandris/i.rgb.his/openfiles.c	                        (rev 0)
+++ sandbox/alexandris/i.rgb.his/openfiles.c	2016-09-04 13:55:49 UTC (rev 69364)
@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "globals.h"
+
+void openfiles(char *red, char *green, char *blue,
+	       char *hue, char *saturation, char *lightness,
+	       int fd_input[3], int fd_output[3], DCELL * rowbuffer[3])
+{
+    /* declarations */
+    /* const char *mapset;                     /1* mapset name *1/ */
+
+    /* RASTER_MAP_TYPE red_data_type; */
+    /* RASTER_MAP_TYPE green_data_type; */
+    /* RASTER_MAP_TYPE blue_data_type; */
+
+    /* open input files */
+    fd_input[0] = Rast_open_old(red, "");
+    fd_input[1] = Rast_open_old(green, "");
+    fd_input[2] = Rast_open_old(blue, "");
+
+    /* open output files */
+    fd_output[0] = Rast_open_fp_new(hue);
+    fd_output[1] = Rast_open_fp_new(saturation);
+    fd_output[2] = Rast_open_fp_new(lightness);
+
+    /* allocate row buffers */
+    rowbuffer[0] = Rast_allocate_d_buf();
+    rowbuffer[1] = Rast_allocate_d_buf();
+    rowbuffer[2] = Rast_allocate_d_buf();
+    /* how to dynamically set the map type? */
+
+    /* get mapset (NULL if map not found in any mapset) */
+    /* mapset = (char *) G_find_raster2(red, ""); */
+    /* if (mapset == NULL) */
+
+    /*
+     * To Do: replicate an `any` function? */
+     */
+    
+    /*     G_fatal_error(_("Raster map <%s> not found"), red); */
+    /* G_debug(1, "Working in current Mapset which is: %s", mapset); */
+
+    /* determine input raster map type */
+    /* red_data_type = Rast_map_type(red, mapset); */
+    /* G_debug(1, "Red input raster map is of type: %RASTER_MAP_TYPE", red_data_type); */
+
+    /* repeat for green and blue */
+
+    /*
+     *
+
+    /* allocate the cell row buffer */
+    /* rowbuffer[0] = Rast_allocate_buf(red_data_type); */
+    /* rowbuffer[1] = Rast_allocate_buf(green_data_type); */
+    /* rowbuffer[2] = Rast_allocate_buf(blue_data_type); */
+
+}

Added: sandbox/alexandris/i.rgb.his/rgb2his.c
===================================================================
--- sandbox/alexandris/i.rgb.his/rgb2his.c	                        (rev 0)
+++ sandbox/alexandris/i.rgb.his/rgb2his.c	2016-09-04 13:55:49 UTC (rev 69364)
@@ -0,0 +1,124 @@
+
+/******************************************************************************
+NAME:                         RGB2HIS
+ 
+PURPOSE    To process red,green,blue bands to hue
+   Get red, green, blue from input buffer
+   Create the HIS bands
+   Write to output buffer
+ 
+ASSUMPTION:
+   The input images are read to the input buffer.
+ 
+******************************************************************************/
+/* For GRASS one row from each cell map is passed in and each cell in
+   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(DCELL *rowbuffer[3], int columns, double max_level)
+{
+    int column;         /* column indicator               */
+    double red;         /* the red band output            */
+    double green;       /* the green band output          */
+    double blue;        /* the blue band output           */
+    double min;         /* minimum among red, green, blue */
+    double max;         /* maximum among red, green, blue */
+    float chroma;       /* chrome, intermediate value     */
+    float lightness;    /* lightness                      */
+    float saturation;   /* saturation                     */
+    float hue = 0.0L;   /* hue                            */
+
+for (column = 0; column < columns; column++) {
+
+	if (Rast_is_d_null_value(&rowbuffer[0][column]) ||
+	    Rast_is_d_null_value(&rowbuffer[1][column]) ||
+	    Rast_is_d_null_value(&rowbuffer[2][column])) {
+            Rast_set_d_null_value(&rowbuffer[0][column], 1);
+            Rast_set_d_null_value(&rowbuffer[1][column], 1);
+            Rast_set_d_null_value(&rowbuffer[2][column], 1);
+            continue;
+        }
+
+    /* scale r, g, b to [0.0,1.0] */
+
+    red = rowbuffer[0][column];
+    red /= max_level;
+
+    green = rowbuffer[1][column];
+    green /= max_level;
+
+    blue = rowbuffer[2][column];
+    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;
+    lightness = ((max + min) / 2.0);
+
+    /* if R == G == B, then min == max, which is achromatic */
+
+    if (chroma == 0.0) {
+
+        saturation = 0.0;
+
+        /* undefined -- (how to) set to NULL? */
+        hue = 0.0;
+
+        rowbuffer[0][column] = (FCELL)hue;
+        rowbuffer[1][column] = (FCELL)saturation;
+        rowbuffer[2][column] = (FCELL)lightness;
+    }
+
+    /*  else chromatic */
+
+    else if (chroma != 0.0) {
+
+        saturation = chroma / (1.0 - fabs(2.0 * lightness - 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;
+
+        /* HSL output values */
+        rowbuffer[0][column] = (FCELL)hue;
+        rowbuffer[1][column] = (FCELL)saturation;
+        rowbuffer[2][column] = (FCELL)lightness;
+    }
+
+    G_debug(2, "Output rowbuffers 0, 1, 2: %f, %f, %f\n",
+            rowbuffer[0][column], rowbuffer[1][column], rowbuffer[2][column]);
+  }
+}



More information about the grass-commit mailing list