Unfortunately, there's a little bug in the HSL compose patch, in
gimp_hsl_to_rgb4 in the case of zero saturation. This fixes that.
I'd like to have an option to use luminosity rather than value in
curves and layers; I'm not sure how to do it without introducing
additional complexity.
--- ./libgimpcolor/gimpcolorspace.c~ 2006-06-27 06:33:48.000000000 -0400
+++ ./libgimpcolor/gimpcolorspace.c 2007-01-06 14:57:28.000000000 -0500
@@ -1003,6 +1003,90 @@
}
/**
+ * gimp_rgb_to_hsl4:
+ * @rgb: RGB triplet, rgb[0] is red channel, rgb[1] is green,
+ * rgb[2] is blue (0..255)
+ * @hue: Pointer to hue channel (0..1)
+ * @saturation: Pointer to saturation channel (0..1)
+ * @luma: Pointer to luma channel (0..1)
+ *
+ * Convert an RGB color value to an HSL (Hue, Saturation, Lightness)
+ * color value.
+ *
+ * Since: GIMP 2.4
+ **/
+void
+gimp_rgb_to_hsl4 (const guchar *rgb,
+ gdouble *hue,
+ gdouble *saturation,
+ gdouble *luma)
+{
+ gdouble red, green, blue;
+ gdouble h, s, l;
+ gdouble min, max;
+ gdouble delta;
+
+ red = rgb[0] / 255.0;
+ green = rgb[1] / 255.0;
+ blue = rgb[2] / 255.0;
+
+ h = 0.0; /* Shut up -Wall */
+
+ if (red > green)
+ {
+ max = MAX (red, blue);
+ min = MIN (green, blue);
+ }
+ else
+ {
+ max = MAX (green, blue);
+ min = MIN (red, blue);
+ }
+
+ l = (max + min) / 2.0;
+
+ if (max == min)
+ {
+ s = 0.0;
+ h = GIMP_HSL_UNDEFINED;
+ }
+ else
+ {
+ if (l <= 0.5)
+ s = (max - min) / (max + min);
+ else
+ s = (max - min) / (2.0 - max - min);
+
+ delta = max - min;
+
+ if (delta == 0.0)
+ delta = 1.0;
+
+ if (red == max)
+ {
+ h = (green - blue) / delta;
+ }
+ else if (green == max)
+ {
+ h = 2.0 + (blue - red) / delta;
+ }
+ else if (blue == max)
+ {
+ h = 4.0 + (red - green) / delta;
+ }
+
+ h /= 6.0;
+
+ if (h < 0.0)
+ h += 1.0;
+ }
+
+ *hue = h;
+ *saturation = s;
+ *luma = l;
+}
+
+/**
* gimp_hsv_to_rgb4:
* @rgb: RGB triplet, rgb[0] is red channel, rgb[1] is green,
* rgb[2] is blue (0..255)
@@ -1083,3 +1167,45 @@
rgb[1] = ROUND (saturation * 255.0);
rgb[2] = ROUND (value * 255.0);
}
+
+/**
+ * gimp_hsl_to_rgb4:
+ * @rgb: RGB triplet, rgb[0] is red channel, rgb[1] is green,
+ * rgb[2] is blue (0..255)
+ * @hue: Hue channel (0..1)
+ * @saturation: Saturation channel (0..1)
+ * @luma: Luma channel (0..1)
+ *
+ * Convert an HSL color value (Hue, Saturation, Lightness) to an RGB
+ * color value.
+ *
+ * Since: GIMP 2.4
+ **/
+void
+gimp_hsl_to_rgb4 (guchar *rgb,
+ gdouble hue,
+ gdouble saturation,
+ gdouble luma)
+{
+ if (saturation == 0.0)
+ {
+ rgb[0] = ROUND(luma * 255.0);
+ rgb[1] = ROUND(luma * 255.0);
+ rgb[2] = ROUND(luma * 255.0);
+ }
+ else
+ {
+ gdouble m1, m2;
+
+ if (luma <= 0.5)
+ m2 = luma * (1.0 + saturation);
+ else
+ m2 = luma + saturation - luma * saturation;
+
+ m1 = 2.0 * luma - m2;
+
+ rgb[0] = ROUND (gimp_hsl_value (m1, m2, hue * 6.0 + 2.0) * 255.0);
+ rgb[1] = ROUND (gimp_hsl_value (m1, m2, hue * 6.0) * 255.0);
+ rgb[2] = ROUND (gimp_hsl_value (m1, m2, hue * 6.0 - 2.0) * 255.0);
+ }
+}
--- ./libgimpcolor/gimpcolorspace.h~ 2006-06-27 06:33:48.000000000 -0400
+++ ./libgimpcolor/gimpcolorspace.h 2007-01-06 13:07:47.000000000 -0500
@@ -94,6 +94,14 @@
gdouble hue,
gdouble saturation,
gdouble value);
+void gimp_rgb_to_hsl4 (const guchar *rgb,
+ gdouble *hue,
+ gdouble *saturation,
+ gdouble *luma);
+void gimp_hsl_to_rgb4 (guchar *rgb,
+ gdouble hue,
+ gdouble saturation,
+ gdouble luma);
G_END_DECLS
--- ./libgimpcolor/gimpcolor.def~ 2006-09-01 07:14:32.000000000 -0400
+++ ./libgimpcolor/gimpcolor.def 2007-01-06 14:42:27.000000000 -0500
@@ -18,6 +18,7 @@
gimp_cmyka_set_uchar
gimp_hsl_get_type
gimp_hsl_to_rgb
+ gimp_hsl_to_rgb4
gimp_hsl_to_rgb_int
gimp_hsv_clamp
gimp_hsv_get_type
@@ -55,6 +56,7 @@
gimp_rgb_to_cmyk
gimp_rgb_to_cmyk_int
gimp_rgb_to_hsl
+ gimp_rgb_to_hsl4
gimp_rgb_to_hsl_int
gimp_rgb_to_hsv
gimp_rgb_to_hsv4
--- ./plug-ins/common/decompose.c~ 2006-06-27 06:33:49.000000000 -0400
+++ ./plug-ins/common/decompose.c 2007-01-06 13:31:42.000000000 -0500
@@ -100,12 +100,20 @@
gint bpp, gint numpix, guchar **dst);
static void extract_hsv (const guchar *src,
gint bpp, gint numpix, guchar **dst);
+static void extract_hsl (const guchar *src,
+ gint bpp, gint numpix, guchar **dst);
static void extract_hue (const guchar *src,
gint bpp, gint numpix, guchar **dst);
static void extract_sat (const guchar *src,
gint bpp, gint numpix, guchar **dst);
static void extract_val (const guchar *src,
gint bpp, gint numpix, guchar **dst);
+static void extract_huel (const guchar *src,
+ gint bpp, gint numpix, guchar **dst);
+static void extract_satl (const guchar *src,
+ gint bpp, gint numpix, guchar **dst);
+static void extract_luma (const guchar *src,
+ gint bpp, gint numpix, guchar **dst);
static void extract_cmy (const guchar *src,
gint bpp, gint numpix, guchar **dst);
static void extract_cyan (const guchar *src,
@@ -182,6 +190,15 @@
{ N_("Value"), FALSE, 1, { N_("value") }, extract_val },
+ { N_("HSL"), TRUE, 3, { N_("hue_l"),
+ N_("saturation_l"),
+ N_("luma") }, extract_hsl },
+
+ { N_("Hue (L)"), FALSE, 1, { N_("hue_l") }, extract_huel },
+ { N_("Saturation (L)"), FALSE, 1, { N_("saturation_l") }, extract_satl },
+ { N_("Luma"), FALSE, 1, { N_("luma") }, extract_luma },
+
+
{ N_("CMY"), TRUE, 3, { N_("cyan"),
N_("magenta"),
N_("yellow") }, extract_cmy },
@@ -957,6 +974,90 @@
static void
+extract_hsl (const guchar *src,
+ gint bpp,
+ gint numpix,
+ guchar **dst)
+{
+ register const guchar *rgb_src = src;
+ register guchar *hue_dst = dst[0];
+ register guchar *sat_dst = dst[1];
+ register guchar *lum_dst = dst[2];
+ register gint count = numpix, offset = bpp;
+ gdouble hue, sat, val;
+
+ while (count-- > 0)
+ {
+ gimp_rgb_to_hsl4 (rgb_src, &hue, &sat, &val);
+ *hue_dst++ = (guchar) (hue * 255.999);
+ *sat_dst++ = (guchar) (sat * 255.999);
+ *lum_dst++ = (guchar) (val * 255.999);
+ rgb_src += offset;
+ }
+}
+
+
+static void
+extract_huel (const guchar *src,
+ gint bpp,
+ gint numpix,
+ guchar **dst)
+{
+ register const guchar *rgb_src = src;
+ register guchar *hue_dst = dst[0];
+ register gint count = numpix, offset = bpp;
+ gdouble hue, dummy;
+
+ while (count-- > 0)
+ {
+ gimp_rgb_to_hsl4 (rgb_src, &hue, &dummy, &dummy);
+ *hue_dst++ = (guchar) (hue * 255.999);
+ rgb_src += offset;
+ }
+}
+
+
+static void
+extract_satl (const guchar *src,
+ gint bpp,
+ gint numpix,
+ guchar **dst)
+{
+ register const guchar *rgb_src = src;
+ register guchar *sat_dst = dst[0];
+ register gint count = numpix, offset = bpp;
+ gdouble sat, dummy;
+
+ while (count-- > 0)
+ {
+ gimp_rgb_to_hsl4 (rgb_src, &dummy, &sat, &dummy);
+ *sat_dst++ = (guchar) (sat * 255.999);
+ rgb_src += offset;
+ }
+}
+
+
+static void
+extract_luma (const guchar *src,
+ gint bpp,
+ gint numpix,
+ guchar **dst)
+{
+ register const guchar *rgb_src = src;
+ register guchar *lum_dst = dst[0];
+ register gint count = numpix, offset = bpp;
+ gdouble lum, dummy;
+
+ while (count-- > 0)
+ {
+ gimp_rgb_to_hsl4 (rgb_src, &dummy, &dummy, &lum);
+ *lum_dst++ = (guchar) (lum * 255.999);
+ rgb_src += offset;
+ }
+}
+
+
+static void
extract_cyan (const guchar *src,
gint bpp,
gint numpix,
--- ./plug-ins/common/compose.c~ 2006-09-01 07:14:34.000000000 -0400
+++ ./plug-ins/common/compose.c 2007-01-06 13:08:52.000000000 -0500
@@ -93,6 +93,11 @@
gint numpix,
guchar *dst,
gboolean dst_has_alpha);
+static void compose_hsl (guchar **src,
+ gint *incr,
+ gint numpix,
+ guchar *dst,
+ gboolean dst_has_alpha);
static void compose_cmy (guchar **src,
gint *incr,
gint numpix,
@@ -211,6 +216,14 @@
{ NULL, NULL, NULL, NULL },
"hsv-compose", compose_hsv },
+ { N_("HSL"), 3,
+ { N_("_Hue:"),
+ N_("_Saturation:"),
+ N_("_Luma:"),
+ NULL },
+ { NULL, NULL, NULL, NULL },
+ "hsl-compose", compose_hsl },
+
{ N_("CMY"), 3,
{ N_("_Cyan:"),
N_("_Magenta:"),
@@ -337,7 +350,7 @@
{ GIMP_PDB_IMAGE, "image2", "Second input image" },
{ GIMP_PDB_IMAGE, "image3", "Third input image" },
{ GIMP_PDB_IMAGE, "image4", "Fourth input image" },
- { GIMP_PDB_STRING, "compose-type", "What to compose: RGB, RGBA, HSV, CMY, CMYK" },
+ { GIMP_PDB_STRING, "compose-type", "What to compose: RGB, RGBA, HSV, HSL, CMY, CMYK" },
{ GIMP_PDB_INT8, "value1", "Mask value if image 1 is -1" },
{ GIMP_PDB_INT8, "value2", "Mask value if image 2 is -1" },
{ GIMP_PDB_INT8, "value3", "Mask value if image 3 is -1" },
@@ -357,7 +370,7 @@
{ GIMP_PDB_DRAWABLE, "drawable2", "Second input drawable" },
{ GIMP_PDB_DRAWABLE, "drawable3", "Third input drawable" },
{ GIMP_PDB_DRAWABLE, "drawable4", "Fourth input drawable" },
- { GIMP_PDB_STRING, "compose-type", "What to compose: RGB, RGBA, HSV, CMY, CMYK" },
+ { GIMP_PDB_STRING, "compose-type", "What to compose: RGB, RGBA, HSV, HSL, CMY, CMYK" },
{ GIMP_PDB_INT8, "value1", "Mask value if image 1 is -1" },
{ GIMP_PDB_INT8, "value2", "Mask value if image 2 is -1" },
{ GIMP_PDB_INT8, "value3", "Mask value if image 3 is -1" },
@@ -1035,6 +1048,38 @@
static void
+compose_hsl (guchar **src,
+ gint *incr_src,
+ gint numpix,
+ guchar *dst,
+ gboolean dst_has_alpha)
+{
+ register const guchar *hue_src = src[0];
+ register const guchar *sat_src = src[1];
+ register const guchar *lum_src = src[2];
+ register guchar *rgb_dst = dst;
+ register gint count = numpix;
+ gint hue_incr = incr_src[0];
+ gint sat_incr = incr_src[1];
+ gint lum_incr = incr_src[2];
+
+ while (count-- > 0)
+ {
+ gimp_hsl_to_rgb4 (rgb_dst, (gdouble) *hue_src / 255.0,
+ (gdouble) *sat_src / 255.0,
+ (gdouble) *lum_src / 255.0);
+ rgb_dst += 3;
+ hue_src += hue_incr;
+ sat_src += sat_incr;
+ lum_src += lum_incr;
+
+ if (dst_has_alpha)
+ rgb_dst++;
+ }
+}
+
+
+static void
compose_cmy (guchar **src,
gint *incr_src,
gint numpix,
_______________________________________________
Gimp-developer mailing list
Gimp-developer@xxxxxxxxxxxxxxxxxxxxxx
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer