[GRASS-SVN] r69420 - in sandbox/alexandris: . i.hsl.rgb i.rgb.hsl

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Sep 9 06:07:07 PDT 2016


Author: nikosa
Date: 2016-09-09 06:07:06 -0700 (Fri, 09 Sep 2016)
New Revision: 69420

Added:
   sandbox/alexandris/i.hsl.rgb/
   sandbox/alexandris/i.hsl.rgb/Makefile
   sandbox/alexandris/i.hsl.rgb/close_files.c
   sandbox/alexandris/i.hsl.rgb/globals.h
   sandbox/alexandris/i.hsl.rgb/hsl_to_rgb.c
   sandbox/alexandris/i.hsl.rgb/i.hsl.rgb.html
   sandbox/alexandris/i.hsl.rgb/i.hsl.rgb.md
   sandbox/alexandris/i.hsl.rgb/main.c
   sandbox/alexandris/i.hsl.rgb/open_files.c
   sandbox/alexandris/i.rgb.hsl/
   sandbox/alexandris/i.rgb.hsl/Makefile
   sandbox/alexandris/i.rgb.hsl/close_files.c
   sandbox/alexandris/i.rgb.hsl/globals.h
   sandbox/alexandris/i.rgb.hsl/i.rgb.hsl.html
   sandbox/alexandris/i.rgb.hsl/i.rgb.hsl.md
   sandbox/alexandris/i.rgb.hsl/main.c
   sandbox/alexandris/i.rgb.hsl/open_files.c
   sandbox/alexandris/i.rgb.hsl/rgb_to_hsl.c
Removed:
   sandbox/alexandris/emptyfile
   sandbox/alexandris/i.fusion.hpf/
   sandbox/alexandris/i.rgb.his/
Log:
Added i.rgb.hsl, i.hsl.rgb -- removed i.rgb.his

