[babl] extensions: Add the HSL color space
- From: Téo Mazars <teom src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [babl] extensions: Add the HSL color space
- Date: Mon, 24 Jun 2013 21:02:40 +0000 (UTC)
commit 0600fb9a5769556273c6f8c83d0cc5e3fe775e0a
Author: Téo Mazars <teo mazars ensimag fr>
Date: Mon Jun 24 22:55:35 2013 +0200
extensions: Add the HSL color space
Needed at least as legacy
extensions/HSL.c | 286 ++++++++++++++++++++++++++++++++++++++++++++++++
extensions/Makefile.am | 2 +
tests/Makefile.am | 1 +
tests/hsl.c | 111 +++++++++++++++++++
4 files changed, 400 insertions(+), 0 deletions(-)
---
diff --git a/extensions/HSL.c b/extensions/HSL.c
new file mode 100644
index 0000000..5426474
--- /dev/null
+++ b/extensions/HSL.c
@@ -0,0 +1,286 @@
+/* babl - dynamically extendable universal pixel conversion library.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <string.h>
+
+#include "babl.h"
+#include "base/util.h"
+
+#define MIN(a,b) ((a > b) ? b : a)
+#define MAX(a,b) ((a < b) ? b : a)
+
+static long rgba_to_hsla (char *src,
+ char *dst,
+ long samples);
+static long hsla_to_rgba (char *src,
+ char *dst,
+ long samples);
+static long rgba_to_hsl (char *src,
+ char *dst,
+ long samples);
+static long hsl_to_rgba (char *src,
+ char *dst,
+ long samples);
+static void rgb_to_hsl_step (double *src,
+ double *dst);
+static void hsl_to_rgb_step (double *src,
+ double *dst);
+static inline double hue2cpn (double p,
+ double q,
+ double hue);
+int init (void);
+
+
+int
+init (void)
+{
+ babl_component_new ("hue", NULL);
+ babl_component_new ("saturation", NULL);
+ babl_component_new ("lightness", NULL);
+ babl_component_new ("alpha", NULL);
+
+ babl_model_new ("name", "HSLA",
+ babl_component ("hue"),
+ babl_component ("saturation"),
+ babl_component ("lightness"),
+ babl_component ("alpha"),
+ NULL);
+ babl_model_new ("name", "HSL",
+ babl_component ("hue"),
+ babl_component ("saturation"),
+ babl_component ("lightness"),
+ NULL);
+
+
+ babl_conversion_new (babl_model ("RGBA"),
+ babl_model ("HSLA"),
+ "linear", rgba_to_hsla,
+ NULL);
+ babl_conversion_new (babl_model ("RGBA"),
+ babl_model ("HSL"),
+ "linear", rgba_to_hsl,
+ NULL);
+ babl_conversion_new (babl_model ("HSLA"),
+ babl_model ("RGBA"),
+ "linear", hsla_to_rgba,
+ NULL);
+ babl_conversion_new (babl_model ("HSL"),
+ babl_model ("RGBA"),
+ "linear", hsl_to_rgba,
+ NULL);
+
+ babl_format_new ("name", "HSLA float",
+ babl_model ("HSLA"),
+ babl_type ("float"),
+ babl_component ("hue"),
+ babl_component ("saturation"),
+ babl_component ("lightness"),
+ babl_component ("alpha"),
+ NULL);
+ babl_format_new ("name", "HSL float",
+ babl_model ("HSL"),
+ babl_type ("float"),
+ babl_component ("hue"),
+ babl_component ("saturation"),
+ babl_component ("lightness"),
+ NULL);
+ return 0;
+}
+
+
+static inline void
+rgb_to_hsl_step (double* src,
+ double* dst)
+{
+
+ double min, max;
+ double hue, saturation, lightness;
+ int cpn_max;
+
+ double red = linear_to_gamma_2_2 (src[0]);
+ double green = linear_to_gamma_2_2 (src[1]);
+ double blue = linear_to_gamma_2_2 (src[2]);
+
+ max = MAX (red, MAX (green, blue));
+ min = MIN (red, MIN (green, blue));
+
+ if (max == red)
+ cpn_max = 0;
+ else if (max == green)
+ cpn_max = 1;
+ else
+ cpn_max = 2;
+
+ lightness = (max + min) / 2.0;
+
+ if (max == min)
+ {
+ hue = saturation = 0;
+ }
+ else
+ {
+ double diff = max - min;
+ double sum = max + min;
+ saturation = lightness > 0.5 ? diff / (2.0 - sum) : diff / sum;
+ switch (cpn_max)
+ {
+ case 0: hue = (green - blue) / diff + (green < blue ? 6.0 : 0.0); break;
+ case 1: hue = (blue - red) / diff + 2.0; break;
+ case 2: hue = (red - green) / diff + 4.0; break;
+ default: break;
+ }
+ hue /= 6.0;
+ }
+
+ dst[0] = hue;
+ dst[1] = saturation;
+ dst[2] = lightness;
+}
+
+
+static long
+rgba_to_hsla (char *src,
+ char *dst,
+ long samples)
+{
+ long n = samples;
+
+ while (n--)
+ {
+ double alpha = ((double *) src)[3];
+
+ rgb_to_hsl_step ((double *) src, (double *) dst);
+
+ ((double *) dst)[3] = alpha;
+
+ src += 4 * sizeof (double);
+ dst += 4 * sizeof (double);
+ }
+
+ return samples;
+}
+
+
+static long
+rgba_to_hsl (char *src,
+ char *dst,
+ long samples)
+{
+ long n = samples;
+
+ while (n--)
+ {
+ rgb_to_hsl_step ((double *) src, (double *) dst);
+
+ src += 4 * sizeof (double);
+ dst += 3 * sizeof (double);
+ }
+
+ return samples;
+}
+
+
+static inline double
+hue2cpn (double p, double q, double hue)
+{
+ if (hue < 0.0) hue += 1.0;
+ if (hue > 1.0) hue -= 1.0;
+ if (hue < 1.0 / 6.0) return p + (q - p) * 6.0 * hue;
+ if (hue < 1.0 / 2.0) return q;
+ if (hue < 2.0 / 3.0) return p + (q - p) * (2.0 / 3.0 - hue) * 6.0;
+ return p;
+}
+
+
+static void
+hsl_to_rgb_step (double *src,
+ double *dst)
+{
+ double hue = src[0];
+ double saturation = src[1];
+ double lightness = src[2];
+
+ double red = 0, green = 0, blue = 0;
+
+ if (saturation < 1e-7)
+ {
+ red = green = blue = lightness;
+ }
+ else
+ {
+ double q = lightness < 0.5 ?
+ lightness * (1 + saturation) :
+ lightness + saturation - lightness * saturation;
+
+ double p = 2 * lightness - q;
+
+ red = hue2cpn (p, q, hue + 1.0/3.0);
+ green = hue2cpn (p, q, hue);
+ blue = hue2cpn (p, q, hue - 1.0/3.0);
+ }
+
+ dst[0] = gamma_2_2_to_linear (red);
+ dst[1] = gamma_2_2_to_linear (green);
+ dst[2] = gamma_2_2_to_linear (blue);
+}
+
+
+static long
+hsla_to_rgba (char *src,
+ char *dst,
+ long samples)
+{
+ long n = samples;
+
+ while (n--)
+ {
+ double alpha = ((double *) src)[3];
+
+ hsl_to_rgb_step ((double *) src, (double *) dst);
+
+ ((double *) dst)[3] = alpha;
+
+ src += 4 * sizeof (double);
+ dst += 4 * sizeof (double);
+ }
+
+ return samples;
+}
+
+
+static long
+hsl_to_rgba (char *src,
+ char *dst,
+ long samples)
+{
+ long n = samples;
+
+ while (n--)
+ {
+ hsl_to_rgb_step ((double *) src, (double *) dst);
+
+ ((double *) dst)[3] = 1.0;
+
+ src += 3 * sizeof (double);
+ dst += 4 * sizeof (double);
+ }
+
+ return samples;
+}
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index b657117..dca87c0 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -25,6 +25,7 @@ ext_LTLIBRARIES = \
float.la \
fast-float.la \
naive-CMYK.la \
+ HSL.la \
HSV.la \
simple.la \
sse2-float.la \
@@ -41,6 +42,7 @@ gggl_la_SOURCES = gggl.c
gimp_8bit_la_SOURCES = gimp-8bit.c
grey_la_SOURCES = grey.c
naive_CMYK_la_SOURCES = naive-CMYK.c
+HSL_la_SOURCES = HSL.c
HSV_la_SOURCES = HSV.c
sse2_float_la_SOURCES = sse2-float.c
sse2_int8_la_SOURCES = sse2-int8.c
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3a38e51..5f7e5b2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -12,6 +12,7 @@ C_TESTS = \
extract \
floatclamp \
float-to-8bit \
+ hsl \
hsva \
types \
palette \
diff --git a/tests/hsl.c b/tests/hsl.c
new file mode 100644
index 0000000..4b24db2
--- /dev/null
+++ b/tests/hsl.c
@@ -0,0 +1,111 @@
+/* babl - dynamically extendable universal pixel conversion library.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <math.h>
+#include <stdio.h>
+
+#include "config.h"
+#include "babl.h"
+
+#define CHECK_CONV(test_name, componenttype, src_fmt, dst_fmt, src_pix, expected_pix) \
+ { \
+ const Babl *fish; \
+ int i; \
+ fish = babl_fish (src_fmt, dst_fmt); \
+ if (!fish) \
+ { \
+ printf (" %s failed to make fish\n", test_name); \
+ OK = 0; \
+ } \
+ for (i = 0; i < sizeof(src_pix)/sizeof(src_pix[0]); i ++) \
+ { \
+ int c; \
+ componenttype result[10]; \
+ babl_process (fish, src_pix[i], result, 1); \
+ for (c = 0; c < sizeof(expected_pix[i])/sizeof(expected_pix[i][0]); c++) \
+ if (fabs(result[c] - expected_pix[i][c]) > 0.001) \
+ { \
+ printf (" %s failed #%i[%i] got %lf expected %lf\n", \
+ test_name, i, c, result[c], expected_pix[i][c]); \
+ OK = 0; \
+ } \
+ } \
+ }
+
+
+int
+main (int argc,
+ char **argv)
+{
+ int OK = 1;
+
+ float rgba[][4] = {{1.0 , 1.0 , 1.0 , 1.0},
+ {0.214041, 0.214041, 0.214041, 1.0},
+ {0.0 , 0.0 , 0.0 , 1.0},
+ {1.0 , 0.0 , 0.0 , 1.0},
+ {0.522519, 0.522519, 0.0 , 1.0},
+ {0.0 , 0.214041, 0.0 , 1.0},
+ {0.214041, 1.0 , 1.0 , 1.0},
+ {0.214041, 0.214041, 1.0 , 1.0},
+ {0.522520, 0.050876, 0.522521, 1.0},
+ {0.353069, 0.372000, 0.017878, 1.0},
+ {0.052772, 0.010679, 0.823194, 1.0},
+ {0.012693, 0.414530, 0.052934, 1.0},
+ {0.870621, 0.579515, 0.004228, 1.0},
+ {0.453672, 0.029212, 0.781390, 1.0},
+ {0.850554, 0.181933, 0.081839, 1.0},
+ {0.995195, 0.941644, 0.244979, 1.0},
+ {0.009836, 0.595745, 0.308242, 1.0},
+ {0.036595, 0.019338, 0.315257, 1.0},
+ {0.209470, 0.207646, 0.478434, 1.0}};
+
+ float hsla[][4] = {{0.0, 0.0 , 1.0 , 1.0},
+ {0.0, 0.0 , 0.500, 1.0},
+ {0.0, 0.0 , 0.0 , 1.0},
+ {0.0, 1.0 , 0.500, 1.0},
+ {0.166667, 1.0 , 0.375, 1.0},
+ {0.333333, 1.0 , 0.250, 1.0},
+ {0.5, 1.0 , 0.750, 1.0},
+ {0.666666, 1.0 , 0.750, 1.0},
+ {0.833333, 0.500, 0.500, 1.0},
+ {0.171666, 0.638, 0.393, 1.0},
+ {0.6975, 0.832, 0.511, 1.0},
+ {0.374722, 0.707, 0.396, 1.0},
+ {0.1375, 0.893, 0.497, 1.0},
+ {0.788028, 0.775, 0.542, 1.0},
+ {0.039837, 0.817, 0.624, 1.0},
+ {0.158083, 0.991, 0.765, 1.0},
+ {0.451149, 0.779, 0.447, 1.0},
+ {0.689732, 0.601, 0.373, 1.0},
+ {0.668129, 0.290, 0.607, 1.0}};
+
+ babl_init ();
+
+ CHECK_CONV ("rgba to hsla ", float,
+ babl_format ("RGBA float"),
+ babl_format ("HSLA float"),
+ rgba, hsla);
+
+ CHECK_CONV ("hsla to rgba ", float,
+ babl_format ("HSLA float"),
+ babl_format ("RGBA float"),
+ hsla, rgba);
+
+ babl_exit ();
+
+ return !OK;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]