babl: fix some annotation to make the function usable in bindings.
[babl.git] / extensions / CIE.c
blobc9db8b7431ae8ffb42a12904da4a1f0a0acaf252
1 /* babl - dynamically extendable universal pixel conversion library.
2 * Copyright (C) 2005, 2014, 2019 Øyvind Kolås.
3 * Copyright (C) 2009, Martin Nordholts
4 * Copyright (C) 2014, 2019 Elle Stone
5 * Copyright (C) 2017, 2018 Red Hat, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see
19 * <https://www.gnu.org/licenses/>.
22 #include "config.h"
23 #include <math.h>
24 #include <stdint.h>
25 #include <string.h>
27 #if defined(USE_SSE2)
28 #include <emmintrin.h>
29 #endif /* defined(USE_SSE2) */
31 #include "babl-internal.h"
32 #include "extensions/util.h"
34 #define DEGREES_PER_RADIAN (180 / 3.14159265358979323846)
35 #define RADIANS_PER_DEGREE (1 / DEGREES_PER_RADIAN)
36 #define DEGREES_PER_RADIANf (180 / 3.14159265358979323846f)
37 #define RADIANS_PER_DEGREEf (1 / DEGREES_PER_RADIANf)
39 #define LAB_EPSILON (216.0 / 24389.0)
40 #define LAB_EPSILONf (216.0f / 24389.0f)
41 #define LAB_KAPPA (24389.0 / 27.0)
42 #define LAB_KAPPAf (24389.0f / 27.0f)
44 /* The constants below hard-code the D50-adapted sRGB ICC profile
45 * reference white, aka the ICC profile D50 illuminant.
47 * In a properly ICC profile color-managed application, the profile
48 * illuminant values should be retrieved from the image's
49 * ICC profile's illuminant.
51 * At present, the ICC profile illuminant is always D50. This might
52 * change when the next version of the ICC specs is released.
54 * As encoded in an actual V2 or V4 ICC profile,
55 * the illuminant values are hexadecimal-rounded, as are the following
56 * hard-coded D50 ICC profile illuminant values:
59 #define D50_WHITE_REF_X 0.964202880
60 #define D50_WHITE_REF_Y 1.000000000
61 #define D50_WHITE_REF_Z 0.824905400
63 #define D50_WHITE_REF_Xf 0.964202880f
64 #define D50_WHITE_REF_Yf 1.000000000f
65 #define D50_WHITE_REF_Zf 0.824905400f
67 #define NEAR_ZERO 0.0000000001
68 #define NEAR_ZEROf 0.0000000001f
69 #define near_zero(a) ((a) < NEAR_ZERO && (a) > -NEAR_ZERO)
70 #define near_zerof(a) ((a) < NEAR_ZEROf && (a) > -NEAR_ZEROf)
72 #define D50_WHITE_REF_x 0.345702921222f
73 #define D50_WHITE_REF_y 0.358537532290f
76 static void types (void);
77 static void components (void);
78 static void models (void);
79 static void conversions (void);
80 static void formats (void);
82 int init (void);
83 #include "babl-verify-cpu.inc"
85 int
86 init (void)
88 BABL_VERIFY_CPU();
89 types ();
90 components ();
91 models ();
92 formats ();
93 conversions ();
94 return 0;
97 static void
98 components (void)
100 babl_component_new ("CIE L", "doc", "Luminance, range 0.0-100.0 in float", NULL);
101 babl_component_new ("CIE a", "chroma", "doc", "chroma component 0.0 is no saturation", NULL);
102 babl_component_new ("CIE b", "chroma", "doc", "chroma component 0.0 is no saturation", NULL);
103 babl_component_new ("CIE C(ab)", "chroma", "doc", "chrominance/saturation", NULL);
104 babl_component_new ("CIE H(ab)", "chroma", "doc", "hue value range 0.0-360.0", NULL);
105 babl_component_new ("CIE X", NULL);
106 babl_component_new ("CIE Y", NULL);
107 babl_component_new ("CIE Z", NULL);
108 babl_component_new ("CIE x", NULL);
109 babl_component_new ("CIE y", NULL);
110 /* CIE 1976 UCS */
111 babl_component_new ("CIE u", NULL);
112 babl_component_new ("CIE v", NULL);
113 /* babl_component_new ("CIE z", NULL);*/
116 static void
117 models (void)
119 babl_model_new (
120 "name", "CIE Lab",
121 "doc", "CIE Lab color model, a perceptually uniform space, euclidian distance in this space represents delta E.",
122 babl_component ("CIE L"),
123 babl_component ("CIE a"),
124 babl_component ("CIE b"),
125 "CIE",
126 NULL);
128 babl_model_new (
129 "name", "CIE Lab alpha",
130 "doc", "CIE Lab color model, with separate alpha",
131 babl_component ("CIE L"),
132 babl_component ("CIE a"),
133 babl_component ("CIE b"),
134 babl_component ("A"),
135 "CIE",
136 "alpha",
137 NULL);
139 babl_model_new (
140 "name", "CIE LCH(ab)",
141 "doc", "CIE LCH color model, using cylindrical coordinates",
142 babl_component ("CIE L"),
143 babl_component ("CIE C(ab)"),
144 babl_component ("CIE H(ab)"),
145 "CIE",
146 NULL);
148 babl_model_new (
149 "name", "CIE LCH(ab) alpha",
150 "doc", "CIE LCH color model, using cylindrical coordinates, with separate alpha",
151 babl_component ("CIE L"),
152 babl_component ("CIE C(ab)"),
153 babl_component ("CIE H(ab)"),
154 babl_component ("A"),
155 "CIE",
156 "alpha",
157 NULL);
159 babl_model_new (
160 "name", "CIE XYZ",
161 babl_component ("CIE X"),
162 babl_component ("CIE Y"),
163 babl_component ("CIE Z"),
164 "CIE",
165 NULL);
167 babl_model_new (
168 "name", "CIE XYZ alpha",
169 babl_component ("CIE X"),
170 babl_component ("CIE Y"),
171 babl_component ("CIE Z"),
172 babl_component ("A"),
173 "CIE",
174 "alpha",
175 NULL);
177 babl_model_new (
178 "name", "CIE xyY",
179 "doc", "the coordinate system often used for drawing chromaticity diagrams. Y is luminance.",
180 babl_component ("CIE x"),
181 babl_component ("CIE y"),
182 babl_component ("CIE Y"),
183 "CIE",
184 NULL);
186 babl_model_new (
187 "name", "CIE xyY alpha",
188 "doc", "the coordinate system often used for drawing chromaticity diagrams. Y is luminance, with separate alpha",
189 babl_component ("CIE x"),
190 babl_component ("CIE y"),
191 babl_component ("CIE Y"),
192 babl_component ("A"),
193 "CIE",
194 "alpha",
195 NULL);
197 /* CIE 1976 UCS */
198 babl_model_new (
199 "name", "CIE Yuv",
200 "doc", "A newer more perceptually uniform space than xyY for chromaticity diagrams.",
201 babl_component ("CIE Y"),
202 babl_component ("CIE u"),
203 babl_component ("CIE v"),
204 NULL);
206 babl_model_new (
207 "name", "CIE Yuv alpha",
208 "doc", "A newer more perceptually uniform space than xyY for chromaticity diagrams, with separate alpha.",
209 babl_component ("CIE Y"),
210 babl_component ("CIE u"),
211 babl_component ("CIE v"),
212 babl_component ("A"),
213 NULL);
216 static void rgbcie_init (void);
218 /******** begin double RGB/CIE color space conversions ****************/
220 static inline void ab_to_CHab (double a,
221 double b,
222 double *to_C,
223 double *to_H);
225 static inline void CHab_to_ab (double C,
226 double H,
227 double *to_a,
228 double *to_b);
230 static inline void XYZ_to_LAB (double X,
231 double Y,
232 double Z,
233 double *to_L,
234 double *to_a,
235 double *to_b
238 static inline void LAB_to_XYZ (double L,
239 double a,
240 double b,
241 double *to_X,
242 double *to_Y,
243 double *to_Z
246 static inline void XYZ_to_xyY (double X,
247 double Y,
248 double Z,
249 double *to_x,
250 double *to_y,
251 double *to_Y
254 static inline void xyY_to_XYZ (double x,
255 double y,
256 double Y,
257 double *to_X,
258 double *to_Y,
259 double *to_Z
262 /* CIE 1976 UCS */
263 static inline void XYZ_to_Yuv (double X,
264 double Y,
265 double Z,
266 double *to_Y,
267 double *to_u,
268 double *to_v
271 static inline void Yuv_to_XYZ (double Y,
272 double u,
273 double v,
274 double *to_X,
275 double *to_Y,
276 double *to_Z
279 static inline void
280 XYZ_to_LAB (double X,
281 double Y,
282 double Z,
283 double *to_L,
284 double *to_a,
285 double *to_b)
287 double xr = X / D50_WHITE_REF_X;
288 double yr = Y / D50_WHITE_REF_Y;
289 double zr = Z / D50_WHITE_REF_Z;
291 double fx = xr > LAB_EPSILON ? cbrt (xr) : (LAB_KAPPA * xr + 16.0) / 116.0;
292 double fy = yr > LAB_EPSILON ? cbrt (yr) : (LAB_KAPPA * yr + 16.0) / 116.0;
293 double fz = zr > LAB_EPSILON ? cbrt (zr) : (LAB_KAPPA * zr + 16.0) / 116.0;
295 *to_L = 116.0 * fy - 16.0;
296 *to_a = 500.0 * (fx - fy);
297 *to_b = 200.0 * (fy - fz);
300 static inline void
301 LAB_to_XYZ (double L,
302 double a,
303 double b,
304 double *to_X,
305 double *to_Y,
306 double *to_Z)
308 double fy = (L + 16.0) / 116.0;
309 double fy_cubed = fy * fy * fy;
311 double fx = fy + a / 500.0;
312 double fx_cubed = fx * fx * fx;
314 double fz = fy - b / 200.0;
315 double fz_cubed = fz * fz * fz;
317 double yr = L > LAB_KAPPA * LAB_EPSILON ? fy_cubed : L / LAB_KAPPA;
318 double xr = fx_cubed > LAB_EPSILON ? fx_cubed : (fx * 116.0 - 16.0) / LAB_KAPPA;
319 double zr = fz_cubed > LAB_EPSILON ? fz_cubed : (fz * 116.0 - 16.0) / LAB_KAPPA;
321 *to_X = xr * D50_WHITE_REF_X;
322 *to_Y = yr * D50_WHITE_REF_Y;
323 *to_Z = zr * D50_WHITE_REF_Z;
326 /* CIE xyY */
327 static inline void
328 XYZ_to_xyY (double X,
329 double Y,
330 double Z,
331 double *to_x,
332 double *to_y,
333 double *to_Y)
335 double sum = X + Y + Z;
336 if (near_zero (sum))
337 { *to_Y = 0.0;
338 *to_x = D50_WHITE_REF_x;
339 *to_y = D50_WHITE_REF_y;
341 else
343 *to_x = X / sum;
344 *to_y = Y / sum;
345 *to_Y = Y;
349 static inline void
350 xyY_to_XYZ (double x,
351 double y,
352 double Y,
353 double *to_X,
354 double *to_Y,
355 double *to_Z)
357 if (near_zero (Y))
359 *to_X = 0.0;
360 *to_Y = 0.0;
361 *to_Z = 0.0;
363 else
365 *to_X = (x * Y) / y;
366 *to_Y = Y;
367 *to_Z = ((1 - x - y) * Y) / y;
372 /* CIE 1976 UCS */
374 /* Code for near-zero XYZ and RGB for CIE 1976 UCS patterned
375 * after code written by and used with kind permission of Graeme Gill.
376 * Graeme Gill's code is in "icc.c"
377 * downloadable from http://argyllcms.com/ */
379 static inline void
380 XYZ_to_Yuv (double X,
381 double Y,
382 double Z,
383 double *to_Y,
384 double *to_u,
385 double *to_v)
387 double sum = X + (15.0 * Y) + (3.0 * Z);
388 if (near_zero (sum))
390 *to_Y = 0.0;
391 *to_u = 4.0/19.0;
392 *to_v = 9.0/19.0;
394 else
396 *to_Y = Y;
397 *to_u = (4.0 * X) / sum;
398 *to_v = (9.0 * Y) / sum;
402 static inline void
403 Yuv_to_XYZ (double Y,
404 double u,
405 double v,
406 double *to_X,
407 double *to_Y,
408 double *to_Z)
410 if (near_zero (v))
412 *to_X = 0.0;
413 *to_Y = 0.0;
414 *to_Z = 0.0;
416 else
418 *to_X = ((9.0 * u * Y)/(4.0 * v));
419 *to_Y = Y;
420 *to_Z = -(((20.0 * v + 3.0 * u - 12.0) * Y)/(4.0 * v));
424 /* rgb <-> XYZ */
426 static void
427 rgba_to_xyz (const Babl *conversion,
428 char *src,
429 char *dst,
430 long n)
432 const Babl *space = babl_conversion_get_source_space (conversion);
433 while (n--)
435 double RGB[3] = {((double *) src)[0],
436 ((double *) src)[1],
437 ((double *) src)[2] };
438 babl_space_to_xyz (space, RGB, (double*)dst);
440 src += sizeof (double) * 4;
441 dst += sizeof (double) * 3;
445 static void
446 xyz_to_rgba (const Babl *conversion,
447 char *src,
448 char *dst,
449 long n)
451 const Babl *space = babl_conversion_get_destination_space (conversion);
452 while (n--)
454 babl_space_from_xyz (space, (double*)src, (double*) dst);
455 ((double *) dst)[3] = 1.0;
456 src += sizeof (double) * 3;
457 dst += sizeof (double) * 4;
461 static void
462 rgba_to_xyza (const Babl *conversion,char *src,
463 char *dst,
464 long n)
466 const Babl *space = babl_conversion_get_source_space (conversion);
467 while (n--)
469 babl_space_to_xyz (space, (double*)src, (double*)dst);
470 ((double *) dst)[3] = ((double *) src)[3];
472 src += sizeof (double) * 4;
473 dst += sizeof (double) * 4;
477 static void
478 xyza_to_rgba (const Babl *conversion,char *src,
479 char *dst,
480 long n)
482 const Babl *space = babl_conversion_get_destination_space (conversion);
483 while (n--)
485 babl_space_from_xyz (space, (double*)src, (double*) dst);
486 ((double *) dst)[3] = ((double *) src)[3];
488 src += sizeof (double) * 4;
489 dst += sizeof (double) * 4;
494 /* rgb -> xyY */
495 static void
496 rgba_to_xyY (const Babl *conversion,
497 char *src,
498 char *dst,
499 long n)
501 const Babl *space = babl_conversion_get_source_space (conversion);
502 while (n--)
504 double XYZ[3], x, y, Y;
506 babl_space_to_xyz (space, (double*)src, XYZ);
507 XYZ_to_xyY (XYZ[0], XYZ[1], XYZ[2], &x, &y, &Y);
509 ((double *) dst)[0] = x;
510 ((double *) dst)[1] = y;
511 ((double *) dst)[2] = Y;
513 src += sizeof (double) * 4;
514 dst += sizeof (double) * 3;
518 static void
519 rgba_to_xyYa (const Babl *conversion,char *src,
520 char *dst,
521 long n)
523 const Babl *space = babl_conversion_get_source_space (conversion);
524 while (n--)
526 double alpha = ((double *) src)[3];
527 double XYZ[3], x, y, Y;
529 //convert RGB to XYZ
530 babl_space_to_xyz (space, (double*)src, XYZ);
532 //convert XYZ to xyY
533 XYZ_to_xyY (XYZ[0], XYZ[1], XYZ[2], &x, &y, &Y);
535 ((double *) dst)[0] = x;
536 ((double *) dst)[1] = y;
537 ((double *) dst)[2] = Y;
538 ((double *) dst)[3] = alpha;
540 src += sizeof (double) * 4;
541 dst += sizeof (double) * 4;
547 /* rgb -> Yuv */
548 static void
549 rgba_to_Yuv (const Babl *conversion,char *src,
550 char *dst,
551 long n)
553 const Babl *space = babl_conversion_get_source_space (conversion);
554 while (n--)
556 double XYZ[3], Y, u, v;
558 babl_space_to_xyz (space, (double*)src, XYZ);
559 XYZ_to_Yuv (XYZ[0], XYZ[1], XYZ[2], &Y, &u, &v);
561 ((double *) dst)[0] = Y;
562 ((double *) dst)[1] = u;
563 ((double *) dst)[2] = v;
565 src += sizeof (double) * 4;
566 dst += sizeof (double) * 3;
570 static void
571 rgba_to_Yuva (const Babl *conversion,char *src,
572 char *dst,
573 long n)
575 const Babl *space = babl_conversion_get_source_space (conversion);
576 while (n--)
578 double alpha = ((double *) src)[3];
579 double XYZ[3], Y, u, v;
581 //convert RGB to XYZ
582 babl_space_to_xyz (space, (double*)src, XYZ);
584 //convert XYZ to Yuv
585 XYZ_to_Yuv (XYZ[0], XYZ[1], XYZ[2], &Y, &u, &v);
587 ((double *) dst)[0] = Y;
588 ((double *) dst)[1] = u;
589 ((double *) dst)[2] = v;
590 ((double *) dst)[3] = alpha;
592 src += sizeof (double) * 4;
593 dst += sizeof (double) * 4;
598 /* rgbf <->xyYf */
599 static void
600 rgbaf_to_xyYaf (const Babl *conversion,
601 float *src,
602 float *dst,
603 long samples)
605 const Babl *space = babl_conversion_get_source_space (conversion);
606 float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_Xf;
607 float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_Xf;
608 float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_Xf;
609 float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
610 float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
611 float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
612 float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Zf;
613 float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Zf;
614 float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Zf;
615 long n = samples;
617 while (n--)
619 float x, y, X, Y, Z, r, g, b, a;
620 r = src[0];
621 g = src[1];
622 b = src[2];
623 a = src[3];
625 if (near_zerof(r) && near_zerof(g) && near_zerof(b))
627 Y = 0.0f;
628 x = D50_WHITE_REF_x;
629 y = D50_WHITE_REF_y;
631 else
633 X = m_0_0 * r + m_0_1 * g + m_0_2 * b;
634 Y = m_1_0 * r + m_1_1 * g + m_1_2 * b;
635 Z = m_2_0 * r + m_2_1 * g + m_2_2 * b;
637 x = X / (X + Y + Z);
638 y = Y / (X + Y + Z);
641 dst[0] = x;
642 dst[1] = y;
643 dst[2] = Y;
644 dst[3] = a;
646 src += 4;
647 dst += 4;
651 static void
652 rgbf_to_xyYf (const Babl *conversion,float *src,
653 float *dst,
654 long samples)
656 const Babl *space = babl_conversion_get_source_space (conversion);
657 float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_Xf;
658 float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_Xf;
659 float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_Xf;
660 float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
661 float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
662 float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
663 float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Zf;
664 float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Zf;
665 float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Zf;
666 long n = samples;
668 while (n--)
670 float x, y, X, Y, Z, r, g, b;
671 r = src[0];
672 g = src[1];
673 b = src[2];
675 if (near_zerof(r) && near_zerof(g) && near_zerof(b))
677 Y = 0.0f;
678 x = D50_WHITE_REF_x;
679 y = D50_WHITE_REF_y;
681 else
683 X = m_0_0 * r + m_0_1 * g + m_0_2 * b;
684 Y = m_1_0 * r + m_1_1 * g + m_1_2 * b;
685 Z = m_2_0 * r + m_2_1 * g + m_2_2 * b;
687 x = X / (X + Y + Z);
688 y = Y / (X + Y + Z);
691 dst[0] = x;
692 dst[1] = y;
693 dst[2] = Y;
695 src += 3;
696 dst += 3;
701 static void
702 rgbaf_to_xyYf (const Babl *conversion,
703 float *src,
704 float *dst,
705 long samples)
707 const Babl *space = babl_conversion_get_source_space (conversion);
708 float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_Xf;
709 float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_Xf;
710 float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_Xf;
711 float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
712 float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
713 float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
714 float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Zf;
715 float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Zf;
716 float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Zf;
717 long n = samples;
719 while (n--)
721 float x, y, X, Y, Z, r, g, b;
722 r = src[0];
723 g = src[1];
724 b = src[2];
726 if (near_zerof(r) && near_zerof(g) && near_zerof(b))
728 Y = 0.0f;
729 x = D50_WHITE_REF_x;
730 y = D50_WHITE_REF_y;
732 else
734 X = m_0_0 * r + m_0_1 * g + m_0_2 * b;
735 Y = m_1_0 * r + m_1_1 * g + m_1_2 * b;
736 Z = m_2_0 * r + m_2_1 * g + m_2_2 * b;
738 x = X / (X + Y + Z);
739 y = Y / (X + Y + Z);
742 dst[0] = x;
743 dst[1] = y;
744 dst[2] = Y;
746 src += 4;
747 dst += 3;
753 /* rgbf -> Yuv */
754 static void
755 rgbaf_to_Yuvaf (const Babl *conversion,
756 float *src,
757 float *dst,
758 long samples)
760 const Babl *space = babl_conversion_get_source_space (conversion);
761 float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_Xf;
762 float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_Xf;
763 float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_Xf;
764 float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
765 float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
766 float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
767 float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Zf;
768 float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Zf;
769 float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Zf;
770 long n = samples;
772 while (n--)
774 float u, v, X, Y, Z, r, g, b, a, sum;
775 r = src[0];
776 g = src[1];
777 b = src[2];
778 a = src[3];
780 if (near_zerof(r) && near_zerof(g) && near_zerof(b))
782 Y = 0.0f;
783 u = 4.0f/19.0f;
784 v = 9.0f/19.0f;
786 else
788 X = m_0_0 * r + m_0_1 * g + m_0_2 * b;
789 Y = m_1_0 * r + m_1_1 * g + m_1_2 * b;
790 Z = m_2_0 * r + m_2_1 * g + m_2_2 * b;
792 sum = (X + 15.0f * Y + 3.0f * Z);
793 u = (4.0f * X) / sum;
794 v = (9.0f * Y) / sum;
797 dst[0] = Y;
798 dst[1] = u;
799 dst[2] = v;
800 dst[3] = a;
802 src += 4;
803 dst += 4;
807 static void
808 rgbf_to_Yuvf (const Babl *conversion,float *src,
809 float *dst,
810 long samples)
812 const Babl *space = babl_conversion_get_source_space (conversion);
813 float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_Xf;
814 float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_Xf;
815 float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_Xf;
816 float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
817 float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
818 float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
819 float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Zf;
820 float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Zf;
821 float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Zf;
822 long n = samples;
824 while (n--)
826 float u, v, X, Y, Z, r, g, b, sum;
827 r = src[0];
828 g = src[1];
829 b = src[2];
831 if (near_zerof(r) && near_zerof(g) && near_zerof(b))
833 Y = 0.0f;
834 u = 4.0/19.0;
835 v = 9.0/19.0;
837 else
839 X = m_0_0 * r + m_0_1 * g + m_0_2 * b;
840 Y = m_1_0 * r + m_1_1 * g + m_1_2 * b;
841 Z = m_2_0 * r + m_2_1 * g + m_2_2 * b;
843 sum = (X + 15.0f * Y + 3.0f * Z);
844 u = (4.0f * X) / sum;
845 v = (9.0f * Y) / sum;
848 dst[0] = Y;
849 dst[1] = u;
850 dst[2] = v;
852 src += 3;
853 dst += 3;
858 static void
859 rgbaf_to_Yuvf (const Babl *conversion,
860 float *src,
861 float *dst,
862 long samples)
864 const Babl *space = babl_conversion_get_source_space (conversion);
865 float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_Xf;
866 float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_Xf;
867 float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_Xf;
868 float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
869 float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
870 float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
871 float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Zf;
872 float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Zf;
873 float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Zf;
874 long n = samples;
876 while (n--)
878 float u, v, X, Y, Z, r, g, b, sum;
879 r = src[0];
880 g = src[1];
881 b = src[2];
883 if (near_zerof(r) && near_zerof(g) && near_zerof(b))
885 Y = 0.0f;
886 u = 4.0f/19.0f;
887 v = 9.0f/19.0f;
889 else
891 X = m_0_0 * r + m_0_1 * g + m_0_2 * b;
892 Y = m_1_0 * r + m_1_1 * g + m_1_2 * b;
893 Z = m_2_0 * r + m_2_1 * g + m_2_2 * b;
895 sum = (X + 15.0f * Y + 3.0f * Z);
896 u = (4.0f * X) / sum;
897 v = (9.0f * Y) / sum;
900 dst[0] = Y;
901 dst[1] = u;
902 dst[2] = v;
904 src += 4;
905 dst += 3;
912 /* xyY -> rgb */
914 static void
915 xyY_to_rgba (const Babl *conversion,
916 char *src,
917 char *dst,
918 long n)
920 const Babl *space = babl_conversion_get_destination_space (conversion);
921 while (n--)
923 double x = ((double *) src)[0];
924 double y = ((double *) src)[1];
925 double Y = ((double *) src)[2];
927 double R, G, B, X, Z;
929 //convert xyY to XYZ
930 xyY_to_XYZ (x, y, Y, &X, &Y, &Z);
932 //convert XYZ to RGB
934 double XYZ[3] = {X,Y,Z};
935 double RGB[3];
936 babl_space_from_xyz (space, XYZ, RGB);
937 R = RGB[0];
938 G = RGB[1];
939 B = RGB[2];
942 ((double *) dst)[0] = R;
943 ((double *) dst)[1] = G;
944 ((double *) dst)[2] = B;
945 ((double *) dst)[3] = 1.0;
947 src += sizeof (double) * 3;
948 dst += sizeof (double) * 4;
953 static void
954 xyYa_to_rgba (const Babl *conversion,char *src,
955 char *dst,
956 long n)
958 const Babl *space = babl_conversion_get_destination_space (conversion);
959 while (n--)
961 double x = ((double *) src)[0];
962 double y = ((double *) src)[1];
963 double Y = ((double *) src)[2];
964 double alpha = ((double *) src)[3];
966 double X, Z;
968 //convert xyY to XYZ
969 xyY_to_XYZ (x, y, Y, &X, &Y, &Z);
972 //convert XYZ to RGB
973 double XYZ[3] = {X,Y,Z};
974 babl_space_from_xyz (space, XYZ, (double*)dst);
976 ((double *) dst)[3] = alpha;
978 src += sizeof (double) * 4;
979 dst += sizeof (double) * 4;
985 /* Yuv -> rgb */
987 static void
988 Yuv_to_rgba (const Babl *conversion,char *src,
989 char *dst,
990 long n)
992 const Babl *space = babl_conversion_get_destination_space (conversion);
993 while (n--)
995 double Y = ((double *) src)[0];
996 double u = ((double *) src)[1];
997 double v = ((double *) src)[2];
999 double R, G, B, X, Z;
1001 //convert Yuv to XYZ
1002 Yuv_to_XYZ (Y, u, v, &X, &Y, &Z);
1004 //convert XYZ to RGB
1006 double XYZ[3] = {X,Y,Z};
1007 double RGB[3];
1008 babl_space_from_xyz (space, XYZ, RGB);
1009 R = RGB[0];
1010 G = RGB[1];
1011 B = RGB[2];
1014 ((double *) dst)[0] = R;
1015 ((double *) dst)[1] = G;
1016 ((double *) dst)[2] = B;
1017 ((double *) dst)[3] = 1.0;
1019 src += sizeof (double) * 3;
1020 dst += sizeof (double) * 4;
1025 static void
1026 Yuva_to_rgba (const Babl *conversion,char *src,
1027 char *dst,
1028 long n)
1030 const Babl *space = babl_conversion_get_destination_space (conversion);
1031 while (n--)
1033 double Y = ((double *) src)[0];
1034 double u = ((double *) src)[1];
1035 double v = ((double *) src)[2];
1036 double alpha = ((double *) src)[3];
1038 double X, Z;
1040 //convert Yuv to XYZ
1041 Yuv_to_XYZ (Y, u, v, &X, &Y, &Z);
1044 //convert XYZ to RGB
1045 double XYZ[3] = {X,Y,Z};
1046 babl_space_from_xyz (space, XYZ, (double*)dst);
1048 ((double *) dst)[3] = alpha;
1050 src += sizeof (double) * 4;
1051 dst += sizeof (double) * 4;
1056 /* xyYf -> rgbf */
1058 static void
1059 xyYf_to_rgbf (const Babl *conversion,float *src,
1060 float *dst,
1061 long samples)
1063 const Babl *space = babl_conversion_get_source_space (conversion);
1064 float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_Xf;
1065 float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Yf;
1066 float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Zf;
1067 float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_Xf;
1068 float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Yf;
1069 float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Zf;
1070 float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_Xf;
1071 float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Yf;
1072 float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Zf;
1073 long n = samples;
1075 while (n--)
1077 float X, Z, r, g, b;
1078 float x = src[0];
1079 float y = src[1];
1080 float Y = src[2];
1082 if (near_zerof (y))
1084 X = 0.0f;
1085 Y = 0.0f;
1086 Z = 0.0f;
1088 else
1090 X = (x * Y) / y;
1091 //Y = Y;
1092 Z = ((1 - x - y) * Y) / y;
1095 r = m_0_0 * X + m_0_1 * Y + m_0_2 * Z;
1096 g = m_1_0 * X + m_1_1 * Y + m_1_2 * Z;
1097 b = m_2_0 * X + m_2_1 * Y + m_2_2 * Z;
1099 dst[0] = r;
1100 dst[1] = g;
1101 dst[2] = b;
1103 src += 3;
1104 dst += 3;
1110 static void
1111 xyYf_to_rgbaf (const Babl *conversion,
1112 float *src,
1113 float *dst,
1114 long samples)
1116 const Babl *space = babl_conversion_get_source_space (conversion);
1117 float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_Xf;
1118 float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Yf;
1119 float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Zf;
1120 float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_Xf;
1121 float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Yf;
1122 float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Zf;
1123 float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_Xf;
1124 float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Yf;
1125 float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Zf;
1126 long n = samples;
1128 while (n--)
1130 float X, Z, r, g, b;
1131 float x = src[0];
1132 float y = src[1];
1133 float Y = src[2];
1136 if (near_zerof (Y))
1138 X = 0.0f;
1139 Y = 0.0f;
1140 Z = 0.0f;
1142 else
1144 X = (x * Y) / y;
1145 //Y = Y;
1146 Z = ((1 - x - y) * Y) / y;
1149 r = m_0_0 * X + m_0_1 * Y + m_0_2 * Z;
1150 g = m_1_0 * X + m_1_1 * Y + m_1_2 * Z;
1151 b = m_2_0 * X + m_2_1 * Y + m_2_2 * Z;
1153 dst[0] = r;
1154 dst[1] = g;
1155 dst[2] = b;
1156 dst[3] = 1.0f;
1158 src += 3;
1159 dst += 4;
1163 static void
1164 xyYaf_to_rgbaf (const Babl *conversion,
1165 float *src,
1166 float *dst,
1167 long samples)
1169 const Babl *space = babl_conversion_get_source_space (conversion);
1170 float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_Xf;
1171 float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Yf;
1172 float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Zf;
1173 float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_Xf;
1174 float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Yf;
1175 float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Zf;
1176 float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_Xf;
1177 float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Yf;
1178 float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Zf;
1179 long n = samples;
1181 while (n--)
1183 float X, Z, r, g, b;
1184 float x = src[0];
1185 float y = src[1];
1186 float Y = src[2];
1187 float a = src[3];
1189 if (near_zerof (Y))
1191 X = 0.0f;
1192 Y = 0.0f;
1193 Z = 0.0f;
1195 else
1197 X = (x * Y) / y;
1198 //Y = Y;
1199 Z = ((1 - x - y) * Y) / y;
1202 r = m_0_0 * X + m_0_1 * Y + m_0_2 * Z;
1203 g = m_1_0 * X + m_1_1 * Y + m_1_2 * Z;
1204 b = m_2_0 * X + m_2_1 * Y + m_2_2 * Z;
1206 dst[0] = r;
1207 dst[1] = g;
1208 dst[2] = b;
1209 dst[3] = a;
1211 src += 4;
1212 dst += 4;
1218 /* Yuvf -> rgbf */
1220 static void
1221 Yuvf_to_rgbf (const Babl *conversion,float *src,
1222 float *dst,
1223 long samples)
1225 const Babl *space = babl_conversion_get_source_space (conversion);
1226 float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_Xf;
1227 float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Yf;
1228 float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Zf;
1229 float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_Xf;
1230 float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Yf;
1231 float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Zf;
1232 float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_Xf;
1233 float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Yf;
1234 float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Zf;
1235 long n = samples;
1237 while (n--)
1239 float X, Z, r, g, b;
1240 float Y = src[0];
1241 float u = src[1];
1242 float v = src[2];
1244 if (near_zerof (v))
1246 X = 0.0f;
1247 Y = 0.0f;
1248 Z = 0.0f;
1250 else
1252 X = ((9.0f * u * Y)/(4.0f * v));
1253 //Y = Y;
1254 Z = -(((20.0f * v + 3.0f * u - 12.0f) * Y)/(4.0f * v));
1257 r = m_0_0 * X + m_0_1 * Y + m_0_2 * Z;
1258 g = m_1_0 * X + m_1_1 * Y + m_1_2 * Z;
1259 b = m_2_0 * X + m_2_1 * Y + m_2_2 * Z;
1261 dst[0] = r;
1262 dst[1] = g;
1263 dst[2] = b;
1265 src += 3;
1266 dst += 3;
1272 static void
1273 Yuvf_to_rgbaf (const Babl *conversion,
1274 float *src,
1275 float *dst,
1276 long samples)
1278 const Babl *space = babl_conversion_get_source_space (conversion);
1279 float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_Xf;
1280 float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Yf;
1281 float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Zf;
1282 float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_Xf;
1283 float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Yf;
1284 float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Zf;
1285 float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_Xf;
1286 float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Yf;
1287 float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Zf;
1288 long n = samples;
1290 while (n--)
1292 float X, Z, r, g, b;
1293 float Y = src[0];
1294 float u = src[1];
1295 float v = src[2];
1297 if (near_zerof (v))
1299 X = 0.0f;
1300 Y = 0.0f;
1301 Z = 0.0f;
1303 else
1305 X = ((9.0f * u * Y)/(4.0f * v));
1306 //Y = Y;
1307 Z = -(((20.0f * v + 3.0f * u - 12.0f) * Y)/(4.0f * v));
1310 r = m_0_0 * X + m_0_1 * Y + m_0_2 * Z;
1311 g = m_1_0 * X + m_1_1 * Y + m_1_2 * Z;
1312 b = m_2_0 * X + m_2_1 * Y + m_2_2 * Z;
1314 dst[0] = r;
1315 dst[1] = g;
1316 dst[2] = b;
1317 dst[3] = 1.0f;
1319 src += 3;
1320 dst += 4;
1324 static void
1325 Yuvaf_to_rgbaf (const Babl *conversion,
1326 float *src,
1327 float *dst,
1328 long samples)
1330 const Babl *space = babl_conversion_get_source_space (conversion);
1331 float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_Xf;
1332 float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Yf;
1333 float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Zf;
1334 float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_Xf;
1335 float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Yf;
1336 float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Zf;
1337 float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_Xf;
1338 float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Yf;
1339 float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Zf;
1340 long n = samples;
1342 while (n--)
1344 float X, Z, r, g, b;
1345 float Y = src[0];
1346 float u = src[1];
1347 float v = src[2];
1348 float a = src[3];
1350 if (near_zerof (v))
1352 X = 0.0f;
1353 Y = 0.0f;
1354 Z = 0.0f;
1356 else
1358 X = ((9.0f * u * Y)/(4.0f * v));
1359 //Y = Y;
1360 Z = -(((20.0f * v + 3.0f * u - 12.0f) * Y)/(4.0f * v));
1363 r = m_0_0 * X + m_0_1 * Y + m_0_2 * Z;
1364 g = m_1_0 * X + m_1_1 * Y + m_1_2 * Z;
1365 b = m_2_0 * X + m_2_1 * Y + m_2_2 * Z;
1367 dst[0] = r;
1368 dst[1] = g;
1369 dst[2] = b;
1370 dst[3] = a;
1372 src += 4;
1373 dst += 4;
1378 /* rgb <-> LAB */
1380 static void
1381 rgba_to_lab (const Babl *conversion,
1382 char *src,
1383 char *dst,
1384 long n)
1386 const Babl *space = babl_conversion_get_source_space (conversion);
1387 while (n--)
1389 double XYZ[3], L, a, b;
1391 babl_space_to_xyz (space, (double*)src, XYZ);
1392 XYZ_to_LAB (XYZ[0], XYZ[1], XYZ[2], &L, &a, &b);
1394 ((double *) dst)[0] = L;
1395 ((double *) dst)[1] = a;
1396 ((double *) dst)[2] = b;
1398 src += sizeof (double) * 4;
1399 dst += sizeof (double) * 3;
1404 static void
1405 lab_to_rgba (const Babl *conversion,
1406 char *src,
1407 char *dst,
1408 long n)
1410 const Babl *space = babl_conversion_get_destination_space (conversion);
1411 while (n--)
1413 double L = ((double *) src)[0];
1414 double a = ((double *) src)[1];
1415 double b = ((double *) src)[2];
1417 double X, Y, Z, R, G, B;
1419 //convert Lab to XYZ
1420 LAB_to_XYZ (L, a, b, &X, &Y, &Z);
1422 //convert XYZ to RGB
1424 double XYZ[3] = {X,Y,Z};
1425 double RGB[3];
1426 babl_space_from_xyz (space, XYZ, RGB);
1427 R = RGB[0];
1428 G = RGB[1];
1429 B = RGB[2];
1432 ((double *) dst)[0] = R;
1433 ((double *) dst)[1] = G;
1434 ((double *) dst)[2] = B;
1435 ((double *) dst)[3] = 1.0;
1437 src += sizeof (double) * 3;
1438 dst += sizeof (double) * 4;
1442 static void
1443 rgba_to_laba (const Babl *conversion,
1444 char *src,
1445 char *dst,
1446 long n)
1448 const Babl *space = babl_conversion_get_source_space (conversion);
1449 while (n--)
1451 double alpha = ((double *) src)[3];
1452 double XYZ[3], L, a, b;
1454 //convert RGB to XYZ
1455 babl_space_to_xyz (space, (double*)src, XYZ);
1457 //convert XYZ to Lab
1458 XYZ_to_LAB (XYZ[0], XYZ[1], XYZ[2], &L, &a, &b);
1460 ((double *) dst)[0] = L;
1461 ((double *) dst)[1] = a;
1462 ((double *) dst)[2] = b;
1463 ((double *) dst)[3] = alpha;
1465 src += sizeof (double) * 4;
1466 dst += sizeof (double) * 4;
1470 static void
1471 laba_to_rgba (const Babl *conversion,
1472 char *src,
1473 char *dst,
1474 long n)
1476 const Babl *space = babl_conversion_get_destination_space (conversion);
1477 while (n--)
1479 double L = ((double *) src)[0];
1480 double a = ((double *) src)[1];
1481 double b = ((double *) src)[2];
1482 double alpha = ((double *) src)[3];
1484 double X, Y, Z;
1486 //convert Lab to XYZ
1487 LAB_to_XYZ (L, a, b, &X, &Y, &Z);
1490 //convert XYZ to RGB
1491 double XYZ[3] = {X,Y,Z};
1492 babl_space_from_xyz (space, XYZ, (double*)dst);
1494 ((double *) dst)[3] = alpha;
1496 src += sizeof (double) * 4;
1497 dst += sizeof (double) * 4;
1502 /* rgb <-> LCh */
1504 static inline void
1505 CHab_to_ab (double C,
1506 double H,
1507 double *to_a,
1508 double *to_b)
1510 *to_a = cos (H * RADIANS_PER_DEGREE) * C;
1511 *to_b = sin (H * RADIANS_PER_DEGREE) * C;
1514 static inline void
1515 ab_to_CHab (double a,
1516 double b,
1517 double *to_C,
1518 double *to_H)
1520 *to_C = sqrt ( (a * a) + (b * b) );
1521 *to_H = atan2 (b, a) * DEGREES_PER_RADIAN;
1523 // Keep H within the range 0-360
1524 if (*to_H < 0.0)
1525 *to_H += 360;
1528 static void
1529 rgba_to_lchab (const Babl *conversion,
1530 char *src,
1531 char *dst,
1532 long n)
1534 const Babl *space = babl_conversion_get_source_space (conversion);
1536 while (n--)
1538 double XYZ[3], L, a, b, C, H;
1540 //convert RGB to XYZ
1541 babl_space_to_xyz (space, (double *)src, XYZ);
1543 //convert XYZ to Lab
1544 XYZ_to_LAB (XYZ[0], XYZ[1], XYZ[2], &L, &a, &b);
1547 //convert Lab to LCH(ab)
1548 ab_to_CHab (a, b, &C, &H);
1550 ((double *) dst)[0] = L;
1551 ((double *) dst)[1] = C;
1552 ((double *) dst)[2] = H;
1554 src += sizeof (double) * 4;
1555 dst += sizeof (double) * 3;
1559 static void
1560 lchab_to_rgba (const Babl *conversion,
1561 char *src,
1562 char *dst,
1563 long n)
1565 const Babl *space = babl_conversion_get_source_space (conversion);
1567 while (n--)
1569 double L = ((double *) src)[0];
1570 double C = ((double *) src)[1];
1571 double H = ((double *) src)[2];
1572 double a, b, X, Y, Z;
1574 //Convert LCH(ab) to Lab
1575 CHab_to_ab (C, H, &a, &b);
1577 //Convert LAB to XYZ
1578 LAB_to_XYZ (L, a, b, &X, &Y, &Z);
1580 //Convert XYZ to RGB
1582 double XYZ[3] = {X,Y,Z};
1583 babl_space_from_xyz (space, XYZ, (double*)dst);
1586 ((double *) dst)[3] = 1.0;
1588 src += sizeof (double) * 3;
1589 dst += sizeof (double) * 4;
1593 static void
1594 rgba_to_lchaba (const Babl *conversion,
1595 char *src,
1596 char *dst,
1597 long n)
1599 const Babl *space = babl_conversion_get_source_space (conversion);
1601 while (n--)
1603 double alpha = ((double *) src)[3];
1604 double XYZ[3], L, a, b, C, H;
1606 //convert RGB to XYZ
1607 babl_space_to_xyz (space, (double*)src, XYZ);
1609 //convert XYZ to Lab
1610 XYZ_to_LAB (XYZ[0], XYZ[1], XYZ[2], &L, &a, &b);
1612 //convert Lab to LCH(ab)
1613 ab_to_CHab (a, b, &C, &H);
1615 ((double *) dst)[0] = L;
1616 ((double *) dst)[1] = C;
1617 ((double *) dst)[2] = H;
1618 ((double *) dst)[3] = alpha;
1620 src += sizeof (double) * 4;
1621 dst += sizeof (double) * 4;
1625 static void
1626 lchaba_to_rgba (const Babl *conversion,
1627 char *src,
1628 char *dst,
1629 long n)
1631 const Babl *space = babl_conversion_get_destination_space (conversion);
1632 while (n--)
1634 double L = ((double *) src)[0];
1635 double C = ((double *) src)[1];
1636 double H = ((double *) src)[2];
1637 double alpha = ((double *) src)[3];
1638 double a, b, X, Y, Z;
1640 //Convert LCH(ab) to Lab
1641 CHab_to_ab (C, H, &a, &b);
1643 //Convert Lab to XYZ
1644 LAB_to_XYZ (L, a, b, &X, &Y, &Z);
1646 //Convert XYZ to RGB
1648 double XYZ[3] = {X,Y,Z};
1649 babl_space_from_xyz (space, XYZ, (double*)dst);
1651 ((double *) dst)[3] = alpha;
1653 src += sizeof (double) * 4;
1654 dst += sizeof (double) * 4;
1659 /******** end double RGB/CIE color space conversions ******************/
1661 /******** begin floating point RGB/CIE color space conversions ********/
1663 /* origin: http://www.hackersdelight.org/hdcodetxt/acbrt.c.txt
1664 * permissions: http://www.hackersdelight.org/permissions.htm
1666 /* _cbrtf(x)
1667 * Return cube root of x
1670 static inline float
1671 _cbrtf (float x)
1673 union { float f; uint32_t i; } u = { x };
1675 u.i = u.i / 4 + u.i / 16;
1676 u.i = u.i + u.i / 16;
1677 u.i = u.i + u.i / 256;
1678 u.i = 0x2a5137a0 + u.i;
1679 u.f = 0.33333333f * (2.0f * u.f + x / (u.f * u.f));
1680 u.f = 0.33333333f * (2.0f * u.f + x / (u.f * u.f));
1682 return u.f;
1685 static inline float
1686 cubef (float f)
1688 return f * f * f;
1691 static void
1692 Yf_to_Lf (const Babl *conversion,
1693 float *src,
1694 float *dst,
1695 long samples)
1697 long n = samples;
1699 while (n--)
1701 float yr = src[0];
1702 float L = yr > LAB_EPSILONf ? 116.0f * _cbrtf (yr) - 16 : LAB_KAPPAf * yr;
1704 dst[0] = L;
1706 src++;
1707 dst++;
1711 static void
1712 Yaf_to_Lf (const Babl *conversion,
1713 float *src,
1714 float *dst,
1715 long samples)
1717 long n = samples;
1719 while (n--)
1721 float yr = src[0];
1722 float L = yr > LAB_EPSILONf ? 116.0f * _cbrtf (yr) - 16 : LAB_KAPPAf * yr;
1724 dst[0] = L;
1726 src += 2;
1727 dst += 1;
1731 static void
1732 Yaf_to_Laf (const Babl *conversion,
1733 float *src,
1734 float *dst,
1735 long samples)
1737 long n = samples;
1739 while (n--)
1741 float yr = src[0];
1742 float a = src[1];
1743 float L = yr > LAB_EPSILONf ? 116.0f * _cbrtf (yr) - 16 : LAB_KAPPAf * yr;
1745 dst[0] = L;
1746 dst[1] = a;
1748 src += 2;
1749 dst += 2;
1753 static void
1754 rgbf_to_Labf (const Babl *conversion,
1755 float *src,
1756 float *dst,
1757 long samples)
1759 const Babl *space = babl_conversion_get_source_space (conversion);
1760 float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_Xf;
1761 float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_Xf;
1762 float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_Xf;
1763 float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
1764 float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
1765 float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
1766 float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Zf;
1767 float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Zf;
1768 float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Zf;
1769 long n = samples;
1771 while (n--)
1773 float r = src[0];
1774 float g = src[1];
1775 float b = src[2];
1777 float xr = m_0_0 * r + m_0_1 * g + m_0_2 * b;
1778 float yr = m_1_0 * r + m_1_1 * g + m_1_2 * b;
1779 float zr = m_2_0 * r + m_2_1 * g + m_2_2 * b;
1781 float fx = xr > LAB_EPSILONf ? _cbrtf (xr) : (LAB_KAPPAf * xr + 16.0f) / 116.0f;
1782 float fy = yr > LAB_EPSILONf ? _cbrtf (yr) : (LAB_KAPPAf * yr + 16.0f) / 116.0f;
1783 float fz = zr > LAB_EPSILONf ? _cbrtf (zr) : (LAB_KAPPAf * zr + 16.0f) / 116.0f;
1785 float L = 116.0f * fy - 16.0f;
1786 float A = 500.0f * (fx - fy);
1787 float B = 200.0f * (fy - fz);
1789 dst[0] = L;
1790 dst[1] = A;
1791 dst[2] = B;
1793 src += 3;
1794 dst += 3;
1798 static void
1799 rgbaf_to_Lf (const Babl *conversion,
1800 float *src,
1801 float *dst,
1802 long samples)
1804 const Babl *space = babl_conversion_get_source_space (conversion);
1805 float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
1806 float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
1807 float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
1808 long n = samples;
1810 while (n--)
1812 float r = src[0];
1813 float g = src[1];
1814 float b = src[2];
1816 float yr = m_1_0 * r + m_1_1 * g + m_1_2 * b;
1817 float L = yr > LAB_EPSILONf ? 116.0f * _cbrtf (yr) - 16 : LAB_KAPPAf * yr;
1819 dst[0] = L;
1821 src += 4;
1822 dst += 1;
1826 static void
1827 rgbaf_to_Labf (const Babl *conversion,
1828 float *src,
1829 float *dst,
1830 long samples)
1832 const Babl *space = babl_conversion_get_source_space (conversion);
1833 float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_Xf;
1834 float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_Xf;
1835 float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_Xf;
1836 float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
1837 float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
1838 float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
1839 float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Zf;
1840 float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Zf;
1841 float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Zf;
1842 long n = samples;
1844 while (n--)
1846 float r = src[0];
1847 float g = src[1];
1848 float b = src[2];
1850 float xr = m_0_0 * r + m_0_1 * g + m_0_2 * b;
1851 float yr = m_1_0 * r + m_1_1 * g + m_1_2 * b;
1852 float zr = m_2_0 * r + m_2_1 * g + m_2_2 * b;
1854 float fx = xr > LAB_EPSILONf ? _cbrtf (xr) : (LAB_KAPPAf * xr + 16.0f) / 116.0f;
1855 float fy = yr > LAB_EPSILONf ? _cbrtf (yr) : (LAB_KAPPAf * yr + 16.0f) / 116.0f;
1856 float fz = zr > LAB_EPSILONf ? _cbrtf (zr) : (LAB_KAPPAf * zr + 16.0f) / 116.0f;
1858 float L = 116.0f * fy - 16.0f;
1859 float A = 500.0f * (fx - fy);
1860 float B = 200.0f * (fy - fz);
1862 dst[0] = L;
1863 dst[1] = A;
1864 dst[2] = B;
1866 src += 4;
1867 dst += 3;
1871 static void
1872 rgbaf_to_Labaf (const Babl *conversion,
1873 float *src,
1874 float *dst,
1875 long samples)
1877 const Babl *space = babl_conversion_get_source_space (conversion);
1878 float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_Xf;
1879 float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_Xf;
1880 float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_Xf;
1881 float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
1882 float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
1883 float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
1884 float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Zf;
1885 float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Zf;
1886 float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Zf;
1887 long n = samples;
1889 while (n--)
1891 float r = src[0];
1892 float g = src[1];
1893 float b = src[2];
1894 float a = src[3];
1896 float xr = m_0_0 * r + m_0_1 * g + m_0_2 * b;
1897 float yr = m_1_0 * r + m_1_1 * g + m_1_2 * b;
1898 float zr = m_2_0 * r + m_2_1 * g + m_2_2 * b;
1900 float fx = xr > LAB_EPSILONf ? _cbrtf (xr) : (LAB_KAPPAf * xr + 16.0f) / 116.0f;
1901 float fy = yr > LAB_EPSILONf ? _cbrtf (yr) : (LAB_KAPPAf * yr + 16.0f) / 116.0f;
1902 float fz = zr > LAB_EPSILONf ? _cbrtf (zr) : (LAB_KAPPAf * zr + 16.0f) / 116.0f;
1904 float L = 116.0f * fy - 16.0f;
1905 float A = 500.0f * (fx - fy);
1906 float B = 200.0f * (fy - fz);
1908 dst[0] = L;
1909 dst[1] = A;
1910 dst[2] = B;
1911 dst[3] = a;
1913 src += 4;
1914 dst += 4;
1918 static void
1919 Labf_to_Lf (const Babl *conversion,
1920 float *src,
1921 float *dst,
1922 long samples)
1924 long n = samples;
1926 while (n--)
1928 dst[0] = src[0];
1930 src += 3;
1931 dst += 1;
1935 static void
1936 Labaf_to_Lf (const Babl *conversion,
1937 float *src,
1938 float *dst,
1939 long samples)
1941 long n = samples;
1943 while (n--)
1945 dst[0] = src[0];
1947 src += 4;
1948 dst += 1;
1952 static void
1953 Labf_to_rgbf (const Babl *conversion,
1954 float *src,
1955 float *dst,
1956 long samples)
1958 const Babl *space = babl_conversion_get_source_space (conversion);
1959 float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_Xf;
1960 float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Yf;
1961 float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Zf;
1962 float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_Xf;
1963 float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Yf;
1964 float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Zf;
1965 float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_Xf;
1966 float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Yf;
1967 float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Zf;
1968 long n = samples;
1970 while (n--)
1972 float L = src[0];
1973 float A = src[1];
1974 float B = src[2];
1976 float fy = (L + 16.0f) / 116.0f;
1977 float fx = fy + A / 500.0f;
1978 float fz = fy - B / 200.0f;
1980 float yr = L > LAB_KAPPAf * LAB_EPSILONf ? cubef (fy) : L / LAB_KAPPAf;
1981 float xr = cubef (fx) > LAB_EPSILONf ? cubef (fx) : (fx * 116.0f - 16.0f) / LAB_KAPPAf;
1982 float zr = cubef (fz) > LAB_EPSILONf ? cubef (fz) : (fz * 116.0f - 16.0f) / LAB_KAPPAf;
1984 float r = m_0_0 * xr + m_0_1 * yr + m_0_2 * zr;
1985 float g = m_1_0 * xr + m_1_1 * yr + m_1_2 * zr;
1986 float b = m_2_0 * xr + m_2_1 * yr + m_2_2 * zr;
1988 dst[0] = r;
1989 dst[1] = g;
1990 dst[2] = b;
1992 src += 3;
1993 dst += 3;
1998 static void
1999 Labf_to_rgbaf (const Babl *conversion,float *src,
2000 float *dst,
2001 long samples)
2003 const Babl *space = babl_conversion_get_source_space (conversion);
2004 float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_Xf;
2005 float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Yf;
2006 float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Zf;
2007 float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_Xf;
2008 float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Yf;
2009 float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Zf;
2010 float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_Xf;
2011 float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Yf;
2012 float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Zf;
2013 long n = samples;
2015 while (n--)
2017 float L = src[0];
2018 float A = src[1];
2019 float B = src[2];
2021 float fy = (L + 16.0f) / 116.0f;
2022 float fx = fy + A / 500.0f;
2023 float fz = fy - B / 200.0f;
2025 float yr = L > LAB_KAPPAf * LAB_EPSILONf ? cubef (fy) : L / LAB_KAPPAf;
2026 float xr = cubef (fx) > LAB_EPSILONf ? cubef (fx) : (fx * 116.0f - 16.0f) / LAB_KAPPAf;
2027 float zr = cubef (fz) > LAB_EPSILONf ? cubef (fz) : (fz * 116.0f - 16.0f) / LAB_KAPPAf;
2029 float r = m_0_0 * xr + m_0_1 * yr + m_0_2 * zr;
2030 float g = m_1_0 * xr + m_1_1 * yr + m_1_2 * zr;
2031 float b = m_2_0 * xr + m_2_1 * yr + m_2_2 * zr;
2033 dst[0] = r;
2034 dst[1] = g;
2035 dst[2] = b;
2036 dst[3] = 1.0f;
2038 src += 3;
2039 dst += 4;
2043 static void
2044 Labaf_to_rgbaf (const Babl *conversion,
2045 float *src,
2046 float *dst,
2047 long samples)
2049 const Babl *space = babl_conversion_get_source_space (conversion);
2050 float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_Xf;
2051 float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Yf;
2052 float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Zf;
2053 float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_Xf;
2054 float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Yf;
2055 float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Zf;
2056 float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_Xf;
2057 float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Yf;
2058 float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Zf;
2059 long n = samples;
2061 while (n--)
2063 float L = src[0];
2064 float A = src[1];
2065 float B = src[2];
2066 float a = src[3];
2068 float fy = (L + 16.0f) / 116.0f;
2069 float fx = fy + A / 500.0f;
2070 float fz = fy - B / 200.0f;
2072 float yr = L > LAB_KAPPAf * LAB_EPSILONf ? cubef (fy) : L / LAB_KAPPAf;
2073 float xr = cubef (fx) > LAB_EPSILONf ? cubef (fx) : (fx * 116.0f - 16.0f) / LAB_KAPPAf;
2074 float zr = cubef (fz) > LAB_EPSILONf ? cubef (fz) : (fz * 116.0f - 16.0f) / LAB_KAPPAf;
2076 float r = m_0_0 * xr + m_0_1 * yr + m_0_2 * zr;
2077 float g = m_1_0 * xr + m_1_1 * yr + m_1_2 * zr;
2078 float b = m_2_0 * xr + m_2_1 * yr + m_2_2 * zr;
2080 dst[0] = r;
2081 dst[1] = g;
2082 dst[2] = b;
2083 dst[3] = a;
2085 src += 4;
2086 dst += 4;
2090 static void
2091 Labf_to_Lchabf (const Babl *conversion,
2092 float *src,
2093 float *dst,
2094 long samples)
2096 long n = samples;
2098 while (n--)
2100 float L = src[0];
2101 float A = src[1];
2102 float B = src[2];
2104 float C = sqrtf (A * A + B * B);
2105 float H = atan2f (B, A) * DEGREES_PER_RADIANf;
2107 // Keep H within the range 0-360
2108 if (H < 0.0f)
2109 H += 360.0f;
2111 dst[0] = L;
2112 dst[1] = C;
2113 dst[2] = H;
2115 src += 3;
2116 dst += 3;
2120 static void
2121 Lchabf_to_Labf (const Babl *conversion,
2122 float *src,
2123 float *dst,
2124 long samples)
2126 long n = samples;
2128 while (n--)
2130 float L = src[0];
2131 float C = src[1];
2132 float H = src[2];
2134 float A = C * cosf (H * RADIANS_PER_DEGREEf);
2135 float B = C * sinf (H * RADIANS_PER_DEGREEf);
2137 dst[0] = L;
2138 dst[1] = A;
2139 dst[2] = B;
2141 src += 3;
2142 dst += 3;
2146 static void
2147 Labaf_to_Lchabaf (const Babl *conversion,
2148 float *src,
2149 float *dst,
2150 long samples)
2152 long n = samples;
2154 while (n--)
2156 float L = src[0];
2157 float A = src[1];
2158 float B = src[2];
2159 float a = src[3];
2161 float C = sqrtf (A * A + B * B);
2162 float H = atan2f (B, A) * DEGREES_PER_RADIANf;
2164 // Keep H within the range 0-360
2165 if (H < 0.0f)
2166 H += 360.0f;
2168 dst[0] = L;
2169 dst[1] = C;
2170 dst[2] = H;
2171 dst[3] = a;
2173 src += 4;
2174 dst += 4;
2178 static void
2179 Lchabaf_to_Labaf (const Babl *conversion,
2180 float *src,
2181 float *dst,
2182 long samples)
2184 long n = samples;
2186 while (n--)
2188 float L = src[0];
2189 float C = src[1];
2190 float H = src[2];
2191 float a = src[3];
2193 float A = C * cosf (H * RADIANS_PER_DEGREEf);
2194 float B = C * sinf (H * RADIANS_PER_DEGREEf);
2196 dst[0] = L;
2197 dst[1] = A;
2198 dst[2] = B;
2199 dst[3] = a;
2201 src += 4;
2202 dst += 4;
2206 #if defined(USE_SSE2)
2208 /* This is an SSE2 version of Halley's method for approximating the
2209 * cube root of an IEEE float implementation.
2211 * The scalar version is as follows:
2213 * static inline float
2214 * _cbrt_5f (float x)
2216 * union { float f; uint32_t i; } u = { x };
2218 * u.i = u.i / 3 + 709921077;
2219 * return u.f;
2222 * static inline float
2223 * _cbrta_halleyf (float a, float R)
2225 * float a3 = a * a * a;
2226 * float b = a * (a3 + R + R) / (a3 + a3 + R);
2227 * return b;
2230 * static inline float
2231 * _cbrtf (float x)
2233 * float a;
2235 * a = _cbrt_5f (x);
2236 * a = _cbrta_halleyf (a, x);
2237 * a = _cbrta_halleyf (a, x);
2238 * return a;
2241 * The above scalar version seems to have originated from
2242 * http://metamerist.com/cbrt/cbrt.htm but that's not accessible
2243 * anymore. At present there's a copy in CubeRoot.cpp in the Skia
2244 * sources that's licensed under a BSD-style license. There's some
2245 * discussion on the implementation at
2246 * http://www.voidcn.com/article/p-gpwztojr-wt.html.
2248 * Note that Darktable also has an SSE2 version of the same algorithm,
2249 * but uses only a single iteration of Halley's method, which is too
2250 * coarse.
2252 /* Return cube roots of the four single-precision floating point
2253 * components of x.
2255 static inline __m128
2256 _cbrtf_ps_sse2 (__m128 x)
2258 const __m128i magic = _mm_set1_epi32 (709921077);
2260 __m128i xi = _mm_castps_si128 (x);
2261 __m128 xi_3 = _mm_div_ps (_mm_cvtepi32_ps (xi), _mm_set1_ps (3.0f));
2262 __m128i ai = _mm_add_epi32 (_mm_cvtps_epi32 (xi_3), magic);
2263 __m128 a = _mm_castsi128_ps (ai);
2265 __m128 a3 = _mm_mul_ps (_mm_mul_ps (a, a), a);
2266 __m128 divisor = _mm_add_ps (_mm_add_ps (a3, a3), x);
2267 a = _mm_div_ps (_mm_mul_ps (a, _mm_add_ps (a3, _mm_add_ps (x, x))), divisor);
2269 a3 = _mm_mul_ps (_mm_mul_ps (a, a), a);
2270 divisor = _mm_add_ps (_mm_add_ps (a3, a3), x);
2271 a = _mm_div_ps (_mm_mul_ps (a, _mm_add_ps (a3, _mm_add_ps (x, x))), divisor);
2273 return a;
2276 static inline __m128
2277 lab_r_to_f_sse2 (__m128 r)
2279 const __m128 epsilon = _mm_set1_ps (LAB_EPSILON);
2280 const __m128 kappa = _mm_set1_ps (LAB_KAPPA);
2282 const __m128 f_big = _cbrtf_ps_sse2 (r);
2284 const __m128 f_small = _mm_div_ps (_mm_add_ps (_mm_mul_ps (kappa, r), _mm_set1_ps (16.0f)),
2285 _mm_set1_ps (116.0f));
2287 const __m128 mask = _mm_cmpgt_ps (r, epsilon);
2288 const __m128 f = _mm_or_ps (_mm_and_ps (mask, f_big), _mm_andnot_ps (mask, f_small));
2289 return f;
2292 static void
2293 Yf_to_Lf_sse2 (const Babl *conversion,
2294 const float *src,
2295 float *dst,
2296 long samples)
2298 long i = 0;
2299 long remainder;
2301 if (((uintptr_t) src % 16) + ((uintptr_t) dst % 16) == 0)
2303 const long n = (samples / 4) * 4;
2305 for ( ; i < n; i += 4)
2307 __m128 Y = _mm_load_ps (src);
2309 __m128 fy = lab_r_to_f_sse2 (Y);
2311 __m128 L = _mm_sub_ps (_mm_mul_ps (_mm_set1_ps (116.0f), fy), _mm_set1_ps (16.0f));
2313 _mm_store_ps (dst, L);
2315 src += 4;
2316 dst += 4;
2320 remainder = samples - i;
2321 while (remainder--)
2323 float yr = src[0];
2324 float L = yr > LAB_EPSILONf ? 116.0f * _cbrtf (yr) - 16 : LAB_KAPPAf * yr;
2326 dst[0] = L;
2328 src++;
2329 dst++;
2333 static void
2334 Yaf_to_Lf_sse2 (const Babl *conversion,
2335 const float *src,
2336 float *dst,
2337 long samples)
2339 long i = 0;
2340 long remainder;
2342 if (((uintptr_t) src % 16) + ((uintptr_t) dst % 16) == 0)
2344 const long n = (samples / 4) * 4;
2346 for ( ; i < n; i += 4)
2348 __m128 YaYa0 = _mm_load_ps (src);
2349 __m128 YaYa1 = _mm_load_ps (src + 4);
2351 __m128 Y = _mm_shuffle_ps (YaYa0, YaYa1, _MM_SHUFFLE (2, 0, 2, 0));
2353 __m128 fy = lab_r_to_f_sse2 (Y);
2355 __m128 L = _mm_sub_ps (_mm_mul_ps (_mm_set1_ps (116.0f), fy), _mm_set1_ps (16.0f));
2357 _mm_store_ps (dst, L);
2359 src += 8;
2360 dst += 4;
2364 remainder = samples - i;
2365 while (remainder--)
2367 float yr = src[0];
2368 float L = yr > LAB_EPSILONf ? 116.0f * _cbrtf (yr) - 16 : LAB_KAPPAf * yr;
2370 dst[0] = L;
2372 src += 2;
2373 dst += 1;
2377 static void
2378 rgbaf_to_Lf_sse2 (const Babl *conversion,
2379 const float *src,
2380 float *dst,
2381 long samples)
2383 const Babl *space = babl_conversion_get_source_space (conversion);
2384 const float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
2385 const float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
2386 const float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
2387 long i = 0;
2388 long remainder;
2390 if (((uintptr_t) src % 16) + ((uintptr_t) dst % 16) == 0)
2392 const long n = (samples / 4) * 4;
2393 const __m128 m_1_0_v = _mm_set1_ps (m_1_0);
2394 const __m128 m_1_1_v = _mm_set1_ps (m_1_1);
2395 const __m128 m_1_2_v = _mm_set1_ps (m_1_2);
2397 for ( ; i < n; i += 4)
2399 __m128 rgba0 = _mm_load_ps (src);
2400 __m128 rgba1 = _mm_load_ps (src + 4);
2401 __m128 rgba2 = _mm_load_ps (src + 8);
2402 __m128 rgba3 = _mm_load_ps (src + 12);
2404 __m128 r = rgba0;
2405 __m128 g = rgba1;
2406 __m128 b = rgba2;
2407 __m128 a = rgba3;
2408 _MM_TRANSPOSE4_PS (r, g, b, a);
2411 __m128 yr = _mm_add_ps (_mm_add_ps (_mm_mul_ps (m_1_0_v, r), _mm_mul_ps (m_1_1_v, g)),
2412 _mm_mul_ps (m_1_2_v, b));
2414 __m128 fy = lab_r_to_f_sse2 (yr);
2416 __m128 L = _mm_sub_ps (_mm_mul_ps (_mm_set1_ps (116.0f), fy), _mm_set1_ps (16.0f));
2418 _mm_store_ps (dst, L);
2421 src += 16;
2422 dst += 4;
2426 remainder = samples - i;
2427 while (remainder--)
2429 float r = src[0];
2430 float g = src[1];
2431 float b = src[2];
2433 float yr = m_1_0 * r + m_1_1 * g + m_1_2 * b;
2434 float L = yr > LAB_EPSILONf ? 116.0f * _cbrtf (yr) - 16 : LAB_KAPPAf * yr;
2436 dst[0] = L;
2438 src += 4;
2439 dst += 1;
2443 static void
2444 rgbaf_to_Labaf_sse2_aligned_4mult (const Babl *conversion,
2445 const float *src,
2446 float *dst,
2447 long samples)
2449 const Babl *space = babl_conversion_get_source_space (conversion);
2450 const float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_Xf;
2451 const float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_Xf;
2452 const float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_Xf;
2453 const float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Yf;
2454 const float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Yf;
2455 const float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Yf;
2456 const float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Zf;
2457 const float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Zf;
2458 const float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Zf;
2459 long i = 0;
2461 const __m128 m_0_0_v = _mm_set1_ps (m_0_0);
2462 const __m128 m_0_1_v = _mm_set1_ps (m_0_1);
2463 const __m128 m_0_2_v = _mm_set1_ps (m_0_2);
2464 const __m128 m_1_0_v = _mm_set1_ps (m_1_0);
2465 const __m128 m_1_1_v = _mm_set1_ps (m_1_1);
2466 const __m128 m_1_2_v = _mm_set1_ps (m_1_2);
2467 const __m128 m_2_0_v = _mm_set1_ps (m_2_0);
2468 const __m128 m_2_1_v = _mm_set1_ps (m_2_1);
2469 const __m128 m_2_2_v = _mm_set1_ps (m_2_2);
2471 assert (((uintptr_t) src % 16) + ((uintptr_t) dst % 16) == 0);
2472 assert (samples % 4 == 0);
2474 for ( ; i < samples; i += 4)
2476 __m128 Laba0;
2477 __m128 Laba1;
2478 __m128 Laba2;
2479 __m128 Laba3;
2481 __m128 rgba0 = _mm_load_ps (src);
2482 __m128 rgba1 = _mm_load_ps (src + 4);
2483 __m128 rgba2 = _mm_load_ps (src + 8);
2484 __m128 rgba3 = _mm_load_ps (src + 12);
2486 __m128 r = rgba0;
2487 __m128 g = rgba1;
2488 __m128 b = rgba2;
2489 __m128 a = rgba3;
2490 _MM_TRANSPOSE4_PS (r, g, b, a);
2493 __m128 xr = _mm_add_ps (_mm_add_ps (_mm_mul_ps (m_0_0_v, r), _mm_mul_ps (m_0_1_v, g)),
2494 _mm_mul_ps (m_0_2_v, b));
2495 __m128 yr = _mm_add_ps (_mm_add_ps (_mm_mul_ps (m_1_0_v, r), _mm_mul_ps (m_1_1_v, g)),
2496 _mm_mul_ps (m_1_2_v, b));
2497 __m128 zr = _mm_add_ps (_mm_add_ps (_mm_mul_ps (m_2_0_v, r), _mm_mul_ps (m_2_1_v, g)),
2498 _mm_mul_ps (m_2_2_v, b));
2500 __m128 fx = lab_r_to_f_sse2 (xr);
2501 __m128 fy = lab_r_to_f_sse2 (yr);
2502 __m128 fz = lab_r_to_f_sse2 (zr);
2504 __m128 L = _mm_sub_ps (_mm_mul_ps (_mm_set1_ps (116.0f), fy), _mm_set1_ps (16.0f));
2505 __m128 A = _mm_mul_ps (_mm_set1_ps (500.0f), _mm_sub_ps (fx, fy));
2506 __m128 B = _mm_mul_ps (_mm_set1_ps (200.0f), _mm_sub_ps (fy, fz));
2508 Laba0 = L;
2509 Laba1 = A;
2510 Laba2 = B;
2511 Laba3 = a;
2512 _MM_TRANSPOSE4_PS (Laba0, Laba1, Laba2, Laba3);
2515 _mm_store_ps (dst, Laba0);
2516 _mm_store_ps (dst + 4, Laba1);
2517 _mm_store_ps (dst + 8, Laba2);
2518 _mm_store_ps (dst + 12, Laba3);
2520 src += 16;
2521 dst += 16;
2525 static void
2526 rgbaf_to_Labaf_sse2 (const Babl *conversion,
2527 const float *src,
2528 float *dst,
2529 long samples)
2531 if (((uintptr_t) src % 16) + ((uintptr_t) dst % 16) == 0 ||
2532 samples < 4)
2534 long first_samples = samples / 4 * 4;
2535 long remainder;
2537 rgbaf_to_Labaf_sse2_aligned_4mult (conversion, src, dst, first_samples);
2538 remainder = samples - first_samples;
2540 if (remainder)
2542 float __attribute__ ((aligned (16))) aligned_src[16];
2543 float __attribute__ ((aligned (16))) aligned_dest[16];
2545 memcpy (aligned_src, src + first_samples * 4, remainder * 16);
2546 memset (aligned_src + remainder * 4, 0, 4 * 16 - (remainder * 16));
2547 rgbaf_to_Labaf_sse2_aligned_4mult (conversion, (const float *) aligned_src, aligned_dest, 4);
2548 memcpy (dst + first_samples * 4, aligned_dest, remainder * 16);
2551 else
2553 float __attribute__ ((aligned (16))) _aligned_src[4 * samples];
2554 float __attribute__ ((aligned (16))) _aligned_dst[4 * samples];
2555 float *aligned_src;
2556 float *aligned_dst;
2558 if (((uintptr_t) src % 16) != 0)
2560 aligned_src = _aligned_src;
2561 memcpy (aligned_src, src, samples * 16);
2563 else
2565 aligned_src = (float *) src;
2568 if (((uintptr_t) dst % 16) != 0)
2569 aligned_dst = _aligned_dst;
2570 else
2571 aligned_dst = dst;
2573 rgbaf_to_Labaf_sse2 (conversion, aligned_src, aligned_dst, samples);
2575 if (((uintptr_t) dst % 16) != 0)
2576 memcpy (dst, aligned_dst, samples * 16);
2580 #endif /* defined(USE_SSE2) */
2582 static void
2583 conversions (void)
2585 /* babl_model */
2587 babl_conversion_new (
2588 babl_model ("RGBA"),
2589 babl_model ("CIE Lab"),
2590 "linear", rgba_to_lab,
2591 NULL
2593 babl_conversion_new (
2594 babl_model ("CIE Lab"),
2595 babl_model ("RGBA"),
2596 "linear", lab_to_rgba,
2597 NULL
2599 babl_conversion_new (
2600 babl_model ("RGBA"),
2601 babl_model ("CIE Lab alpha"),
2602 "linear", rgba_to_laba,
2603 NULL
2605 babl_conversion_new (
2606 babl_model ("CIE Lab alpha"),
2607 babl_model ("RGBA"),
2608 "linear", laba_to_rgba,
2609 NULL
2611 babl_conversion_new (
2612 babl_model ("RGBA"),
2613 babl_model ("CIE LCH(ab)"),
2614 "linear", rgba_to_lchab,
2615 NULL
2617 babl_conversion_new (
2618 babl_model ("CIE LCH(ab)"),
2619 babl_model ("RGBA"),
2620 "linear", lchab_to_rgba,
2621 NULL
2623 babl_conversion_new (
2624 babl_model ("RGBA"),
2625 babl_model ("CIE LCH(ab) alpha"),
2626 "linear", rgba_to_lchaba,
2627 NULL
2629 babl_conversion_new (
2630 babl_model ("CIE LCH(ab) alpha"),
2631 babl_model ("RGBA"),
2632 "linear", lchaba_to_rgba,
2633 NULL
2635 babl_conversion_new (
2636 babl_model ("RGBA"),
2637 babl_model ("CIE XYZ"),
2638 "linear", rgba_to_xyz,
2639 NULL
2641 babl_conversion_new (
2642 babl_model ("CIE XYZ"),
2643 babl_model ("RGBA"),
2644 "linear", xyz_to_rgba,
2645 NULL
2647 babl_conversion_new (
2648 babl_model ("RGBA"),
2649 babl_model ("CIE XYZ alpha"),
2650 "linear", rgba_to_xyza,
2651 NULL
2653 babl_conversion_new (
2654 babl_model ("CIE XYZ alpha"),
2655 babl_model ("RGBA"),
2656 "linear", xyza_to_rgba,
2657 NULL
2660 /* CIE xyY */
2661 babl_conversion_new (
2662 babl_model ("RGBA"),
2663 babl_model ("CIE xyY"),
2664 "linear", rgba_to_xyY,
2665 NULL
2667 babl_conversion_new (
2668 babl_model ("CIE xyY"),
2669 babl_model ("RGBA"),
2670 "linear", xyY_to_rgba,
2671 NULL
2673 babl_conversion_new (
2674 babl_model ("RGBA"),
2675 babl_model ("CIE xyY alpha"),
2676 "linear", rgba_to_xyYa,
2677 NULL
2679 babl_conversion_new (
2680 babl_model ("CIE xyY alpha"),
2681 babl_model ("RGBA"),
2682 "linear", xyYa_to_rgba,
2683 NULL
2686 /* CIE 1976 UCS */
2687 babl_conversion_new (
2688 babl_model ("RGBA"),
2689 babl_model ("CIE Yuv"),
2690 "linear", rgba_to_Yuv,
2691 NULL
2693 babl_conversion_new (
2694 babl_model ("CIE Yuv"),
2695 babl_model ("RGBA"),
2696 "linear", Yuv_to_rgba,
2697 NULL
2699 babl_conversion_new (
2700 babl_model ("RGBA"),
2701 babl_model ("CIE Yuv alpha"),
2702 "linear", rgba_to_Yuva,
2703 NULL
2705 babl_conversion_new (
2706 babl_model ("CIE Yuv alpha"),
2707 babl_model ("RGBA"),
2708 "linear", Yuva_to_rgba,
2709 NULL
2712 /* babl_format */
2714 babl_conversion_new (
2715 babl_format ("RGB float"),
2716 babl_format ("CIE Lab float"),
2717 "linear", rgbf_to_Labf,
2718 NULL
2720 babl_conversion_new (
2721 babl_format ("RGBA float"),
2722 babl_format ("CIE Lab float"),
2723 "linear", rgbaf_to_Labf,
2724 NULL
2726 babl_conversion_new (
2727 babl_format ("RGBA float"),
2728 babl_format ("CIE Lab alpha float"),
2729 "linear", rgbaf_to_Labaf,
2730 NULL
2732 babl_conversion_new (
2733 babl_format ("CIE Lab float"),
2734 babl_format ("RGB float"),
2735 "linear", Labf_to_rgbf,
2736 NULL
2738 babl_conversion_new (
2739 babl_format ("CIE Lab float"),
2740 babl_format ("RGBA float"),
2741 "linear", Labf_to_rgbaf,
2742 NULL
2744 babl_conversion_new (
2745 babl_format ("CIE Lab alpha float"),
2746 babl_format ("RGBA float"),
2747 "linear", Labaf_to_rgbaf,
2748 NULL
2750 babl_conversion_new (
2751 babl_format ("Y float"),
2752 babl_format ("CIE L float"),
2753 "linear", Yf_to_Lf,
2754 NULL
2756 babl_conversion_new (
2757 babl_format ("YA float"),
2758 babl_format ("CIE L float"),
2759 "linear", Yaf_to_Lf,
2760 NULL
2762 babl_conversion_new (
2763 babl_format ("YA float"),
2764 babl_format ("CIE L alpha float"),
2765 "linear", Yaf_to_Laf,
2766 NULL
2768 babl_conversion_new (
2769 babl_format ("RGBA float"),
2770 babl_format ("CIE L float"),
2771 "linear", rgbaf_to_Lf,
2772 NULL
2774 babl_conversion_new (
2775 babl_format ("CIE Lab float"),
2776 babl_format ("CIE L float"),
2777 "linear", Labf_to_Lf,
2778 NULL
2780 babl_conversion_new (
2781 babl_format ("CIE Lab alpha float"),
2782 babl_format ("CIE L float"),
2783 "linear", Labaf_to_Lf,
2784 NULL
2786 babl_conversion_new (
2787 babl_format ("CIE Lab float"),
2788 babl_format ("CIE LCH(ab) float"),
2789 "linear", Labf_to_Lchabf,
2790 NULL
2792 babl_conversion_new (
2793 babl_format ("CIE LCH(ab) float"),
2794 babl_format ("CIE Lab float"),
2795 "linear", Lchabf_to_Labf,
2796 NULL
2798 babl_conversion_new (
2799 babl_format ("CIE Lab alpha float"),
2800 babl_format ("CIE LCH(ab) alpha float"),
2801 "linear", Labaf_to_Lchabaf,
2802 NULL
2804 babl_conversion_new (
2805 babl_format ("CIE LCH(ab) alpha float"),
2806 babl_format ("CIE Lab alpha float"),
2807 "linear", Lchabaf_to_Labaf,
2808 NULL
2811 /* CIE xyY */
2812 babl_conversion_new (
2813 babl_format ("RGB float"),
2814 babl_format ("CIE xyY float"),
2815 "linear", rgbf_to_xyYf,
2816 NULL
2818 babl_conversion_new (
2819 babl_format ("RGBA float"),
2820 babl_format ("CIE xyY alpha float"),
2821 "linear", rgbaf_to_xyYaf,
2822 NULL
2824 babl_conversion_new (
2825 babl_format ("RGBA float"),
2826 babl_format ("CIE xyY float"),
2827 "linear", rgbaf_to_xyYf,
2828 NULL
2830 babl_conversion_new (
2831 babl_format ("CIE xyY float"),
2832 babl_format ("RGB float"),
2833 "linear", xyYf_to_rgbf,
2834 NULL
2836 babl_conversion_new (
2837 babl_format ("CIE xyY float"),
2838 babl_format ("RGBA float"),
2839 "linear", xyYf_to_rgbaf,
2840 NULL
2842 babl_conversion_new (
2843 babl_format ("CIE xyY alpha float"),
2844 babl_format ("RGBA float"),
2845 "linear", xyYaf_to_rgbaf,
2846 NULL
2848 /* CIE 1976 UCS */
2849 babl_conversion_new (
2850 babl_format ("RGB float"),
2851 babl_format ("CIE Yuv float"),
2852 "linear", rgbf_to_Yuvf,
2853 NULL
2855 babl_conversion_new (
2856 babl_format ("RGBA float"),
2857 babl_format ("CIE Yuv alpha float"),
2858 "linear", rgbaf_to_Yuvaf,
2859 NULL
2861 babl_conversion_new (
2862 babl_format ("RGBA float"),
2863 babl_format ("CIE Yuv float"),
2864 "linear", rgbaf_to_Yuvf,
2865 NULL
2867 babl_conversion_new (
2868 babl_format ("CIE Yuv float"),
2869 babl_format ("RGB float"),
2870 "linear", Yuvf_to_rgbf,
2871 NULL
2873 babl_conversion_new (
2874 babl_format ("CIE Yuv float"),
2875 babl_format ("RGBA float"),
2876 "linear", Yuvf_to_rgbaf,
2877 NULL
2879 babl_conversion_new (
2880 babl_format ("CIE Yuv alpha float"),
2881 babl_format ("RGBA float"),
2882 "linear", Yuvaf_to_rgbaf,
2883 NULL
2885 #if defined(USE_SSE2)
2887 if (babl_cpu_accel_get_support () & BABL_CPU_ACCEL_X86_SSE2)
2889 babl_conversion_new (
2890 babl_format ("RGBA float"),
2891 babl_format ("CIE Lab alpha float"),
2892 "linear", rgbaf_to_Labaf_sse2,
2893 NULL
2895 babl_conversion_new (
2896 babl_format ("Y float"),
2897 babl_format ("CIE L float"),
2898 "linear", Yf_to_Lf_sse2,
2899 NULL
2901 babl_conversion_new (
2902 babl_format ("YA float"),
2903 babl_format ("CIE L float"),
2904 "linear", Yaf_to_Lf_sse2,
2905 NULL
2907 babl_conversion_new (
2908 babl_format ("RGBA float"),
2909 babl_format ("CIE L float"),
2910 "linear", rgbaf_to_Lf_sse2,
2911 NULL
2915 #endif /* defined(USE_SSE2) */
2917 rgbcie_init ();
2920 static void
2921 formats (void)
2923 babl_format_new (
2924 "name", "CIE Lab float",
2925 babl_model ("CIE Lab"),
2927 babl_type ("float"),
2928 babl_component ("CIE L"),
2929 babl_component ("CIE a"),
2930 babl_component ("CIE b"),
2931 NULL);
2933 babl_format_new (
2934 "name", "CIE XYZ float",
2935 babl_model ("CIE XYZ"),
2937 babl_type ("float"),
2938 babl_component ("CIE X"),
2939 babl_component ("CIE Y"),
2940 babl_component ("CIE Z"),
2941 NULL);
2943 babl_format_new (
2944 "name", "CIE XYZ alpha float",
2945 babl_model ("CIE XYZ"),
2947 babl_type ("float"),
2948 babl_component ("CIE X"),
2949 babl_component ("CIE Y"),
2950 babl_component ("CIE Z"),
2951 babl_component ("A"),
2952 NULL);
2954 babl_format_new (
2955 "name", "CIE Lab alpha float",
2956 babl_model ("CIE Lab alpha"),
2958 babl_type ("float"),
2959 babl_component ("CIE L"),
2960 babl_component ("CIE a"),
2961 babl_component ("CIE b"),
2962 babl_component ("A"),
2963 NULL);
2965 babl_format_new (
2966 "name", "CIE LCH(ab) float",
2967 babl_model ("CIE LCH(ab)"),
2969 babl_type ("float"),
2970 babl_component ("CIE L"),
2971 babl_component ("CIE C(ab)"),
2972 babl_component ("CIE H(ab)"),
2973 NULL);
2975 babl_format_new (
2976 "name", "CIE LCH(ab) alpha float",
2977 babl_model ("CIE LCH(ab) alpha"),
2979 babl_type ("float"),
2980 babl_component ("CIE L"),
2981 babl_component ("CIE C(ab)"),
2982 babl_component ("CIE H(ab)"),
2983 babl_component ("A"),
2984 NULL);
2986 babl_format_new (
2987 "name", "CIE L float",
2988 babl_model ("CIE Lab"),
2989 babl_type ("float"),
2990 babl_component ("CIE L"),
2991 NULL);
2993 babl_format_new (
2994 "name", "CIE L alpha float",
2995 babl_model ("CIE Lab alpha"),
2996 babl_type ("float"),
2997 babl_component ("CIE L"),
2998 babl_component ("A"),
2999 NULL);
3001 babl_format_new (
3002 "name", "CIE Lab u8",
3003 babl_model ("CIE Lab"),
3005 babl_type ("CIE u8 L"),
3006 babl_component ("CIE L"),
3007 babl_type ("CIE u8 ab"),
3008 babl_component ("CIE a"),
3009 babl_type ("CIE u8 ab"),
3010 babl_component ("CIE b"),
3011 NULL);
3013 babl_format_new (
3014 "name", "CIE Lab alpha u8",
3015 babl_model ("CIE Lab alpha"),
3017 babl_type ("CIE u8 L"),
3018 babl_component ("CIE L"),
3019 babl_type ("CIE u8 ab"),
3020 babl_component ("CIE a"),
3021 babl_type ("CIE u8 ab"),
3022 babl_component ("CIE b"),
3023 babl_type ("u8"),
3024 babl_component ("A"),
3025 NULL);
3027 babl_format_new (
3028 "name", "CIE Lab u16",
3029 babl_model ("CIE Lab"),
3031 babl_type ("CIE u16 L"),
3032 babl_component ("CIE L"),
3033 babl_type ("CIE u16 ab"),
3034 babl_component ("CIE a"),
3035 babl_type ("CIE u16 ab"),
3036 babl_component ("CIE b"),
3037 NULL);
3039 babl_format_new (
3040 "name", "CIE Lab alpha u16",
3041 babl_model ("CIE Lab alpha"),
3043 babl_type ("CIE u16 L"),
3044 babl_component ("CIE L"),
3045 babl_type ("CIE u16 ab"),
3046 babl_component ("CIE a"),
3047 babl_type ("CIE u16 ab"),
3048 babl_component ("CIE b"),
3049 babl_type ("u16"),
3050 babl_component ("A"),
3051 NULL);
3053 babl_format_new (
3054 "name", "CIE xyY float",
3055 babl_model ("CIE xyY"),
3057 babl_type ("float"),
3058 babl_component ("CIE x"),
3059 babl_component ("CIE y"),
3060 babl_component ("CIE Y"),
3061 NULL);
3063 babl_format_new (
3064 "name", "CIE xyY alpha float",
3065 babl_model ("CIE xyY alpha"),
3067 babl_type ("float"),
3068 babl_component ("CIE x"),
3069 babl_component ("CIE y"),
3070 babl_component ("CIE Y"),
3071 babl_component ("A"),
3072 NULL);
3074 /* CIE 1976 UCS */
3075 babl_format_new (
3076 "name", "CIE Yuv float",
3077 babl_model ("CIE Yuv"),
3079 babl_type ("float"),
3080 babl_component ("CIE Y"),
3081 babl_component ("CIE u"),
3082 babl_component ("CIE v"),
3083 NULL);
3085 babl_format_new (
3086 "name", "CIE Yuv alpha float",
3087 babl_model ("CIE Yuv alpha"),
3089 babl_type ("float"),
3090 babl_component ("CIE Y"),
3091 babl_component ("CIE u"),
3092 babl_component ("CIE v"),
3093 babl_component ("A"),
3094 NULL);
3098 /******** end floating point RGB/CIE color space conversions **********/
3100 /******** begin integer RGB/CIE color space conversions **************/
3102 static inline void
3103 convert_double_u8_scaled (const Babl *conversion,
3104 double min_val,
3105 double max_val,
3106 unsigned char min,
3107 unsigned char max,
3108 char *src,
3109 char *dst,
3110 int src_pitch,
3111 int dst_pitch,
3112 long n)
3114 while (n--)
3116 double dval = *(double *) src;
3117 unsigned char u8val;
3119 if (dval < min_val)
3120 u8val = min;
3121 else if (dval > max_val)
3122 u8val = max;
3123 else
3124 u8val = ((dval - min_val) / (max_val - min_val) * (max - min) + min) + 0.5;
3126 *(unsigned char *) dst = u8val;
3127 src += src_pitch;
3128 dst += dst_pitch;
3132 static inline void
3133 convert_u8_double_scaled (const Babl *conversion,
3134 double min_val,
3135 double max_val,
3136 unsigned char min,
3137 unsigned char max,
3138 char *src,
3139 char *dst,
3140 int src_pitch,
3141 int dst_pitch,
3142 long n)
3144 while (n--)
3146 int u8val = *(unsigned char *) src;
3147 double dval;
3149 if (u8val < min)
3150 dval = min_val;
3151 else if (u8val > max)
3152 dval = max_val;
3153 else
3154 dval = (u8val - min) / (double) (max - min) * (max_val - min_val) + min_val;
3156 (*(double *) dst) = dval;
3158 dst += dst_pitch;
3159 src += src_pitch;
3163 #define MAKE_CONVERSIONS(name, min_val, max_val, min, max) \
3164 static void \
3165 convert_ ## name ## _double (const Babl *c, char *src, \
3166 char *dst, \
3167 int src_pitch, \
3168 int dst_pitch, \
3169 long n) \
3171 convert_u8_double_scaled (c, min_val, max_val, min, max, \
3172 src, dst, src_pitch, dst_pitch, n); \
3174 static void \
3175 convert_double_ ## name (const Babl *c, char *src, \
3176 char *dst, \
3177 int src_pitch, \
3178 int dst_pitch, \
3179 long n) \
3181 convert_double_u8_scaled (c, min_val, max_val, min, max, \
3182 src, dst, src_pitch, dst_pitch, n); \
3185 /* source ICC.1:2004-10 */
3187 MAKE_CONVERSIONS (u8_l, 0.0, 100.0, 0x00, 0xff)
3188 MAKE_CONVERSIONS (u8_ab, -128.0, 127.0, 0x00, 0xff)
3190 #undef MAKE_CONVERSIONS
3192 static inline void
3193 convert_float_u8_scaled (const Babl *conversion,
3194 float min_val,
3195 float max_val,
3196 unsigned char min,
3197 unsigned char max,
3198 char *src,
3199 char *dst,
3200 int src_pitch,
3201 int dst_pitch,
3202 long n)
3204 while (n--)
3206 float dval = *(float *) src;
3207 unsigned char u8val;
3209 if (dval < min_val)
3210 u8val = min;
3211 else if (dval > max_val)
3212 u8val = max;
3213 else
3214 u8val = ((dval - min_val) / (max_val - min_val) * (max - min) + min) + 0.5f;
3216 *(unsigned char *) dst = u8val;
3217 src += src_pitch;
3218 dst += dst_pitch;
3222 static inline void
3223 convert_u8_float_scaled (const Babl *conversion,
3224 float min_val,
3225 float max_val,
3226 unsigned char min,
3227 unsigned char max,
3228 char *src,
3229 char *dst,
3230 int src_pitch,
3231 int dst_pitch,
3232 long n)
3234 while (n--)
3236 int u8val = *(unsigned char *) src;
3237 float dval;
3239 if (u8val < min)
3240 dval = min_val;
3241 else if (u8val > max)
3242 dval = max_val;
3243 else
3244 dval = (u8val - min) / (float) (max - min) * (max_val - min_val) + min_val;
3246 (*(float *) dst) = dval;
3248 dst += dst_pitch;
3249 src += src_pitch;
3253 #define MAKE_CONVERSIONS(name, min_val, max_val, min, max) \
3254 static void \
3255 convert_ ## name ## _float (const Babl *c, char *src, \
3256 char *dst, \
3257 int src_pitch, \
3258 int dst_pitch, \
3259 long n) \
3261 convert_u8_float_scaled (c, min_val, max_val, min, max, \
3262 src, dst, src_pitch, dst_pitch, n); \
3264 static void \
3265 convert_float_ ## name (const Babl *c, char *src, \
3266 char *dst, \
3267 int src_pitch, \
3268 int dst_pitch, \
3269 long n) \
3271 convert_float_u8_scaled (c, min_val, max_val, min, max, \
3272 src, dst, src_pitch, dst_pitch, n); \
3275 /* source ICC.1:2004-10 */
3277 MAKE_CONVERSIONS (u8_l, 0.0, 100.0, 0x00, 0xff)
3278 MAKE_CONVERSIONS (u8_ab, -128.0, 127.0, 0x00, 0xff)
3280 #undef MAKE_CONVERSIONS
3282 static void
3283 types_u8 (void)
3285 babl_type_new (
3286 "CIE u8 L",
3287 "integer",
3288 "unsigned",
3289 "bits", 8,
3290 "min_val", 0.0,
3291 "max_val", 100.0,
3292 NULL
3295 babl_type_new (
3296 "CIE u8 ab",
3297 "integer",
3298 "unsigned",
3299 "bits", 8,
3300 "min_val", -128.0,
3301 "max_val", 127.0,
3302 NULL
3305 babl_conversion_new (
3306 babl_type ("CIE u8 L"),
3307 babl_type ("double"),
3308 "plane", convert_u8_l_double,
3309 NULL
3311 babl_conversion_new (
3312 babl_type ("double"),
3313 babl_type ("CIE u8 L"),
3314 "plane", convert_double_u8_l,
3315 NULL
3318 babl_conversion_new (
3319 babl_type ("CIE u8 ab"),
3320 babl_type ("double"),
3321 "plane", convert_u8_ab_double,
3322 NULL
3324 babl_conversion_new (
3325 babl_type ("double"),
3326 babl_type ("CIE u8 ab"),
3327 "plane", convert_double_u8_ab,
3328 NULL
3331 babl_conversion_new (
3332 babl_type ("CIE u8 L"),
3333 babl_type ("float"),
3334 "plane", convert_u8_l_float,
3335 NULL
3337 babl_conversion_new (
3338 babl_type ("float"),
3339 babl_type ("CIE u8 L"),
3340 "plane", convert_float_u8_l,
3341 NULL
3344 babl_conversion_new (
3345 babl_type ("CIE u8 ab"),
3346 babl_type ("float"),
3347 "plane", convert_u8_ab_float,
3348 NULL
3350 babl_conversion_new (
3351 babl_type ("float"),
3352 babl_type ("CIE u8 ab"),
3353 "plane", convert_float_u8_ab,
3354 NULL
3358 static inline void
3359 convert_double_u16_scaled (const Babl *conversion,
3360 double min_val,
3361 double max_val,
3362 unsigned short min,
3363 unsigned short max,
3364 char *src,
3365 char *dst,
3366 int src_pitch,
3367 int dst_pitch,
3368 long n)
3370 while (n--)
3372 double dval = *(double *) src;
3373 unsigned short u16val;
3375 if (dval < min_val)
3376 u16val = min;
3377 else if (dval > max_val)
3378 u16val = max;
3379 else
3380 u16val = ((dval - min_val) / (max_val - min_val) * (max - min) + min) + 0.5f;
3382 *(unsigned short *) dst = u16val;
3383 dst += dst_pitch;
3384 src += src_pitch;
3388 static inline void
3389 convert_u16_double_scaled (const Babl *conversion,
3390 double min_val,
3391 double max_val,
3392 unsigned short min,
3393 unsigned short max,
3394 char *src,
3395 char *dst,
3396 int src_pitch,
3397 int dst_pitch,
3398 long n)
3400 while (n--)
3402 int u16val = *(unsigned short *) src;
3403 double dval;
3405 if (u16val < min)
3406 dval = min_val;
3407 else if (u16val > max)
3408 dval = max_val;
3409 else
3410 dval = (u16val - min) / (double) (max - min) * (max_val - min_val) + min_val;
3412 (*(double *) dst) = dval;
3413 dst += dst_pitch;
3414 src += src_pitch;
3418 #define MAKE_CONVERSIONS(name, min_val, max_val, min, max) \
3419 static void \
3420 convert_ ## name ## _double (const Babl *c, char *src, \
3421 char *dst, \
3422 int src_pitch, \
3423 int dst_pitch, \
3424 long n) \
3426 convert_u16_double_scaled (c, min_val, max_val, min, max, \
3427 src, dst, src_pitch, dst_pitch, n); \
3429 static void \
3430 convert_double_ ## name (const Babl *c, char *src, \
3431 char *dst, \
3432 int src_pitch, \
3433 int dst_pitch, \
3434 long n) \
3436 convert_double_u16_scaled (c, min_val, max_val, min, max, \
3437 src, dst, src_pitch, dst_pitch, n); \
3440 MAKE_CONVERSIONS (u16_l, 0.0, 100.0, 0x00, 0xffff)
3441 MAKE_CONVERSIONS (u16_ab, -128.0, 127.0, 0x00, 0xffff)
3443 #undef MAKE_CONVERSIONS
3446 static inline void
3447 convert_float_u16_scaled (const Babl *conversion,
3448 float min_val,
3449 float max_val,
3450 unsigned short min,
3451 unsigned short max,
3452 char *src,
3453 char *dst,
3454 int src_pitch,
3455 int dst_pitch,
3456 long n)
3458 while (n--)
3460 float dval = *(float *) src;
3461 unsigned short u16val;
3463 if (dval < min_val)
3464 u16val = min;
3465 else if (dval > max_val)
3466 u16val = max;
3467 else
3468 u16val = ((dval - min_val) / (max_val - min_val) * (max - min) + min) + 0.5f;
3470 *(unsigned short *) dst = u16val;
3471 dst += dst_pitch;
3472 src += src_pitch;
3476 static inline void
3477 convert_u16_float_scaled (const Babl *conversion,
3478 float min_val,
3479 float max_val,
3480 unsigned short min,
3481 unsigned short max,
3482 char *src,
3483 char *dst,
3484 int src_pitch,
3485 int dst_pitch,
3486 long n)
3488 while (n--)
3490 int u16val = *(unsigned short *) src;
3491 float dval;
3493 if (u16val < min)
3494 dval = min_val;
3495 else if (u16val > max)
3496 dval = max_val;
3497 else
3498 dval = (u16val - min) / (float) (max - min) * (max_val - min_val) + min_val;
3500 (*(float *) dst) = dval;
3501 dst += dst_pitch;
3502 src += src_pitch;
3506 #define MAKE_CONVERSIONS(name, min_val, max_val, min, max) \
3507 static void \
3508 convert_ ## name ## _float (const Babl *c, char *src, \
3509 char *dst, \
3510 int src_pitch, \
3511 int dst_pitch, \
3512 long n) \
3514 convert_u16_float_scaled (c, min_val, max_val, min, max, \
3515 src, dst, src_pitch, dst_pitch, n); \
3517 static void \
3518 convert_float_ ## name (const Babl *c, char *src, \
3519 char *dst, \
3520 int src_pitch, \
3521 int dst_pitch, \
3522 long n) \
3524 convert_float_u16_scaled (c, min_val, max_val, min, max, \
3525 src, dst, src_pitch, dst_pitch, n); \
3528 MAKE_CONVERSIONS (u16_l, 0.0, 100.0, 0x00, 0xffff)
3529 MAKE_CONVERSIONS (u16_ab, -128.0, 127.0, 0x00, 0xffff)
3531 #undef MAKE_CONVERSIONS
3533 static void
3534 types_u16 (void)
3536 babl_type_new (
3537 "CIE u16 L",
3538 "integer",
3539 "unsigned",
3540 "bits", 16,
3541 "min_val", 0.0,
3542 "max_val", 100.0,
3543 NULL
3546 babl_type_new (
3547 "CIE u16 ab",
3548 "integer",
3549 "unsigned",
3550 "bits", 16,
3551 "min_val", -128.0,
3552 "max_val", 127.0,
3553 NULL
3557 babl_conversion_new (
3558 babl_type ("CIE u16 L"),
3559 babl_type ("double"),
3560 "plane", convert_u16_l_double,
3561 NULL
3563 babl_conversion_new (
3564 babl_type ("double"),
3565 babl_type ("CIE u16 L"),
3566 "plane", convert_double_u16_l,
3567 NULL
3570 babl_conversion_new (
3571 babl_type ("CIE u16 ab"),
3572 babl_type ("double"),
3573 "plane", convert_u16_ab_double,
3574 NULL
3576 babl_conversion_new (
3577 babl_type ("double"),
3578 babl_type ("CIE u16 ab"),
3579 "plane", convert_double_u16_ab,
3580 NULL
3583 babl_conversion_new (
3584 babl_type ("CIE u16 L"),
3585 babl_type ("float"),
3586 "plane", convert_u16_l_float,
3587 NULL
3589 babl_conversion_new (
3590 babl_type ("float"),
3591 babl_type ("CIE u16 L"),
3592 "plane", convert_float_u16_l,
3593 NULL
3596 babl_conversion_new (
3597 babl_type ("CIE u16 ab"),
3598 babl_type ("float"),
3599 "plane", convert_u16_ab_float,
3600 NULL
3602 babl_conversion_new (
3603 babl_type ("float"),
3604 babl_type ("CIE u16 ab"),
3605 "plane", convert_float_u16_ab,
3606 NULL
3610 static void
3611 types (void)
3613 types_u8 ();
3614 types_u16 ();
3617 /******** end integer RGB/CIE color space conversions ****************/
3619 static void
3620 rgbxyzrgb_init (void)
3624 static void
3625 rgbcie_init (void)
3627 static int initialized = 0;
3629 if (!initialized)
3631 rgbxyzrgb_init ();
3632 initialized = 1;