Deleted: sandbox/alexandris/emptyfile
===================================================================
Added: sandbox/alexandris/i.hsl.rgb/Makefile
===================================================================
--- sandbox/alexandris/i.hsl.rgb/Makefile	                        (rev 0)
+++ sandbox/alexandris/i.hsl.rgb/Makefile	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../..
+
+PGM = i.hsl.rgb
+
+LIBES = $(RASTERLIB) $(GISLIB)
+DEPENDENCIES = $(RASTERDEP) $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: sandbox/alexandris/i.hsl.rgb/close_files.c
===================================================================
--- sandbox/alexandris/i.hsl.rgb/close_files.c	                        (rev 0)
+++ sandbox/alexandris/i.hsl.rgb/close_files.c	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,67 @@
+#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
+   to grey scale.  */
+
+/* 
+ * free allocated memory (row buffers),
+ * close raster maps
+ * set color table for output maps to grey scale.
+ */
+
+int close_files(char *red, char *green, char *blue,
+	       int fd_output[3], DCELL * rowbuffer[3])
+{
+    int row;
+    struct Colors colors;
+    struct FPRange range;
+    struct History history;
+    DCELL min, max;
+    const char *mapset;
+
+    /* free allocated memory, close raster maps */
+    for (row = 0; row < 3; row++) {
+        G_free(rowbuffer[row]);
+        Rast_close(fd_output[row]);
+    }
+
+    mapset = G_mapset();
+
+    /* write colors */
+    Rast_read_fp_range(red, mapset, &range);
+    Rast_get_fp_range_min_max(&range, &min, &max);
+    Rast_make_grey_scale_colors(&colors, min, max);
+    Rast_write_colors(red, mapset, &colors);
+
+    Rast_read_fp_range(green, mapset, &range);
+    Rast_get_fp_range_min_max(&range, &min, &max);
+    Rast_make_grey_scale_colors(&colors, min, max);
+    Rast_write_colors(green, mapset, &colors);
+
+    Rast_read_fp_range(blue, mapset, &range);
+    Rast_get_fp_range_min_max(&range, &min, &max);
+    Rast_make_grey_scale_colors(&colors, min, max);
+    Rast_write_colors(blue, mapset, &colors);
+
+    /* write metadata */
+    Rast_short_history(red, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(red, &history);
+    Rast_put_cell_title(red, "Image red");
+
+    Rast_short_history(green, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(green, &history);
+    Rast_put_cell_title(green, "Image green");
+
+    Rast_short_history(blue, "raster", &history);
+    Rast_command_history(&history);
+    Rast_write_history(blue, &history);
+    Rast_put_cell_title(blue, "Image blue");
+
+    return 0;
+}

Added: sandbox/alexandris/i.hsl.rgb/globals.h
===================================================================
--- sandbox/alexandris/i.hsl.rgb/globals.h	                        (rev 0)
+++ sandbox/alexandris/i.hsl.rgb/globals.h	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,31 @@
+#ifndef __GLOBALS_H__
+#define __GLOBALS_H__
+
+#include <grass/raster.h>
+
+/*
+ * open_files.c
+ * hue, saturation, lightness,
+ * red, green, blue,
+ * int fd_input[3], int fd_output[3],
+ * DCELL * rowbuf[3]
+ */
+void open_files(char *, char *, char *,
+               char *, char *, char *,
+               int[3], int[3],
+               DCELL *[3]);
+
+/* hsl_to_rgb.c */
+void hsl_to_rgb(DCELL *[3], int, double);
+
+/* 
+ * close_files.c
+ * free allocated memory (row buffers),
+ * close raster maps
+ * set color table for output maps to grey scale.
+ */
+int close_files(char *, char *, char *,
+               int[3],
+               DCELL *[3]);
+
+#endif /* __GLOBALS_H__ */

Added: sandbox/alexandris/i.hsl.rgb/hsl_to_rgb.c
===================================================================
--- sandbox/alexandris/i.hsl.rgb/hsl_to_rgb.c	                        (rev 0)
+++ sandbox/alexandris/i.hsl.rgb/hsl_to_rgb.c	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,115 @@
+/*
+ * PURPOSE      Convert hue, saturation and lightness properties of the HSL
+ *                color space model to red, green and blue of the RGB color space
+ *               model
+ */
+
+#include <grass/gis.h>
+#include "globals.h"
+#include <math.h>
+
+void hsl_to_rgb(DCELL *rowbuffer[3], int columns, double max_colors)
+{
+    long column;		/* column indicator                          */
+    double red;			/* the red band output                       */
+    double green;		/* the green band output                     */
+    double blue;		/* the blue band output                      */
+    double chroma;		/* value used for determining RGB            */
+    double intermediate;/* value used for determining RGB            */
+    double baseline_rgb;/* value used for determining RGB            */
+    double lightness;	/* lightness value                           */
+    double saturation;	/* saturation value                          */
+    double hue;			/* hue                                       */
+    double hue60;		/* hue                                       */
+
+    /* loop over columns and appropriately set NULLs */
+    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;
+    }
+
+    /* input HSL color-space properties */
+    hue = rowbuffer[0][column];
+    saturation = rowbuffer[1][column];
+    lightness = rowbuffer[2][column];
+    G_debug(2, "Input Hue, Saturation, Lightness: %f, %f, %f", hue, saturation, lightness);
+
+    /* chroma, hue/60, intermediate `x`, baseline RGB */
+    chroma = (1.0 - fabs(2.0*lightness - 1.0)) * saturation;
+    G_debug(2, "Chroma: %f", chroma);
+
+    hue60 = hue / 60.0;
+    G_debug(2, "Hue/60: %f", hue60);
+
+    intermediate = chroma * (1.0 - fabs( fmod(hue60, 2) - 1.0));
+    G_debug(2, "Intermediate: %f", intermediate);
+
+    baseline_rgb = lightness - 0.5 * chroma;
+    G_debug(2, "Baseline RGB value: %f", baseline_rgb);
+
+    /* conversions */
+    if (hue >= 0.0 && hue < 60.0)
+    {
+        red = chroma;
+        green = intermediate;
+        blue = 0.0;
+    }
+    else if (hue >= 60.0 && hue < 120.0)
+    {
+        red = intermediate;
+        green = chroma;
+        blue = 0.0;
+    }
+    else if (hue >= 120.0 && hue < 180.0)
+    {
+        red = 0.0;
+        green = chroma;
+        blue = intermediate;
+    }
+    else if (hue >= 180.0 && hue < 240.0)
+    {
+        red = 0.0;
+        green = intermediate;
+        blue = chroma;
+    }
+    else if (hue >= 240.0 && hue < 300.0)
+    {
+        red = intermediate;
+        green = 0.0;
+        blue = chroma;
+    }
+    else if (hue >= 300.0 && hue < 360.0)
+    {
+        red = chroma;
+        green = 0.0;
+        blue = intermediate;
+    }
+    else
+    {
+        red = green = blue = 0.0;
+    }
+
+    /* add baseline RGB value*/
+    red += baseline_rgb;
+    green += baseline_rgb;
+    blue += baseline_rgb;
+    G_debug(2, "Red, Green, Blue: %f, %f, %f", red, green, blue);
+
+    /* scale up to requested bitness */
+    red *= max_colors;
+    green *= max_colors;
+    blue *= max_colors;
+    G_debug(2, "Red, Green, Blue [scaled up to]: %f, %f, %f, [%.0f]", red, green, blue, max_colors);
+
+    /* place output row into corresponding buffer */
+    rowbuffer[0][column] = (DCELL) red;
+    rowbuffer[1][column] = (DCELL) green;
+    rowbuffer[2][column] = (DCELL) blue;
+    }
+}

