/src/libvips/libvips/colour/Oklab2XYZ.c
Line | Count | Source |
1 | | /* Oklab to XYZ. |
2 | | * |
3 | | */ |
4 | | |
5 | | /* |
6 | | |
7 | | This file is part of VIPS. |
8 | | |
9 | | VIPS is free software; you can redistribute it and/or modify |
10 | | it under the terms of the GNU Lesser General Public License as published by |
11 | | the Free Software Foundation; either version 2 of the License, or |
12 | | (at your option) any later version. |
13 | | |
14 | | This program is distributed in the hope that it will be useful, |
15 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | GNU Lesser General Public License for more details. |
18 | | |
19 | | You should have received a copy of the GNU Lesser General Public License |
20 | | along with this program; if not, write to the Free Software |
21 | | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
22 | | 02110-1301 USA |
23 | | |
24 | | */ |
25 | | |
26 | | /* |
27 | | |
28 | | These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk |
29 | | |
30 | | */ |
31 | | |
32 | | /* |
33 | | #define VIPS_DEBUG |
34 | | */ |
35 | | |
36 | | #ifdef HAVE_CONFIG_H |
37 | | #include <config.h> |
38 | | #endif /*HAVE_CONFIG_H*/ |
39 | | #include <glib/gi18n-lib.h> |
40 | | |
41 | | #include <stdio.h> |
42 | | #include <math.h> |
43 | | |
44 | | #include <vips/vips.h> |
45 | | #include <vips/debug.h> |
46 | | |
47 | | #include "pcolour.h" |
48 | | |
49 | | typedef VipsColourTransform VipsOklab2XYZ; |
50 | | typedef VipsColourTransformClass VipsOklab2XYZClass; |
51 | | |
52 | 36 | G_DEFINE_TYPE(VipsOklab2XYZ, vips_Oklab2XYZ, VIPS_TYPE_COLOUR_TRANSFORM); |
53 | 36 | |
54 | 36 | /* Process a buffer of data. |
55 | 36 | */ |
56 | 36 | static void |
57 | 36 | vips_Oklab2XYZ_line(VipsColour *colour, VipsPel *out, VipsPel **in, int width) |
58 | 36 | { |
59 | 3 | float *restrict p = (float *) in[0]; |
60 | 3 | float *restrict q = (float *) out; |
61 | | |
62 | 7 | for (int x = 0; x < width; x++) { |
63 | 4 | const float L = p[0]; |
64 | 4 | const float a = p[1]; |
65 | 4 | const float b = p[2]; |
66 | 4 | p += 3; |
67 | | |
68 | | // M2 inv to get LMS prime |
69 | 4 | const float lp = L * 1. + a * 0.39633779 + b * 0.21580376; |
70 | 4 | const float mp = L * 1.00000001 + a * -0.10556134 + b * -0.06385417; |
71 | 4 | const float sp = L * 1.00000005 + a * -0.08948418 + b * -1.29148554; |
72 | | |
73 | | // back to lms |
74 | 4 | const float l = lp * lp * lp; |
75 | 4 | const float m = mp * mp * mp; |
76 | 4 | const float s = sp * sp * sp; |
77 | | |
78 | | // M1 inv to get D65 normalised XYZ |
79 | 4 | float X = l * 1.22701385 + m * -0.55779998 + s * 0.28125615; |
80 | 4 | float Y = l * -0.04058018 + m * 1.11225687 + s * -0.07167668; |
81 | 4 | float Z = l * -0.07638128 + m * -0.42148198 + s * 1.58616322; |
82 | | |
83 | 4 | q[0] = X * 100.0; |
84 | 4 | q[1] = Y * 100.0; |
85 | 4 | q[2] = Z * 100.0; |
86 | 4 | q += 3; |
87 | 4 | } |
88 | 3 | } |
89 | | |
90 | | static void |
91 | | vips_Oklab2XYZ_class_init(VipsOklab2XYZClass *class) |
92 | 18 | { |
93 | 18 | VipsObjectClass *object_class = (VipsObjectClass *) class; |
94 | 18 | VipsColourClass *colour_class = VIPS_COLOUR_CLASS(class); |
95 | | |
96 | 18 | object_class->nickname = "Oklab2XYZ"; |
97 | 18 | object_class->description = _("transform Oklab to XYZ"); |
98 | | |
99 | 18 | colour_class->process_line = vips_Oklab2XYZ_line; |
100 | 18 | } |
101 | | |
102 | | static void |
103 | | vips_Oklab2XYZ_init(VipsOklab2XYZ *Oklab2XYZ) |
104 | 3 | { |
105 | 3 | VipsColour *colour = VIPS_COLOUR(Oklab2XYZ); |
106 | | |
107 | 3 | colour->interpretation = VIPS_INTERPRETATION_XYZ; |
108 | 3 | } |
109 | | |
110 | | /** |
111 | | * vips_Oklab2XYZ: (method) |
112 | | * @in: input image |
113 | | * @out: (out): output image |
114 | | * @...: `NULL`-terminated list of optional named arguments |
115 | | * |
116 | | * Transform Oklab to XYZ using D65 illuminant. |
117 | | * |
118 | | * Returns: 0 on success, -1 on error |
119 | | */ |
120 | | int |
121 | | vips_Oklab2XYZ(VipsImage *in, VipsImage **out, ...) |
122 | 3 | { |
123 | 3 | va_list ap; |
124 | 3 | int result; |
125 | | |
126 | 3 | va_start(ap, out); |
127 | 3 | result = vips_call_split("Oklab2XYZ", ap, in, out); |
128 | 3 | va_end(ap); |
129 | | |
130 | 3 | return result; |
131 | 3 | } |