[babl] Add extension with HCY color model, and pixel formats
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [babl] Add extension with HCY color model, and pixel formats
- Date: Tue, 15 Nov 2016 00:12:39 +0000 (UTC)
commit b71dcaaf22b5e36529d8430cb78dcdee49643770
Author: SBP <vorstar mac com>
Date: Fri Nov 11 17:14:38 2016 -0600
Add extension with HCY color model, and pixel formats
extensions/HCY.c | 369 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 369 insertions(+), 0 deletions(-)
---
diff --git a/extensions/HCY.c b/extensions/HCY.c
new file mode 100644
index 0000000..51382ef
--- /dev/null
+++ b/extensions/HCY.c
@@ -0,0 +1,369 @@
+/* babl - dynamically extendable universal pixel conversion library.
+ * Copyright (C) 2016, Sirio Bolaños Puchet <vorstar mac com>
+ *
+ * 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/>.
+ */
+
+ /*
+ * Adding support for HCY colorspace, based on the reference implementation by
+ * Kuzma Shapran (https://code.google.com/archive/p/colour-space-viewer)
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <string.h>
+
+#include "babl.h"
+#include "base/util.h"
+
+/* Rec. 601 as in original code //Rec. 709 */
+#define RGB_LUMA_RED 0.299 //0.2126
+#define RGB_LUMA_GREEN 0.587 //0.7152
+#define RGB_LUMA_BLUE 0.114 //0.0722
+#define EPSILON 1e-10
+
+static long rgba_to_hcya (char *src,
+ char *dst,
+ long samples);
+
+static long hcya_to_rgba (char *src,
+ char *dst,
+ long samples);
+
+static long rgba_to_hcy (char *src,
+ char *dst,
+ long samples);
+
+static long hcy_to_rgba (char *src,
+ char *dst,
+ long samples);
+
+static void rgba_to_hcy_step (char *src,
+ char *dst);
+
+static void hcy_to_rgba_step (char *src,
+ char *dst);
+
+static void components (void);
+static void models (void);
+static void conversions (void);
+static void formats (void);
+
+int init (void);
+
+int
+init (void)
+{
+ components ();
+ models ();
+ conversions ();
+ formats ();
+
+ return 0;
+}
+
+
+static void
+components (void)
+{
+ babl_component_new ("hue", NULL);
+ babl_component_new ("HCY chroma", "chroma", NULL);
+ babl_component_new ("HCY luma", "luma", NULL);
+ babl_component_new ("alpha", NULL);
+}
+
+static void
+models (void)
+{
+ babl_model_new (
+ "name", "HCYA",
+ babl_component ("hue"),
+ babl_component ("HCY chroma"),
+ babl_component ("HCY luma"),
+ babl_component ("alpha"),
+ NULL
+ );
+
+ babl_model_new (
+ "name", "HCY",
+ babl_component ("hue"),
+ babl_component ("HCY chroma"),
+ babl_component ("HCY luma"),
+ NULL
+ );
+}
+
+static void
+conversions (void)
+{
+ babl_conversion_new (
+ babl_model ("RGBA"),
+ babl_model ("HCYA"),
+ "linear", rgba_to_hcya,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_model ("RGBA"),
+ babl_model ("HCY"),
+ "linear", rgba_to_hcy,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_model ("HCYA"),
+ babl_model ("RGBA"),
+ "linear", hcya_to_rgba,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_model ("HCY"),
+ babl_model ("RGBA"),
+ "linear", hcy_to_rgba,
+ NULL
+ );
+}
+
+static void
+formats (void)
+{
+ babl_format_new (
+ "name", "HCYA float",
+ babl_model ("HCYA"),
+ babl_type ("float"),
+ babl_component ("hue"),
+ babl_component ("HCY chroma"),
+ babl_component ("HCY luma"),
+ babl_component ("alpha"),
+ NULL
+ );
+
+ babl_format_new (
+ "name", "HCY float",
+ babl_model ("HCY"),
+ babl_type ("float"),
+ babl_component ("hue"),
+ babl_component ("HCY chroma"),
+ babl_component ("HCY luma"),
+ NULL
+ );
+}
+
+static void
+rgba_to_hcy_step (char *src,
+ char *dst)
+{
+ static const double weights[3] = {RGB_LUMA_RED,RGB_LUMA_GREEN,RGB_LUMA_BLUE};
+ double hue, chroma, luma;
+ double X, Y_peak = 0.;
+ int H_sec = 4, t = -1;
+
+ double rgb[3] = {linear_to_gamma_2_2 (((double *) src)[0]),
+ linear_to_gamma_2_2 (((double *) src)[1]),
+ linear_to_gamma_2_2 (((double *) src)[2])};
+ int ix[3] = {0,1,2};
+
+ if (rgb[0] < rgb[1]) {
+ if (rgb[1] > rgb[2]) {
+ if (rgb[0] < rgb[2]) { ix[1] = 2; ix[2] = 1; H_sec = 2; t = 1; }
+ else { ix[0] = 2; ix[1] = 0; ix[2] = 1; H_sec = 2; }
+ }
+ } else {
+ if (rgb[1] < rgb[2]) {
+ if (rgb[0] < rgb[2]) { ix[0] = 1; ix[1] = 0; H_sec = 4; t = 1; }
+ else { ix[0] = 1; ix[1] = 2; ix[2] = 0; H_sec = 6; }
+ } else { ix[0] = 2; ix[2] = 0; H_sec = 0; t = 1; }
+ }
+
+ luma = weights[0] * rgb[0] + weights[1] * rgb[1] + weights[2] * rgb[2];
+ chroma = rgb[ix[2]] - rgb[ix[0]];
+
+ if (chroma >= EPSILON)
+ {
+ X = (rgb[ix[1]] - rgb[ix[0]]) / chroma;
+
+ Y_peak = weights[ix[2]] + X * weights[ix[1]];
+ if (luma > 0. && luma < 1.)
+ chroma /= luma < Y_peak ? luma/Y_peak : (1. - luma)/(1. - Y_peak);
+
+ hue = (H_sec + t * X) / 6.;
+ }
+ else
+ chroma = hue = 0.0;
+
+ ((double *) dst)[0] = hue;
+ ((double *) dst)[1] = chroma;
+ ((double *) dst)[2] = luma;
+}
+
+static void
+hcy_to_rgba_step (char *src,
+ char *dst)
+{
+ double red, green, blue;
+ double Y_peak = 0., H_insec, X, m;
+ int H_sec;
+
+ double hue = ((double *) src)[0];
+ double chroma = ((double *) src)[1];
+ double luma = ((double *) src)[2];
+
+ if(chroma < EPSILON) {
+ red = green = blue = luma;
+ } else {
+ hue *= 6.;
+ H_sec = (int)hue;
+
+ switch (H_sec)
+ {
+ case 0:
+ H_insec = hue - H_sec;
+ Y_peak = RGB_LUMA_RED + H_insec * RGB_LUMA_GREEN;
+ chroma *= luma < Y_peak ? luma/Y_peak : (1. - luma)/(1. - Y_peak);
+ X = chroma * H_insec;
+ m = luma - (RGB_LUMA_RED * chroma + RGB_LUMA_GREEN * X);
+ red = m + chroma; green = m + X; blue = m;
+ break;
+ case 1:
+ H_insec = 1. - (hue - H_sec);
+ Y_peak = RGB_LUMA_GREEN + H_insec * RGB_LUMA_RED;
+ chroma *= luma < Y_peak ? luma/Y_peak : (1. - luma)/(1. - Y_peak);
+ X = chroma * H_insec;
+ m = luma - (RGB_LUMA_RED * X + RGB_LUMA_GREEN * chroma);
+ red = m + X; green = m + chroma; blue = m;
+ break;
+ case 2:
+ H_insec = hue - H_sec;
+ Y_peak = RGB_LUMA_GREEN + H_insec * RGB_LUMA_BLUE;
+ chroma *= luma < Y_peak ? luma/Y_peak : (1. - luma)/(1. - Y_peak);
+ X = chroma * H_insec;
+ m = luma - (RGB_LUMA_GREEN * chroma + RGB_LUMA_BLUE * X);
+ red = m; green = m + chroma; blue = m + X;
+ break;
+ case 3:
+ H_insec = 1. - (hue - H_sec);
+ Y_peak = RGB_LUMA_BLUE + H_insec * RGB_LUMA_GREEN;
+ chroma *= luma < Y_peak ? luma/Y_peak : (1. - luma)/(1. - Y_peak);
+ X = chroma * H_insec;
+ m = luma - (RGB_LUMA_GREEN * X + RGB_LUMA_BLUE * chroma);
+ red = m; green = m + X; blue = m + chroma;
+ break;
+ case 4:
+ H_insec = hue - H_sec;
+ Y_peak = RGB_LUMA_BLUE + H_insec * RGB_LUMA_RED;
+ chroma *= luma < Y_peak ? luma/Y_peak : (1. - luma)/(1. - Y_peak);
+ X = chroma * H_insec;
+ m = luma - (RGB_LUMA_RED * X + RGB_LUMA_BLUE * chroma);
+ red = m + X; green = m; blue = m + chroma;
+ break;
+ default:
+ H_insec = 1. - (hue - H_sec);
+ Y_peak = RGB_LUMA_RED + H_insec * RGB_LUMA_BLUE;
+ chroma *= luma < Y_peak ? luma/Y_peak : (1. - luma)/(1. - Y_peak);
+ X = chroma * H_insec;
+ m = luma - (RGB_LUMA_RED * chroma + RGB_LUMA_BLUE * X);
+ red = m + chroma; green = m; blue = m + X;
+ break;
+ }
+ }
+
+ ((double *) dst)[0] = gamma_2_2_to_linear (red);
+ ((double *) dst)[1] = gamma_2_2_to_linear (green);
+ ((double *) dst)[2] = gamma_2_2_to_linear (blue);
+}
+
+static long
+rgba_to_hcya (char *src,
+ char *dst,
+ long samples)
+{
+ long n = samples;
+
+ while (n--)
+ {
+ double alpha = ((double *) src)[3];
+
+ rgba_to_hcy_step (src, dst);
+
+ ((double *) dst)[3] = alpha;
+
+ src += 4 * sizeof (double);
+ dst += 4 * sizeof (double);
+ }
+
+ return samples;
+}
+
+static long
+hcya_to_rgba (char *src,
+ char *dst,
+ long samples)
+{
+ long n = samples;
+
+ while (n--)
+ {
+ double alpha = ((double *) src)[3];
+
+ hcy_to_rgba_step (src, dst);
+
+ ((double *) dst)[3] = alpha;
+
+ src += 4 * sizeof (double);
+ dst += 4 * sizeof (double);
+ }
+
+ return samples;
+}
+
+static long
+rgba_to_hcy (char *src,
+ char *dst,
+ long samples)
+{
+ long n = samples;
+
+ while (n--)
+ {
+ rgba_to_hcy_step (src, dst);
+
+ src += 4 * sizeof (double);
+ dst += 3 * sizeof (double);
+ }
+
+ return samples;
+}
+
+static long
+hcy_to_rgba (char *src,
+ char *dst,
+ long samples)
+{
+ long n = samples;
+
+ while (n--)
+ {
+ hcy_to_rgba_step (src, dst);
+
+ ((double *) dst)[3] = 1.0;
+
+ src += 3 * sizeof (double);
+ dst += 4 * sizeof (double);
+ }
+
+ return samples;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]