Added: sandbox/alexandris/i.hsl.rgb/i.hsl.rgb.html
===================================================================
--- sandbox/alexandris/i.hsl.rgb/i.hsl.rgb.html	                        (rev 0)
+++ sandbox/alexandris/i.hsl.rgb/i.hsl.rgb.html	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,12 @@
+<h2 id="description">DESCRIPTION</h2>
+<p><em>i.hsl.rgb</em> converts hue, saturation and lightness input images, being dimensions of the HSL color space, into red, green and blue values in the RGB color space. Each output image is given a linear gray scale color table. The current geographic region and mask settings are respected.</p>
+<h2 id="notes">NOTES</h2>
+<ul>
+<li><p>The <em>bits</em> option refers to the bit (or color) depth of the input images, as in bits per color channel. Not to be confused with bits-per-pixel, which refers to the sum of all three color channels. For example, an 8-bit image feaures 256 number of colors. Expecting all input images to be of the same color depth, in example 8 bits, then, an RGB composite would feature 24 bits per pixel.</p></li>
+<li><p>It is possible to process three images with <em>i.hsl.rgb</em> and then recover the original images with <em>i.rgb.hsl</em>.</p></li>
+</ul>
+<h2 id="see-also">SEE ALSO</h2>
+<p><em><a href="i.rgb.his.html">i.rgb.his</a>, <a href="i.his.rgb.html">i.rgb.his</a>, <a href="r.colors.html">r.colors</a></em></p>
+<h2 id="author">AUTHOR</h2>
+<p>Nikos Alexandris</p>
+<p><em>Last changed: $Date: 2016-09-09 13:10:00 +0100 (Fri, 9 Sep 2016) $</em></p>

Added: sandbox/alexandris/i.hsl.rgb/i.hsl.rgb.md
===================================================================
--- sandbox/alexandris/i.hsl.rgb/i.hsl.rgb.md	                        (rev 0)
+++ sandbox/alexandris/i.hsl.rgb/i.hsl.rgb.md	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,34 @@
+DESCRIPTION
+-----------
+
+*i.hsl.rgb* converts hue, saturation and lightness input images, being
+dimensions of the HSL color space, into red, green and blue values in
+the RGB color space. Each output image is given a linear gray scale
+color table. The current geographic region and mask settings are
+respected.
+
+NOTES
+-----
+
+- The *bits* option refers to the bit (or color) depth of the input
+images, as in bits per color channel. Not to be confused with bits-per-pixel,
+which refers to the sum of all three color channels.  For example, an 8-bit
+image feaures 256 number of colors.  Expecting all input images to be of the
+same color depth, in example 8 bits, then, an RGB composite would feature 24
+bits per pixel.
+
+- It is possible to process three images with *i.hsl.rgb* and then recover
+the original images with *i.rgb.hsl*.
+
+SEE ALSO
+--------
+
+*[i.rgb.hsl](i.rgb.hsl.html), [i.rgb.his](i.rgb.his.html), [i.rgb.his](i.his.rgb.html),
+[r.colors](r.colors.html)*
+
+AUTHOR
+------
+
+Nikos Alexandris
+
+*Last changed: \$Date: 2016-09-09 13:10:00 +0100 (Fri, 9 Sep 2016) \$*

