HSL patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Video For Linux]     [Photo]     [Yosemite News]     [gtk]     [GIMP for Windows]     [KDE]     [GEGL]     [Gimp's Home]     [Gimp on GUI]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux