[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