Added: sandbox/alexandris/i.hsl.rgb/main.c
===================================================================
--- sandbox/alexandris/i.hsl.rgb/main.c	                        (rev 0)
+++ sandbox/alexandris/i.hsl.rgb/main.c	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,146 @@
+
+/****************************************************************************
+ *
+ * MODULE:      i.hsl.rgb
+ *
+ * AUTHOR(S):   Nikos Alexandris
+ *
+ * PURPOSE:     Color space conversion, HSL to RGB
+ *
+ * COPYRIGHT:   (C) 2016 by Nikos Alexandris and the GRASS Development Team
+ *
+ *              This program is free software under the GNU General
+ *              Public License (>=v2). Read the COPYING file that
+ *              comes with GRASS for details.
+ *
+ * NOTES:       - Reused base code from i.his.rgb and parts from a diff submitted
+ *              in GRASS-GIS' trac ticket #774
+ *              Adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSL
+ *              - Adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSL
+ *              - Also consulted http://dystopiancode.blogspot.ch/2012/06/hsl-rgb-conversion-algorithms-in-c.html
+ *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.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;
+    int rows, cols;
+    DCELL *rowbuffer[3];
+    struct Option *opt_hue;
+    struct Option *opt_saturation;
+    struct Option *opt_lightness;
+    struct Option *opt_red;
+    struct Option *opt_green;
+    struct Option *opt_blue;
+    struct Option *opt_bits;    /* bits per input image, as in bits per channel */
+    struct GModule *module;
+    int fd_input[3];
+    int fd_output[3];
+    int bits;
+    double max_colors;          /* maximum number of colors */
+
+    G_gisinit(argv[0]);
+
+    /* Set description */
+    module = G_define_module();
+    G_add_keyword(_("imagery"));
+    G_add_keyword(_("color space conversion"));
+    G_add_keyword("HSL");
+    G_add_keyword("hue");
+    G_add_keyword("saturation");
+    G_add_keyword("lightness");
+    G_add_keyword("RGB");
+    module->description =
+    ("Converts Hue, Saturation, Lightness (HSL) images to "
+     "Red, Green, Blue (RGB)");
+
+    /* Define the different options */
+    opt_hue = G_define_standard_option(G_OPT_R_INPUT);
+    opt_hue->key = "hue";
+    opt_hue->description = _("Hue input image in degrees [0, 360]");
+
+    opt_saturation = G_define_standard_option(G_OPT_R_INPUT);
+    opt_saturation->key = "saturation";
+    opt_saturation->description = _("Saturation input image ranging in [0, 1]");
+
+    opt_lightness = G_define_standard_option(G_OPT_R_INPUT);
+    opt_lightness->key = "lightness";
+    opt_lightness->description = _("Lightness input image ranging in [0, 1]");
+
+    opt_red = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_red->key = "red";
+    opt_red->description = _("Red output image");
+
+    opt_green = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_green->key = "green";
+    opt_green->description = _("Green output image");
+
+    opt_blue = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_blue->key = "blue";
+    opt_blue->description = _("Blue output image");
+
+    opt_bits = G_define_option();
+    opt_bits->key = "bits";
+    opt_bits->type = TYPE_INTEGER;
+    opt_bits->required = NO;
+    opt_bits->answer = "8";
+    opt_bits->options = "2-16";
+    opt_bits->description = _("Bits per output image");
+
+    if (G_parser(argc, argv))
+        exit(EXIT_FAILURE);
+
+    /* bits per image, should be > 0 */
+    bits = atoi(opt_bits->answer);
+    if (bits <= 0)
+        G_fatal_error(_("Invalid bit depth definition!"));
+
+    /* open half ended range for maximum number of colors */
+    max_colors = pow(2, bits) - 1.0;
+    G_debug(1, "%d-bit data ranging in [0,%.0f)", bits, max_colors);
+
+    /* get image dimensions */
+    rows = Rast_window_rows();
+    cols = Rast_window_cols();
+
+    /* open input and output files */
+    open_files(opt_hue->answer,  opt_saturation->answer, opt_lightness->answer,
+              opt_red->answer, opt_green->answer, opt_blue->answer,
+              fd_input, fd_output, rowbuffer);
+
+    /* loop over hue, saturation and lightness color space properties */
+    for (row = 0; row < rows; row++) {
+        int property;
+
+
+        /* read in row from each cell map */
+        for (property = 0; property < 3; property++)
+            Rast_get_d_row(fd_input[property], rowbuffer[property], row);
+
+            /* process row of image */
+            hsl_to_rgb(rowbuffer, cols, max_colors);
+
+        /* write out the new row for each cell map */
+        for (property = 0; property < 3; property++)
+            Rast_put_row(fd_output[property], rowbuffer[property], DCELL_TYPE);
+    }
+
+    /* progress */
+    G_percent(row, rows, 2);
+
+    /* close output files */
+    close_files(opt_red->answer, opt_green->answer, opt_blue->answer,
+               fd_output, rowbuffer);
+
+    exit(EXIT_SUCCESS);
+}

