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