Added: sandbox/alexandris/i.hsl.rgb/open_files.c
===================================================================
--- sandbox/alexandris/i.hsl.rgb/open_files.c	                        (rev 0)
+++ sandbox/alexandris/i.hsl.rgb/open_files.c	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "globals.h"
+
+/*
+ * hue, saturation, lightness,
+ * red, green, blue,
+ * input file descriptors, output file descriptors,
+ * (input/output?) rowbuffers
+ */
+
+void open_files(char *hue, char *saturation, char *lightness, 
+               char *red, char *green, char *blue,
+               int fd_input[3], int fd_output[3],
+               DCELL * rowbuffer[3])
+{
+    /* open output files */
+    fd_output[0] = Rast_open_fp_new(red);
+    fd_output[1] = Rast_open_fp_new(green);
+    fd_output[2] = Rast_open_fp_new(blue);
+
+    /* allocate the cell row buffer */
+    rowbuffer[0] = Rast_allocate_d_buf();
+    rowbuffer[1] = Rast_allocate_d_buf();
+    rowbuffer[2] = Rast_allocate_d_buf();
+
+    /* open input files (maps can be in different mapsets) */
+    fd_input[0] = Rast_open_old(hue, "");
+    fd_input[1] = Rast_open_old(saturation, "");
+    fd_input[2] = Rast_open_old(lightness, "");
+}

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

Added: sandbox/alexandris/i.rgb.hsl/close_files.c
===================================================================
--- sandbox/alexandris/i.rgb.hsl/close_files.c	                        (rev 0)
+++ sandbox/alexandris/i.rgb.hsl/close_files.c	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,64 @@
+#include <stdlib.h>
+#include "globals.h"
+
+/* 
+ * free allocated memory (row buffers),
+ * close raster maps
+ * set color table for output maps to grey scale.
+ */
+
+int close_files(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;
+
+    /* free allocated memory, close raster maps */
+    for (row = 0; row < 3; row++) {
+        G_free(output_rowbuffer[row]);
+        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.hsl/globals.h
===================================================================
--- sandbox/alexandris/i.rgb.hsl/globals.h	                        (rev 0)
+++ sandbox/alexandris/i.rgb.hsl/globals.h	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,34 @@
+#ifndef __GLOBALS_H__
+#define __GLOBALS_H__
+
+#include <grass/raster.h>
+
+/* 
+ * open_files.c 
+ * red, green, blue
+ * hue, saturation, lightness,
+ * input file descriptors, output file descriptors
+ * input rowbuffer
+ */
+void open_files(char *, char *, char *,
+               char *, char *, char *,
+               int[3], int[3],
+               DCELL *[3]);
+
+/*
+ * rgb_to_hsl.c
+ * input rowbuffer, columns, maximum range value
+ */
+void rgb_to_hsl(DCELL *[3], int, double);
+
+/*
+ * close_files.c
+ * hue, saturation, intensity (lightness)
+ * output file descriptors
+ * output rowbuffers
+ */
+int close_files(char *, char *, char *,
+               int[3],
+               DCELL *[3]);
+
+#endif /* __GLOBALS_H__ */

Added: sandbox/alexandris/i.rgb.hsl/i.rgb.hsl.html
===================================================================
--- sandbox/alexandris/i.rgb.hsl/i.rgb.hsl.html	                        (rev 0)
+++ sandbox/alexandris/i.rgb.hsl/i.rgb.hsl.html	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,30 @@
+<h2 id="description">DESCRIPTION</h2>
+<p><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, intensity, and saturation of the data. The output raster map layers are created by a standard red-green-blue (RGB) to hue-intensity-saturation (HIS) 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.</p>
+<h2 id="examples">EXAMPLES</h2>
+<h2 id="bit">8-bit</h2>
+<p>The digital numbers for the 8-bit Landsat 7 bands red, green and blue, range between 0 and 255:</p>
+<p><code>for BAND in 10 20 30 ;do echo</code>echo -e "Band <span class="math inline">${BAND}: " && r.info -r lsat7_2002_$</span>BAND<code>;done</code></p>
+<pre><code>Band 10: min=42 max=255
+Band 20: min=28 max=255
+Band 30: min=1 max=255</code></pre>
+<p>Coverting these to hue, saturation and lightness:</p>
+<p><code>i.rgb.hsl r=lsat7_2002_30 g=lsat7_2002_20 bl=lsat7_2002_10 hue=h lightness=l saturation=s</code></p>
+<p>The output images range within:</p>
+<p><code>for DIMENSION in h s l; do echo</code>echo "${DIMENSION}:" && r.info -r ${DIMENSION}` ;done</p>
+<pre><code>h: min=0 max=359.434
+s: min=0 max=1
+l: min=0.08431373 max=1</code></pre>
+<p>Note, the <em>bits</em> option is set to 8 by default. Since the input images, in this examele, are 8-bit, there is no need to modify it.</p>
+<p>Converting back to the original RGB color space using <a href="i.hsl.rgb" class="uri">i.hsl.rgb</a>:</p>
+<p><code>i.hsl.rgb hue=h saturation=s lightness=l r=red g=green bl=blue</code></p>
+<p>Confirming that the range of the values of the output images red, green and blue, is identical to the range of the input Landsat 7 bands:</p>
+<p><code>for IMAGE in red green blue ;do echo \</code>echo -e "${IMAGE}: " && r.info -r $IMAGE` ;done`</p>
+<pre><code>red: min=0 max=255
+green: min=28 max=255
+blue: min=42 max=255</code></pre>
+<h2 id="bit-1">16-bit</h2>
+<h2 id="see-also">SEE ALSO</h2>
+<p><em><a href="i.hsl.rgb.html">i.hsl.rgb</a>, <a href="i.rgb.his.html">i.rgb.his</a>, <a href="i.his.rgb.html">i.his.rgb</a>, <a href="r.colors.html">r.colors</a></em></p>
+<h2 id="author">AUTHOR</h2>
+<p>Nikos Alexandris</p>
+<p><em>Last changed: $Date: 2016-01-28 12:21:34 +0100 (Thu, 28 Jan 2016) $</em></p>

Added: sandbox/alexandris/i.rgb.hsl/i.rgb.hsl.md
===================================================================
--- sandbox/alexandris/i.rgb.hsl/i.rgb.hsl.md	                        (rev 0)
+++ sandbox/alexandris/i.rgb.hsl/i.rgb.hsl.md	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,77 @@
+DESCRIPTION
+-----------
+
+*i.rgb.his* 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, intensity, and saturation
+of the data. The output raster map layers are created by a standard
+red-green-blue (RGB) to hue-intensity-saturation (HIS) 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.
+
+EXAMPLES
+--------
+
+## 8-bit
+
+The digital numbers for the 8-bit Landsat 7 bands red, green and blue, range between 0 and 255:
+
+`for BAND in 10 20 30 ;do echo `echo -e "Band ${BAND}: " && r.info -r lsat7_2002_$BAND` ;done`
+
+```
+Band 10: min=42 max=255
+Band 20: min=28 max=255
+Band 30: min=1 max=255
+```
+
+Coverting these to hue, saturation and lightness:
+
+`i.rgb.hsl r=lsat7_2002_30 g=lsat7_2002_20 bl=lsat7_2002_10 hue=h lightness=l saturation=s`
+
+
+The output images range within:
+
+`for DIMENSION in h s l; do echo `echo "${DIMENSION}:" && r.info -r ${DIMENSION}` ;done
+
+```
+h: min=0 max=359.434
+s: min=0 max=1
+l: min=0.08431373 max=1
+```
+
+Note, the <em>bits</em> option is set to 8 by default. Since the input images,
+in this examele, are 8-bit, there is no need to modify it.
+
+Converting back to the original RGB color space using [i.hsl.rgb](i.hsl.rgb):
+
+`i.hsl.rgb hue=h saturation=s lightness=l r=red g=green bl=blue`
+
+Confirming that the range of the values of the output images red, green and
+blue, is identical to the range of the input Landsat 7 bands:
+
+`for IMAGE in red green blue ;do echo \`echo -e "${IMAGE}: " && r.info -r $IMAGE\` ;done`
+
+```
+red: min=0 max=255
+green: min=28 max=255
+blue: min=42 max=255
+```
+
+
+## 16-bit
+
+
+SEE ALSO
+--------
+
+*[i.hsl.rgb](i.hsl.rgb.html), [i.rgb.his](i.rgb.his.html), [i.his.rgb](i.his.rgb.html),
+[r.colors](r.colors.html)*
+
+
+AUTHOR
+------
+
+Nikos Alexandris
+
+*Last changed: \$Date: 2016-01-28 12:21:34 +0100 (Thu, 28 Jan 2016) \$*

Added: sandbox/alexandris/i.rgb.hsl/main.c
===================================================================
--- sandbox/alexandris/i.rgb.hsl/main.c	                        (rev 0)
+++ sandbox/alexandris/i.rgb.hsl/main.c	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,150 @@
+
+/****************************************************************************
+ *
+ * MODULE:      i.rgb.hsl
+ *
+ * AUTHOR(S):   Nikos Alexandris
+ *              submitted in GRASS-GIS' trac ticket #774
+ *
+ * PURPOSE:     Color space conversion, RGB to HSL
+ *
+ * COPYRIGHT:   (C) 2016 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.
+ *
+ * NOTES:       - Reused base code from i.rgb.his and parts from diff submitted
+ *                in GRASS-GIS' trac ticket #774
+ *              - Adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSL
+ *              - Also consulted http://dystopiancode.blogspot.ch/2012/06/hsl-rgb-conversion-algorithms-in-c.html
+ *
+ *****************************************************************************/
+
+#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_bits;
+    struct GModule *module;
+    int fd_input[3];                        /* input file descriptors */
+    int fd_output[3];                       /* output file descriptors */
+    int bits;                          /* bitness of input raster maps */
+    double max_colors;                       /* 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("red");
+    G_add_keyword("green");
+    G_add_keyword("blue");
+    G_add_keyword("HSL");                   /* Lightness, Luminosity or Luminance */
+    G_add_keyword("hue");
+    G_add_keyword("saturation");
+    G_add_keyword("lightness");
+    module->description =
+    ("Converts individual Red, Green and Blue (RGB) images to "
+     "Hue, Saturation and Lightness dimensions in the 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 image");
+
+    opt_green = G_define_standard_option(G_OPT_R_INPUT);
+    opt_green->key = "green";
+    opt_green->description = _("Green input image");
+
+    opt_blue = G_define_standard_option(G_OPT_R_INPUT);
+    opt_blue->key = "blue";
+    opt_blue->description = _("Blue input image");
+
+    opt_hue = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_hue->key = "hue";
+    opt_hue->description = _("Hue output image in degrees [0, 360]");
+
+    opt_saturation = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_saturation->key = "saturation";
+    opt_saturation->description = _("Saturation output image ranging in [0, 1]");
+
+    opt_lightness = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt_lightness->key = "lightness";
+    opt_lightness->description = _("Lightness output image ranging in [0, 1]");
+
+    opt_bits = G_define_option();
+    opt_bits->key = "bits";
+    opt_bits->type = TYPE_INTEGER;
+    opt_bits->required = NO;
+    opt_bits->answer = "8";
+    opt_bits->options = "2-16";
+    opt_bits->description = _("Bits per input image");
+
+    if (G_parser(argc, argv))
+        exit(EXIT_FAILURE);
+
+
+    /* bit depth, should be > 0 */
+    bits = atoi(opt_bits->answer);
+    if (bits <= 0)
+        G_fatal_error(_("Invalid bit depth definition!"));
+
+    /* open half ended range for maximum level */
+    max_colors = pow(2, bits) - 1.0;
+    G_debug(1, "%d-bit data ranging in [0,%.0f)", bits, max_colors);
+
+
+    /* get image dimensions */
+    rows = Rast_window_rows();
+    cols = Rast_window_cols();
+
+    /* open files */
+    open_files(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 image */
+            rgb_to_hsl(rowbuffer, cols, max_colors);
+
+        /* 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 */
+    close_files(opt_hue->answer, opt_saturation->answer, opt_lightness->answer,
+               fd_output, rowbuffer);
+
+    exit(EXIT_SUCCESS);
+}

Added: sandbox/alexandris/i.rgb.hsl/open_files.c
===================================================================
--- sandbox/alexandris/i.rgb.hsl/open_files.c	                        (rev 0)
+++ sandbox/alexandris/i.rgb.hsl/open_files.c	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,64 @@
+#include <stdio.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/glocale.h>
+#include "globals.h"
+
+/*
+ * red, green, blue
+ * hue, saturation, lightness,
+ * input file descriptors, output file descriptors
+ * (input/output?) rowbuffers
+ */
+
+void open_files(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? */
+
+    /*
+     * To Do: replicate an `any` function?
+     */
+
+    /* get mapset (NULL if map not found in any mapset) */
+    /* mapset = (char *) G_find_raster2(red, ""); */
+    /* if (mapset == NULL) */
+    /*     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.hsl/rgb_to_hsl.c
===================================================================
--- sandbox/alexandris/i.rgb.hsl/rgb_to_hsl.c	                        (rev 0)
+++ sandbox/alexandris/i.rgb.hsl/rgb_to_hsl.c	2016-09-09 13:07:06 UTC (rev 69420)
@@ -0,0 +1,135 @@
+/*
+ * PURPOSE      Convert red, green and blue color values into properties of the
+ *              HSL color space model hue, saturation and lightness model
+ */
+
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include "globals.h"
+#include <math.h>
+
+/*
+ * (input/output) rowbuffer
+ * columns
+ * maximum level of range 2^bit_depth
+ */
+
+void rgb_to_hsl(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 and lightness */
+
+    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 hue, set to -1. */
+        hue = -1.0;
+
+    }
+
+    /*  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;
+
+    }
+
+    G_debug(2, "Minimum and Maximum levels among r, g, b: [%f, %f]", min, max);
+    G_debug(2, "Lightness: %f", lightness);
+
+    /* HSL output values */
+
+    /* set hue = -1 to NULL */
+    if (hue == -1.0)
+    {
+        Rast_set_d_null_value(&rowbuffer[0][column], 1);
+    }
+    else
+    {
+        rowbuffer[0][column] = (FCELL)hue;
+    }
+
+    /* set saturation, lightness */
+    rowbuffer[1][column] = (FCELL)saturation;
+    rowbuffer[2][column] = (FCELL)lightness;
+
+    G_debug(3, "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