xref: /aosp_15_r20/external/pdfium/third_party/lcms/src/cmspcs.c (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker //---------------------------------------------------------------------------------
2*3ac0a46fSAndroid Build Coastguard Worker //
3*3ac0a46fSAndroid Build Coastguard Worker //  Little Color Management System
4*3ac0a46fSAndroid Build Coastguard Worker //  Copyright (c) 1998-2023 Marti Maria Saguer
5*3ac0a46fSAndroid Build Coastguard Worker //
6*3ac0a46fSAndroid Build Coastguard Worker // Permission is hereby granted, free of charge, to any person obtaining
7*3ac0a46fSAndroid Build Coastguard Worker // a copy of this software and associated documentation files (the "Software"),
8*3ac0a46fSAndroid Build Coastguard Worker // to deal in the Software without restriction, including without limitation
9*3ac0a46fSAndroid Build Coastguard Worker // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*3ac0a46fSAndroid Build Coastguard Worker // and/or sell copies of the Software, and to permit persons to whom the Software
11*3ac0a46fSAndroid Build Coastguard Worker // is furnished to do so, subject to the following conditions:
12*3ac0a46fSAndroid Build Coastguard Worker //
13*3ac0a46fSAndroid Build Coastguard Worker // The above copyright notice and this permission notice shall be included in
14*3ac0a46fSAndroid Build Coastguard Worker // all copies or substantial portions of the Software.
15*3ac0a46fSAndroid Build Coastguard Worker //
16*3ac0a46fSAndroid Build Coastguard Worker // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*3ac0a46fSAndroid Build Coastguard Worker // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18*3ac0a46fSAndroid Build Coastguard Worker // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*3ac0a46fSAndroid Build Coastguard Worker // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20*3ac0a46fSAndroid Build Coastguard Worker // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21*3ac0a46fSAndroid Build Coastguard Worker // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22*3ac0a46fSAndroid Build Coastguard Worker // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23*3ac0a46fSAndroid Build Coastguard Worker //
24*3ac0a46fSAndroid Build Coastguard Worker //---------------------------------------------------------------------------------
25*3ac0a46fSAndroid Build Coastguard Worker //
26*3ac0a46fSAndroid Build Coastguard Worker 
27*3ac0a46fSAndroid Build Coastguard Worker #include "lcms2_internal.h"
28*3ac0a46fSAndroid Build Coastguard Worker 
29*3ac0a46fSAndroid Build Coastguard Worker //      inter PCS conversions XYZ <-> CIE L* a* b*
30*3ac0a46fSAndroid Build Coastguard Worker /*
31*3ac0a46fSAndroid Build Coastguard Worker 
32*3ac0a46fSAndroid Build Coastguard Worker 
33*3ac0a46fSAndroid Build Coastguard Worker        CIE 15:2004 CIELab is defined as:
34*3ac0a46fSAndroid Build Coastguard Worker 
35*3ac0a46fSAndroid Build Coastguard Worker        L* = 116*f(Y/Yn) - 16                     0 <= L* <= 100
36*3ac0a46fSAndroid Build Coastguard Worker        a* = 500*[f(X/Xn) - f(Y/Yn)]
37*3ac0a46fSAndroid Build Coastguard Worker        b* = 200*[f(Y/Yn) - f(Z/Zn)]
38*3ac0a46fSAndroid Build Coastguard Worker 
39*3ac0a46fSAndroid Build Coastguard Worker        and
40*3ac0a46fSAndroid Build Coastguard Worker 
41*3ac0a46fSAndroid Build Coastguard Worker               f(t) = t^(1/3)                     1 >= t >  (24/116)^3
42*3ac0a46fSAndroid Build Coastguard Worker                      (841/108)*t + (16/116)      0 <= t <= (24/116)^3
43*3ac0a46fSAndroid Build Coastguard Worker 
44*3ac0a46fSAndroid Build Coastguard Worker 
45*3ac0a46fSAndroid Build Coastguard Worker        Reverse transform is:
46*3ac0a46fSAndroid Build Coastguard Worker 
47*3ac0a46fSAndroid Build Coastguard Worker        X = Xn*[a* / 500 + (L* + 16) / 116] ^ 3   if (X/Xn) > (24/116)
48*3ac0a46fSAndroid Build Coastguard Worker          = Xn*(a* / 500 + L* / 116) / 7.787      if (X/Xn) <= (24/116)
49*3ac0a46fSAndroid Build Coastguard Worker 
50*3ac0a46fSAndroid Build Coastguard Worker 
51*3ac0a46fSAndroid Build Coastguard Worker 
52*3ac0a46fSAndroid Build Coastguard Worker        PCS in Lab2 is encoded as:
53*3ac0a46fSAndroid Build Coastguard Worker 
54*3ac0a46fSAndroid Build Coastguard Worker               8 bit Lab PCS:
55*3ac0a46fSAndroid Build Coastguard Worker 
56*3ac0a46fSAndroid Build Coastguard Worker                      L*      0..100 into a 0..ff byte.
57*3ac0a46fSAndroid Build Coastguard Worker                      a*      t + 128 range is -128.0  +127.0
58*3ac0a46fSAndroid Build Coastguard Worker                      b*
59*3ac0a46fSAndroid Build Coastguard Worker 
60*3ac0a46fSAndroid Build Coastguard Worker              16 bit Lab PCS:
61*3ac0a46fSAndroid Build Coastguard Worker 
62*3ac0a46fSAndroid Build Coastguard Worker                      L*     0..100  into a 0..ff00 word.
63*3ac0a46fSAndroid Build Coastguard Worker                      a*     t + 128  range is  -128.0  +127.9961
64*3ac0a46fSAndroid Build Coastguard Worker                      b*
65*3ac0a46fSAndroid Build Coastguard Worker 
66*3ac0a46fSAndroid Build Coastguard Worker 
67*3ac0a46fSAndroid Build Coastguard Worker 
68*3ac0a46fSAndroid Build Coastguard Worker Interchange Space   Component     Actual Range        Encoded Range
69*3ac0a46fSAndroid Build Coastguard Worker CIE XYZ             X             0 -> 1.99997        0x0000 -> 0xffff
70*3ac0a46fSAndroid Build Coastguard Worker CIE XYZ             Y             0 -> 1.99997        0x0000 -> 0xffff
71*3ac0a46fSAndroid Build Coastguard Worker CIE XYZ             Z             0 -> 1.99997        0x0000 -> 0xffff
72*3ac0a46fSAndroid Build Coastguard Worker 
73*3ac0a46fSAndroid Build Coastguard Worker Version 2,3
74*3ac0a46fSAndroid Build Coastguard Worker -----------
75*3ac0a46fSAndroid Build Coastguard Worker 
76*3ac0a46fSAndroid Build Coastguard Worker CIELAB (16 bit)     L*            0 -> 100.0          0x0000 -> 0xff00
77*3ac0a46fSAndroid Build Coastguard Worker CIELAB (16 bit)     a*            -128.0 -> +127.996  0x0000 -> 0x8000 -> 0xffff
78*3ac0a46fSAndroid Build Coastguard Worker CIELAB (16 bit)     b*            -128.0 -> +127.996  0x0000 -> 0x8000 -> 0xffff
79*3ac0a46fSAndroid Build Coastguard Worker 
80*3ac0a46fSAndroid Build Coastguard Worker 
81*3ac0a46fSAndroid Build Coastguard Worker Version 4
82*3ac0a46fSAndroid Build Coastguard Worker ---------
83*3ac0a46fSAndroid Build Coastguard Worker 
84*3ac0a46fSAndroid Build Coastguard Worker CIELAB (16 bit)     L*            0 -> 100.0          0x0000 -> 0xffff
85*3ac0a46fSAndroid Build Coastguard Worker CIELAB (16 bit)     a*            -128.0 -> +127      0x0000 -> 0x8080 -> 0xffff
86*3ac0a46fSAndroid Build Coastguard Worker CIELAB (16 bit)     b*            -128.0 -> +127      0x0000 -> 0x8080 -> 0xffff
87*3ac0a46fSAndroid Build Coastguard Worker 
88*3ac0a46fSAndroid Build Coastguard Worker */
89*3ac0a46fSAndroid Build Coastguard Worker 
90*3ac0a46fSAndroid Build Coastguard Worker // Conversions
cmsXYZ2xyY(cmsCIExyY * Dest,const cmsCIEXYZ * Source)91*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsXYZ2xyY(cmsCIExyY* Dest, const cmsCIEXYZ* Source)
92*3ac0a46fSAndroid Build Coastguard Worker {
93*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number ISum;
94*3ac0a46fSAndroid Build Coastguard Worker 
95*3ac0a46fSAndroid Build Coastguard Worker     ISum = 1./(Source -> X + Source -> Y + Source -> Z);
96*3ac0a46fSAndroid Build Coastguard Worker 
97*3ac0a46fSAndroid Build Coastguard Worker     Dest -> x = (Source -> X) * ISum;
98*3ac0a46fSAndroid Build Coastguard Worker     Dest -> y = (Source -> Y) * ISum;
99*3ac0a46fSAndroid Build Coastguard Worker     Dest -> Y = Source -> Y;
100*3ac0a46fSAndroid Build Coastguard Worker }
101*3ac0a46fSAndroid Build Coastguard Worker 
cmsxyY2XYZ(cmsCIEXYZ * Dest,const cmsCIExyY * Source)102*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsxyY2XYZ(cmsCIEXYZ* Dest, const cmsCIExyY* Source)
103*3ac0a46fSAndroid Build Coastguard Worker {
104*3ac0a46fSAndroid Build Coastguard Worker     Dest -> X = (Source -> x / Source -> y) * Source -> Y;
105*3ac0a46fSAndroid Build Coastguard Worker     Dest -> Y = Source -> Y;
106*3ac0a46fSAndroid Build Coastguard Worker     Dest -> Z = ((1 - Source -> x - Source -> y) / Source -> y) * Source -> Y;
107*3ac0a46fSAndroid Build Coastguard Worker }
108*3ac0a46fSAndroid Build Coastguard Worker 
109*3ac0a46fSAndroid Build Coastguard Worker /*
110*3ac0a46fSAndroid Build Coastguard Worker        The break point (24/116)^3 = (6/29)^3 is a very small amount of tristimulus
111*3ac0a46fSAndroid Build Coastguard Worker        primary (0.008856).  Generally, this only happens for
112*3ac0a46fSAndroid Build Coastguard Worker        nearly ideal blacks and for some orange / amber colors in transmission mode.
113*3ac0a46fSAndroid Build Coastguard Worker        For example, the Z value of the orange turn indicator lamp lens on an
114*3ac0a46fSAndroid Build Coastguard Worker        automobile will often be below this value.  But the Z does not
115*3ac0a46fSAndroid Build Coastguard Worker        contribute to the perceived color directly.
116*3ac0a46fSAndroid Build Coastguard Worker */
117*3ac0a46fSAndroid Build Coastguard Worker 
118*3ac0a46fSAndroid Build Coastguard Worker static
f(cmsFloat64Number t)119*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number f(cmsFloat64Number t)
120*3ac0a46fSAndroid Build Coastguard Worker {
121*3ac0a46fSAndroid Build Coastguard Worker     const cmsFloat64Number Limit = (24.0/116.0) * (24.0/116.0) * (24.0/116.0);
122*3ac0a46fSAndroid Build Coastguard Worker 
123*3ac0a46fSAndroid Build Coastguard Worker     if (t <= Limit)
124*3ac0a46fSAndroid Build Coastguard Worker         return (841.0/108.0) * t + (16.0/116.0);
125*3ac0a46fSAndroid Build Coastguard Worker     else
126*3ac0a46fSAndroid Build Coastguard Worker         return pow(t, 1.0/3.0);
127*3ac0a46fSAndroid Build Coastguard Worker }
128*3ac0a46fSAndroid Build Coastguard Worker 
129*3ac0a46fSAndroid Build Coastguard Worker static
f_1(cmsFloat64Number t)130*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number f_1(cmsFloat64Number t)
131*3ac0a46fSAndroid Build Coastguard Worker {
132*3ac0a46fSAndroid Build Coastguard Worker     const cmsFloat64Number Limit = (24.0/116.0);
133*3ac0a46fSAndroid Build Coastguard Worker 
134*3ac0a46fSAndroid Build Coastguard Worker     if (t <= Limit) {
135*3ac0a46fSAndroid Build Coastguard Worker         return (108.0/841.0) * (t - (16.0/116.0));
136*3ac0a46fSAndroid Build Coastguard Worker     }
137*3ac0a46fSAndroid Build Coastguard Worker 
138*3ac0a46fSAndroid Build Coastguard Worker     return t * t * t;
139*3ac0a46fSAndroid Build Coastguard Worker }
140*3ac0a46fSAndroid Build Coastguard Worker 
141*3ac0a46fSAndroid Build Coastguard Worker 
142*3ac0a46fSAndroid Build Coastguard Worker // Standard XYZ to Lab. it can handle negative XZY numbers in some cases
cmsXYZ2Lab(const cmsCIEXYZ * WhitePoint,cmsCIELab * Lab,const cmsCIEXYZ * xyz)143*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsXYZ2Lab(const cmsCIEXYZ* WhitePoint, cmsCIELab* Lab, const cmsCIEXYZ* xyz)
144*3ac0a46fSAndroid Build Coastguard Worker {
145*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number fx, fy, fz;
146*3ac0a46fSAndroid Build Coastguard Worker 
147*3ac0a46fSAndroid Build Coastguard Worker     if (WhitePoint == NULL)
148*3ac0a46fSAndroid Build Coastguard Worker         WhitePoint = cmsD50_XYZ();
149*3ac0a46fSAndroid Build Coastguard Worker 
150*3ac0a46fSAndroid Build Coastguard Worker     fx = f(xyz->X / WhitePoint->X);
151*3ac0a46fSAndroid Build Coastguard Worker     fy = f(xyz->Y / WhitePoint->Y);
152*3ac0a46fSAndroid Build Coastguard Worker     fz = f(xyz->Z / WhitePoint->Z);
153*3ac0a46fSAndroid Build Coastguard Worker 
154*3ac0a46fSAndroid Build Coastguard Worker     Lab->L = 116.0*fy - 16.0;
155*3ac0a46fSAndroid Build Coastguard Worker     Lab->a = 500.0*(fx - fy);
156*3ac0a46fSAndroid Build Coastguard Worker     Lab->b = 200.0*(fy - fz);
157*3ac0a46fSAndroid Build Coastguard Worker }
158*3ac0a46fSAndroid Build Coastguard Worker 
159*3ac0a46fSAndroid Build Coastguard Worker 
160*3ac0a46fSAndroid Build Coastguard Worker // Standard XYZ to Lab. It can return negative XYZ in some cases
cmsLab2XYZ(const cmsCIEXYZ * WhitePoint,cmsCIEXYZ * xyz,const cmsCIELab * Lab)161*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsLab2XYZ(const cmsCIEXYZ* WhitePoint, cmsCIEXYZ* xyz,  const cmsCIELab* Lab)
162*3ac0a46fSAndroid Build Coastguard Worker {
163*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number x, y, z;
164*3ac0a46fSAndroid Build Coastguard Worker 
165*3ac0a46fSAndroid Build Coastguard Worker     if (WhitePoint == NULL)
166*3ac0a46fSAndroid Build Coastguard Worker         WhitePoint = cmsD50_XYZ();
167*3ac0a46fSAndroid Build Coastguard Worker 
168*3ac0a46fSAndroid Build Coastguard Worker     y = (Lab-> L + 16.0) / 116.0;
169*3ac0a46fSAndroid Build Coastguard Worker     x = y + 0.002 * Lab -> a;
170*3ac0a46fSAndroid Build Coastguard Worker     z = y - 0.005 * Lab -> b;
171*3ac0a46fSAndroid Build Coastguard Worker 
172*3ac0a46fSAndroid Build Coastguard Worker     xyz -> X = f_1(x) * WhitePoint -> X;
173*3ac0a46fSAndroid Build Coastguard Worker     xyz -> Y = f_1(y) * WhitePoint -> Y;
174*3ac0a46fSAndroid Build Coastguard Worker     xyz -> Z = f_1(z) * WhitePoint -> Z;
175*3ac0a46fSAndroid Build Coastguard Worker 
176*3ac0a46fSAndroid Build Coastguard Worker }
177*3ac0a46fSAndroid Build Coastguard Worker 
178*3ac0a46fSAndroid Build Coastguard Worker static
L2float2(cmsUInt16Number v)179*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number L2float2(cmsUInt16Number v)
180*3ac0a46fSAndroid Build Coastguard Worker {
181*3ac0a46fSAndroid Build Coastguard Worker     return (cmsFloat64Number) v / 652.800;
182*3ac0a46fSAndroid Build Coastguard Worker }
183*3ac0a46fSAndroid Build Coastguard Worker 
184*3ac0a46fSAndroid Build Coastguard Worker // the a/b part
185*3ac0a46fSAndroid Build Coastguard Worker static
ab2float2(cmsUInt16Number v)186*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number ab2float2(cmsUInt16Number v)
187*3ac0a46fSAndroid Build Coastguard Worker {
188*3ac0a46fSAndroid Build Coastguard Worker     return ((cmsFloat64Number) v / 256.0) - 128.0;
189*3ac0a46fSAndroid Build Coastguard Worker }
190*3ac0a46fSAndroid Build Coastguard Worker 
191*3ac0a46fSAndroid Build Coastguard Worker static
L2Fix2(cmsFloat64Number L)192*3ac0a46fSAndroid Build Coastguard Worker cmsUInt16Number L2Fix2(cmsFloat64Number L)
193*3ac0a46fSAndroid Build Coastguard Worker {
194*3ac0a46fSAndroid Build Coastguard Worker     return _cmsQuickSaturateWord(L *  652.8);
195*3ac0a46fSAndroid Build Coastguard Worker }
196*3ac0a46fSAndroid Build Coastguard Worker 
197*3ac0a46fSAndroid Build Coastguard Worker static
ab2Fix2(cmsFloat64Number ab)198*3ac0a46fSAndroid Build Coastguard Worker cmsUInt16Number ab2Fix2(cmsFloat64Number ab)
199*3ac0a46fSAndroid Build Coastguard Worker {
200*3ac0a46fSAndroid Build Coastguard Worker     return _cmsQuickSaturateWord((ab + 128.0) * 256.0);
201*3ac0a46fSAndroid Build Coastguard Worker }
202*3ac0a46fSAndroid Build Coastguard Worker 
203*3ac0a46fSAndroid Build Coastguard Worker 
204*3ac0a46fSAndroid Build Coastguard Worker static
L2float4(cmsUInt16Number v)205*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number L2float4(cmsUInt16Number v)
206*3ac0a46fSAndroid Build Coastguard Worker {
207*3ac0a46fSAndroid Build Coastguard Worker     return (cmsFloat64Number) v / 655.35;
208*3ac0a46fSAndroid Build Coastguard Worker }
209*3ac0a46fSAndroid Build Coastguard Worker 
210*3ac0a46fSAndroid Build Coastguard Worker // the a/b part
211*3ac0a46fSAndroid Build Coastguard Worker static
ab2float4(cmsUInt16Number v)212*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number ab2float4(cmsUInt16Number v)
213*3ac0a46fSAndroid Build Coastguard Worker {
214*3ac0a46fSAndroid Build Coastguard Worker     return ((cmsFloat64Number) v / 257.0) - 128.0;
215*3ac0a46fSAndroid Build Coastguard Worker }
216*3ac0a46fSAndroid Build Coastguard Worker 
217*3ac0a46fSAndroid Build Coastguard Worker 
cmsLabEncoded2FloatV2(cmsCIELab * Lab,const cmsUInt16Number wLab[3])218*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsLabEncoded2FloatV2(cmsCIELab* Lab, const cmsUInt16Number wLab[3])
219*3ac0a46fSAndroid Build Coastguard Worker {
220*3ac0a46fSAndroid Build Coastguard Worker         Lab->L = L2float2(wLab[0]);
221*3ac0a46fSAndroid Build Coastguard Worker         Lab->a = ab2float2(wLab[1]);
222*3ac0a46fSAndroid Build Coastguard Worker         Lab->b = ab2float2(wLab[2]);
223*3ac0a46fSAndroid Build Coastguard Worker }
224*3ac0a46fSAndroid Build Coastguard Worker 
225*3ac0a46fSAndroid Build Coastguard Worker 
cmsLabEncoded2Float(cmsCIELab * Lab,const cmsUInt16Number wLab[3])226*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsLabEncoded2Float(cmsCIELab* Lab, const cmsUInt16Number wLab[3])
227*3ac0a46fSAndroid Build Coastguard Worker {
228*3ac0a46fSAndroid Build Coastguard Worker         Lab->L = L2float4(wLab[0]);
229*3ac0a46fSAndroid Build Coastguard Worker         Lab->a = ab2float4(wLab[1]);
230*3ac0a46fSAndroid Build Coastguard Worker         Lab->b = ab2float4(wLab[2]);
231*3ac0a46fSAndroid Build Coastguard Worker }
232*3ac0a46fSAndroid Build Coastguard Worker 
233*3ac0a46fSAndroid Build Coastguard Worker static
Clamp_L_doubleV2(cmsFloat64Number L)234*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number Clamp_L_doubleV2(cmsFloat64Number L)
235*3ac0a46fSAndroid Build Coastguard Worker {
236*3ac0a46fSAndroid Build Coastguard Worker     const cmsFloat64Number L_max = (cmsFloat64Number) (0xFFFF * 100.0) / 0xFF00;
237*3ac0a46fSAndroid Build Coastguard Worker 
238*3ac0a46fSAndroid Build Coastguard Worker     if (L < 0) L = 0;
239*3ac0a46fSAndroid Build Coastguard Worker     if (L > L_max) L = L_max;
240*3ac0a46fSAndroid Build Coastguard Worker 
241*3ac0a46fSAndroid Build Coastguard Worker     return L;
242*3ac0a46fSAndroid Build Coastguard Worker }
243*3ac0a46fSAndroid Build Coastguard Worker 
244*3ac0a46fSAndroid Build Coastguard Worker 
245*3ac0a46fSAndroid Build Coastguard Worker static
Clamp_ab_doubleV2(cmsFloat64Number ab)246*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number Clamp_ab_doubleV2(cmsFloat64Number ab)
247*3ac0a46fSAndroid Build Coastguard Worker {
248*3ac0a46fSAndroid Build Coastguard Worker     if (ab < MIN_ENCODEABLE_ab2) ab = MIN_ENCODEABLE_ab2;
249*3ac0a46fSAndroid Build Coastguard Worker     if (ab > MAX_ENCODEABLE_ab2) ab = MAX_ENCODEABLE_ab2;
250*3ac0a46fSAndroid Build Coastguard Worker 
251*3ac0a46fSAndroid Build Coastguard Worker     return ab;
252*3ac0a46fSAndroid Build Coastguard Worker }
253*3ac0a46fSAndroid Build Coastguard Worker 
cmsFloat2LabEncodedV2(cmsUInt16Number wLab[3],const cmsCIELab * fLab)254*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsFloat2LabEncodedV2(cmsUInt16Number wLab[3], const cmsCIELab* fLab)
255*3ac0a46fSAndroid Build Coastguard Worker {
256*3ac0a46fSAndroid Build Coastguard Worker     cmsCIELab Lab;
257*3ac0a46fSAndroid Build Coastguard Worker 
258*3ac0a46fSAndroid Build Coastguard Worker     Lab.L = Clamp_L_doubleV2(fLab ->L);
259*3ac0a46fSAndroid Build Coastguard Worker     Lab.a = Clamp_ab_doubleV2(fLab ->a);
260*3ac0a46fSAndroid Build Coastguard Worker     Lab.b = Clamp_ab_doubleV2(fLab ->b);
261*3ac0a46fSAndroid Build Coastguard Worker 
262*3ac0a46fSAndroid Build Coastguard Worker     wLab[0] = L2Fix2(Lab.L);
263*3ac0a46fSAndroid Build Coastguard Worker     wLab[1] = ab2Fix2(Lab.a);
264*3ac0a46fSAndroid Build Coastguard Worker     wLab[2] = ab2Fix2(Lab.b);
265*3ac0a46fSAndroid Build Coastguard Worker }
266*3ac0a46fSAndroid Build Coastguard Worker 
267*3ac0a46fSAndroid Build Coastguard Worker 
268*3ac0a46fSAndroid Build Coastguard Worker static
Clamp_L_doubleV4(cmsFloat64Number L)269*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number Clamp_L_doubleV4(cmsFloat64Number L)
270*3ac0a46fSAndroid Build Coastguard Worker {
271*3ac0a46fSAndroid Build Coastguard Worker     if (L < 0) L = 0;
272*3ac0a46fSAndroid Build Coastguard Worker     if (L > 100.0) L = 100.0;
273*3ac0a46fSAndroid Build Coastguard Worker 
274*3ac0a46fSAndroid Build Coastguard Worker     return L;
275*3ac0a46fSAndroid Build Coastguard Worker }
276*3ac0a46fSAndroid Build Coastguard Worker 
277*3ac0a46fSAndroid Build Coastguard Worker static
Clamp_ab_doubleV4(cmsFloat64Number ab)278*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number Clamp_ab_doubleV4(cmsFloat64Number ab)
279*3ac0a46fSAndroid Build Coastguard Worker {
280*3ac0a46fSAndroid Build Coastguard Worker     if (ab < MIN_ENCODEABLE_ab4) ab = MIN_ENCODEABLE_ab4;
281*3ac0a46fSAndroid Build Coastguard Worker     if (ab > MAX_ENCODEABLE_ab4) ab = MAX_ENCODEABLE_ab4;
282*3ac0a46fSAndroid Build Coastguard Worker 
283*3ac0a46fSAndroid Build Coastguard Worker     return ab;
284*3ac0a46fSAndroid Build Coastguard Worker }
285*3ac0a46fSAndroid Build Coastguard Worker 
286*3ac0a46fSAndroid Build Coastguard Worker static
L2Fix4(cmsFloat64Number L)287*3ac0a46fSAndroid Build Coastguard Worker cmsUInt16Number L2Fix4(cmsFloat64Number L)
288*3ac0a46fSAndroid Build Coastguard Worker {
289*3ac0a46fSAndroid Build Coastguard Worker     return _cmsQuickSaturateWord(L *  655.35);
290*3ac0a46fSAndroid Build Coastguard Worker }
291*3ac0a46fSAndroid Build Coastguard Worker 
292*3ac0a46fSAndroid Build Coastguard Worker static
ab2Fix4(cmsFloat64Number ab)293*3ac0a46fSAndroid Build Coastguard Worker cmsUInt16Number ab2Fix4(cmsFloat64Number ab)
294*3ac0a46fSAndroid Build Coastguard Worker {
295*3ac0a46fSAndroid Build Coastguard Worker     return _cmsQuickSaturateWord((ab + 128.0) * 257.0);
296*3ac0a46fSAndroid Build Coastguard Worker }
297*3ac0a46fSAndroid Build Coastguard Worker 
cmsFloat2LabEncoded(cmsUInt16Number wLab[3],const cmsCIELab * fLab)298*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsFloat2LabEncoded(cmsUInt16Number wLab[3], const cmsCIELab* fLab)
299*3ac0a46fSAndroid Build Coastguard Worker {
300*3ac0a46fSAndroid Build Coastguard Worker     cmsCIELab Lab;
301*3ac0a46fSAndroid Build Coastguard Worker 
302*3ac0a46fSAndroid Build Coastguard Worker     Lab.L = Clamp_L_doubleV4(fLab ->L);
303*3ac0a46fSAndroid Build Coastguard Worker     Lab.a = Clamp_ab_doubleV4(fLab ->a);
304*3ac0a46fSAndroid Build Coastguard Worker     Lab.b = Clamp_ab_doubleV4(fLab ->b);
305*3ac0a46fSAndroid Build Coastguard Worker 
306*3ac0a46fSAndroid Build Coastguard Worker     wLab[0] = L2Fix4(Lab.L);
307*3ac0a46fSAndroid Build Coastguard Worker     wLab[1] = ab2Fix4(Lab.a);
308*3ac0a46fSAndroid Build Coastguard Worker     wLab[2] = ab2Fix4(Lab.b);
309*3ac0a46fSAndroid Build Coastguard Worker }
310*3ac0a46fSAndroid Build Coastguard Worker 
311*3ac0a46fSAndroid Build Coastguard Worker // Auxiliary: convert to Radians
312*3ac0a46fSAndroid Build Coastguard Worker static
RADIANS(cmsFloat64Number deg)313*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number RADIANS(cmsFloat64Number deg)
314*3ac0a46fSAndroid Build Coastguard Worker {
315*3ac0a46fSAndroid Build Coastguard Worker     return (deg * M_PI) / 180.;
316*3ac0a46fSAndroid Build Coastguard Worker }
317*3ac0a46fSAndroid Build Coastguard Worker 
318*3ac0a46fSAndroid Build Coastguard Worker 
319*3ac0a46fSAndroid Build Coastguard Worker // Auxiliary: atan2 but operating in degrees and returning 0 if a==b==0
320*3ac0a46fSAndroid Build Coastguard Worker static
atan2deg(cmsFloat64Number a,cmsFloat64Number b)321*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number atan2deg(cmsFloat64Number a, cmsFloat64Number b)
322*3ac0a46fSAndroid Build Coastguard Worker {
323*3ac0a46fSAndroid Build Coastguard Worker    cmsFloat64Number h;
324*3ac0a46fSAndroid Build Coastguard Worker 
325*3ac0a46fSAndroid Build Coastguard Worker    if (a == 0 && b == 0)
326*3ac0a46fSAndroid Build Coastguard Worker             h   = 0;
327*3ac0a46fSAndroid Build Coastguard Worker     else
328*3ac0a46fSAndroid Build Coastguard Worker             h = atan2(a, b);
329*3ac0a46fSAndroid Build Coastguard Worker 
330*3ac0a46fSAndroid Build Coastguard Worker     h *= (180. / M_PI);
331*3ac0a46fSAndroid Build Coastguard Worker 
332*3ac0a46fSAndroid Build Coastguard Worker     while (h > 360.)
333*3ac0a46fSAndroid Build Coastguard Worker         h -= 360.;
334*3ac0a46fSAndroid Build Coastguard Worker 
335*3ac0a46fSAndroid Build Coastguard Worker     while ( h < 0)
336*3ac0a46fSAndroid Build Coastguard Worker         h += 360.;
337*3ac0a46fSAndroid Build Coastguard Worker 
338*3ac0a46fSAndroid Build Coastguard Worker     return h;
339*3ac0a46fSAndroid Build Coastguard Worker }
340*3ac0a46fSAndroid Build Coastguard Worker 
341*3ac0a46fSAndroid Build Coastguard Worker 
342*3ac0a46fSAndroid Build Coastguard Worker // Auxiliary: Square
343*3ac0a46fSAndroid Build Coastguard Worker static
Sqr(cmsFloat64Number v)344*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number Sqr(cmsFloat64Number v)
345*3ac0a46fSAndroid Build Coastguard Worker {
346*3ac0a46fSAndroid Build Coastguard Worker     return v *  v;
347*3ac0a46fSAndroid Build Coastguard Worker }
348*3ac0a46fSAndroid Build Coastguard Worker // From cylindrical coordinates. No check is performed, then negative values are allowed
cmsLab2LCh(cmsCIELCh * LCh,const cmsCIELab * Lab)349*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsLab2LCh(cmsCIELCh* LCh, const cmsCIELab* Lab)
350*3ac0a46fSAndroid Build Coastguard Worker {
351*3ac0a46fSAndroid Build Coastguard Worker     LCh -> L = Lab -> L;
352*3ac0a46fSAndroid Build Coastguard Worker     LCh -> C = pow(Sqr(Lab ->a) + Sqr(Lab ->b), 0.5);
353*3ac0a46fSAndroid Build Coastguard Worker     LCh -> h = atan2deg(Lab ->b, Lab ->a);
354*3ac0a46fSAndroid Build Coastguard Worker }
355*3ac0a46fSAndroid Build Coastguard Worker 
356*3ac0a46fSAndroid Build Coastguard Worker 
357*3ac0a46fSAndroid Build Coastguard Worker // To cylindrical coordinates. No check is performed, then negative values are allowed
cmsLCh2Lab(cmsCIELab * Lab,const cmsCIELCh * LCh)358*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsLCh2Lab(cmsCIELab* Lab, const cmsCIELCh* LCh)
359*3ac0a46fSAndroid Build Coastguard Worker {
360*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number h = (LCh -> h * M_PI) / 180.0;
361*3ac0a46fSAndroid Build Coastguard Worker 
362*3ac0a46fSAndroid Build Coastguard Worker     Lab -> L = LCh -> L;
363*3ac0a46fSAndroid Build Coastguard Worker     Lab -> a = LCh -> C * cos(h);
364*3ac0a46fSAndroid Build Coastguard Worker     Lab -> b = LCh -> C * sin(h);
365*3ac0a46fSAndroid Build Coastguard Worker }
366*3ac0a46fSAndroid Build Coastguard Worker 
367*3ac0a46fSAndroid Build Coastguard Worker // In XYZ All 3 components are encoded using 1.15 fixed point
368*3ac0a46fSAndroid Build Coastguard Worker static
XYZ2Fix(cmsFloat64Number d)369*3ac0a46fSAndroid Build Coastguard Worker cmsUInt16Number XYZ2Fix(cmsFloat64Number d)
370*3ac0a46fSAndroid Build Coastguard Worker {
371*3ac0a46fSAndroid Build Coastguard Worker     return _cmsQuickSaturateWord(d * 32768.0);
372*3ac0a46fSAndroid Build Coastguard Worker }
373*3ac0a46fSAndroid Build Coastguard Worker 
cmsFloat2XYZEncoded(cmsUInt16Number XYZ[3],const cmsCIEXYZ * fXYZ)374*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsFloat2XYZEncoded(cmsUInt16Number XYZ[3], const cmsCIEXYZ* fXYZ)
375*3ac0a46fSAndroid Build Coastguard Worker {
376*3ac0a46fSAndroid Build Coastguard Worker     cmsCIEXYZ xyz;
377*3ac0a46fSAndroid Build Coastguard Worker 
378*3ac0a46fSAndroid Build Coastguard Worker     xyz.X = fXYZ -> X;
379*3ac0a46fSAndroid Build Coastguard Worker     xyz.Y = fXYZ -> Y;
380*3ac0a46fSAndroid Build Coastguard Worker     xyz.Z = fXYZ -> Z;
381*3ac0a46fSAndroid Build Coastguard Worker 
382*3ac0a46fSAndroid Build Coastguard Worker     // Clamp to encodeable values.
383*3ac0a46fSAndroid Build Coastguard Worker     if (xyz.Y <= 0) {
384*3ac0a46fSAndroid Build Coastguard Worker 
385*3ac0a46fSAndroid Build Coastguard Worker         xyz.X = 0;
386*3ac0a46fSAndroid Build Coastguard Worker         xyz.Y = 0;
387*3ac0a46fSAndroid Build Coastguard Worker         xyz.Z = 0;
388*3ac0a46fSAndroid Build Coastguard Worker     }
389*3ac0a46fSAndroid Build Coastguard Worker 
390*3ac0a46fSAndroid Build Coastguard Worker     if (xyz.X > MAX_ENCODEABLE_XYZ)
391*3ac0a46fSAndroid Build Coastguard Worker         xyz.X = MAX_ENCODEABLE_XYZ;
392*3ac0a46fSAndroid Build Coastguard Worker 
393*3ac0a46fSAndroid Build Coastguard Worker     if (xyz.X < 0)
394*3ac0a46fSAndroid Build Coastguard Worker         xyz.X = 0;
395*3ac0a46fSAndroid Build Coastguard Worker 
396*3ac0a46fSAndroid Build Coastguard Worker     if (xyz.Y > MAX_ENCODEABLE_XYZ)
397*3ac0a46fSAndroid Build Coastguard Worker         xyz.Y = MAX_ENCODEABLE_XYZ;
398*3ac0a46fSAndroid Build Coastguard Worker 
399*3ac0a46fSAndroid Build Coastguard Worker     if (xyz.Y < 0)
400*3ac0a46fSAndroid Build Coastguard Worker         xyz.Y = 0;
401*3ac0a46fSAndroid Build Coastguard Worker 
402*3ac0a46fSAndroid Build Coastguard Worker     if (xyz.Z > MAX_ENCODEABLE_XYZ)
403*3ac0a46fSAndroid Build Coastguard Worker         xyz.Z = MAX_ENCODEABLE_XYZ;
404*3ac0a46fSAndroid Build Coastguard Worker 
405*3ac0a46fSAndroid Build Coastguard Worker     if (xyz.Z < 0)
406*3ac0a46fSAndroid Build Coastguard Worker         xyz.Z = 0;
407*3ac0a46fSAndroid Build Coastguard Worker 
408*3ac0a46fSAndroid Build Coastguard Worker 
409*3ac0a46fSAndroid Build Coastguard Worker     XYZ[0] = XYZ2Fix(xyz.X);
410*3ac0a46fSAndroid Build Coastguard Worker     XYZ[1] = XYZ2Fix(xyz.Y);
411*3ac0a46fSAndroid Build Coastguard Worker     XYZ[2] = XYZ2Fix(xyz.Z);
412*3ac0a46fSAndroid Build Coastguard Worker }
413*3ac0a46fSAndroid Build Coastguard Worker 
414*3ac0a46fSAndroid Build Coastguard Worker 
415*3ac0a46fSAndroid Build Coastguard Worker //  To convert from Fixed 1.15 point to cmsFloat64Number
416*3ac0a46fSAndroid Build Coastguard Worker static
XYZ2float(cmsUInt16Number v)417*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number XYZ2float(cmsUInt16Number v)
418*3ac0a46fSAndroid Build Coastguard Worker {
419*3ac0a46fSAndroid Build Coastguard Worker     cmsS15Fixed16Number fix32;
420*3ac0a46fSAndroid Build Coastguard Worker 
421*3ac0a46fSAndroid Build Coastguard Worker     // From 1.15 to 15.16
422*3ac0a46fSAndroid Build Coastguard Worker     fix32 = v << 1;
423*3ac0a46fSAndroid Build Coastguard Worker 
424*3ac0a46fSAndroid Build Coastguard Worker     // From fixed 15.16 to cmsFloat64Number
425*3ac0a46fSAndroid Build Coastguard Worker     return _cms15Fixed16toDouble(fix32);
426*3ac0a46fSAndroid Build Coastguard Worker }
427*3ac0a46fSAndroid Build Coastguard Worker 
428*3ac0a46fSAndroid Build Coastguard Worker 
cmsXYZEncoded2Float(cmsCIEXYZ * fXYZ,const cmsUInt16Number XYZ[3])429*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsXYZEncoded2Float(cmsCIEXYZ* fXYZ, const cmsUInt16Number XYZ[3])
430*3ac0a46fSAndroid Build Coastguard Worker {
431*3ac0a46fSAndroid Build Coastguard Worker     fXYZ -> X = XYZ2float(XYZ[0]);
432*3ac0a46fSAndroid Build Coastguard Worker     fXYZ -> Y = XYZ2float(XYZ[1]);
433*3ac0a46fSAndroid Build Coastguard Worker     fXYZ -> Z = XYZ2float(XYZ[2]);
434*3ac0a46fSAndroid Build Coastguard Worker }
435*3ac0a46fSAndroid Build Coastguard Worker 
436*3ac0a46fSAndroid Build Coastguard Worker 
437*3ac0a46fSAndroid Build Coastguard Worker // Returns dE on two Lab values
cmsDeltaE(const cmsCIELab * Lab1,const cmsCIELab * Lab2)438*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number CMSEXPORT cmsDeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2)
439*3ac0a46fSAndroid Build Coastguard Worker {
440*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number dL, da, db;
441*3ac0a46fSAndroid Build Coastguard Worker 
442*3ac0a46fSAndroid Build Coastguard Worker     dL = fabs(Lab1 -> L - Lab2 -> L);
443*3ac0a46fSAndroid Build Coastguard Worker     da = fabs(Lab1 -> a - Lab2 -> a);
444*3ac0a46fSAndroid Build Coastguard Worker     db = fabs(Lab1 -> b - Lab2 -> b);
445*3ac0a46fSAndroid Build Coastguard Worker 
446*3ac0a46fSAndroid Build Coastguard Worker     return pow(Sqr(dL) + Sqr(da) + Sqr(db), 0.5);
447*3ac0a46fSAndroid Build Coastguard Worker }
448*3ac0a46fSAndroid Build Coastguard Worker 
449*3ac0a46fSAndroid Build Coastguard Worker 
450*3ac0a46fSAndroid Build Coastguard Worker // Return the CIE94 Delta E
cmsCIE94DeltaE(const cmsCIELab * Lab1,const cmsCIELab * Lab2)451*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number CMSEXPORT cmsCIE94DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2)
452*3ac0a46fSAndroid Build Coastguard Worker {
453*3ac0a46fSAndroid Build Coastguard Worker     cmsCIELCh LCh1, LCh2;
454*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number dE, dL, dC, dh, dhsq;
455*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number c12, sc, sh;
456*3ac0a46fSAndroid Build Coastguard Worker 
457*3ac0a46fSAndroid Build Coastguard Worker     dL = fabs(Lab1 ->L - Lab2 ->L);
458*3ac0a46fSAndroid Build Coastguard Worker 
459*3ac0a46fSAndroid Build Coastguard Worker     cmsLab2LCh(&LCh1, Lab1);
460*3ac0a46fSAndroid Build Coastguard Worker     cmsLab2LCh(&LCh2, Lab2);
461*3ac0a46fSAndroid Build Coastguard Worker 
462*3ac0a46fSAndroid Build Coastguard Worker     dC  = fabs(LCh1.C - LCh2.C);
463*3ac0a46fSAndroid Build Coastguard Worker     dE  = cmsDeltaE(Lab1, Lab2);
464*3ac0a46fSAndroid Build Coastguard Worker 
465*3ac0a46fSAndroid Build Coastguard Worker     dhsq = Sqr(dE) - Sqr(dL) - Sqr(dC);
466*3ac0a46fSAndroid Build Coastguard Worker     if (dhsq < 0)
467*3ac0a46fSAndroid Build Coastguard Worker         dh = 0;
468*3ac0a46fSAndroid Build Coastguard Worker     else
469*3ac0a46fSAndroid Build Coastguard Worker         dh = pow(dhsq, 0.5);
470*3ac0a46fSAndroid Build Coastguard Worker 
471*3ac0a46fSAndroid Build Coastguard Worker     c12 = sqrt(LCh1.C * LCh2.C);
472*3ac0a46fSAndroid Build Coastguard Worker 
473*3ac0a46fSAndroid Build Coastguard Worker     sc = 1.0 + (0.048 * c12);
474*3ac0a46fSAndroid Build Coastguard Worker     sh = 1.0 + (0.014 * c12);
475*3ac0a46fSAndroid Build Coastguard Worker 
476*3ac0a46fSAndroid Build Coastguard Worker     return sqrt(Sqr(dL)  + Sqr(dC) / Sqr(sc) + Sqr(dh) / Sqr(sh));
477*3ac0a46fSAndroid Build Coastguard Worker }
478*3ac0a46fSAndroid Build Coastguard Worker 
479*3ac0a46fSAndroid Build Coastguard Worker 
480*3ac0a46fSAndroid Build Coastguard Worker // Auxiliary
481*3ac0a46fSAndroid Build Coastguard Worker static
ComputeLBFD(const cmsCIELab * Lab)482*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number ComputeLBFD(const cmsCIELab* Lab)
483*3ac0a46fSAndroid Build Coastguard Worker {
484*3ac0a46fSAndroid Build Coastguard Worker   cmsFloat64Number yt;
485*3ac0a46fSAndroid Build Coastguard Worker 
486*3ac0a46fSAndroid Build Coastguard Worker   if (Lab->L > 7.996969)
487*3ac0a46fSAndroid Build Coastguard Worker         yt = (Sqr((Lab->L+16)/116)*((Lab->L+16)/116))*100;
488*3ac0a46fSAndroid Build Coastguard Worker   else
489*3ac0a46fSAndroid Build Coastguard Worker         yt = 100 * (Lab->L / 903.3);
490*3ac0a46fSAndroid Build Coastguard Worker 
491*3ac0a46fSAndroid Build Coastguard Worker   return (54.6 * (M_LOG10E * (log(yt + 1.5))) - 9.6);
492*3ac0a46fSAndroid Build Coastguard Worker }
493*3ac0a46fSAndroid Build Coastguard Worker 
494*3ac0a46fSAndroid Build Coastguard Worker 
495*3ac0a46fSAndroid Build Coastguard Worker 
496*3ac0a46fSAndroid Build Coastguard Worker // bfd - gets BFD(1:1) difference between Lab1, Lab2
cmsBFDdeltaE(const cmsCIELab * Lab1,const cmsCIELab * Lab2)497*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number CMSEXPORT cmsBFDdeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2)
498*3ac0a46fSAndroid Build Coastguard Worker {
499*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number lbfd1,lbfd2,AveC,Aveh,dE,deltaL,
500*3ac0a46fSAndroid Build Coastguard Worker         deltaC,deltah,dc,t,g,dh,rh,rc,rt,bfd;
501*3ac0a46fSAndroid Build Coastguard Worker     cmsCIELCh LCh1, LCh2;
502*3ac0a46fSAndroid Build Coastguard Worker 
503*3ac0a46fSAndroid Build Coastguard Worker 
504*3ac0a46fSAndroid Build Coastguard Worker     lbfd1 = ComputeLBFD(Lab1);
505*3ac0a46fSAndroid Build Coastguard Worker     lbfd2 = ComputeLBFD(Lab2);
506*3ac0a46fSAndroid Build Coastguard Worker     deltaL = lbfd2 - lbfd1;
507*3ac0a46fSAndroid Build Coastguard Worker 
508*3ac0a46fSAndroid Build Coastguard Worker     cmsLab2LCh(&LCh1, Lab1);
509*3ac0a46fSAndroid Build Coastguard Worker     cmsLab2LCh(&LCh2, Lab2);
510*3ac0a46fSAndroid Build Coastguard Worker 
511*3ac0a46fSAndroid Build Coastguard Worker     deltaC = LCh2.C - LCh1.C;
512*3ac0a46fSAndroid Build Coastguard Worker     AveC = (LCh1.C+LCh2.C)/2;
513*3ac0a46fSAndroid Build Coastguard Worker     Aveh = (LCh1.h+LCh2.h)/2;
514*3ac0a46fSAndroid Build Coastguard Worker 
515*3ac0a46fSAndroid Build Coastguard Worker     dE = cmsDeltaE(Lab1, Lab2);
516*3ac0a46fSAndroid Build Coastguard Worker 
517*3ac0a46fSAndroid Build Coastguard Worker     if (Sqr(dE)>(Sqr(Lab2->L-Lab1->L)+Sqr(deltaC)))
518*3ac0a46fSAndroid Build Coastguard Worker         deltah = sqrt(Sqr(dE)-Sqr(Lab2->L-Lab1->L)-Sqr(deltaC));
519*3ac0a46fSAndroid Build Coastguard Worker     else
520*3ac0a46fSAndroid Build Coastguard Worker         deltah =0;
521*3ac0a46fSAndroid Build Coastguard Worker 
522*3ac0a46fSAndroid Build Coastguard Worker 
523*3ac0a46fSAndroid Build Coastguard Worker     dc   = 0.035 * AveC / (1 + 0.00365 * AveC)+0.521;
524*3ac0a46fSAndroid Build Coastguard Worker     g    = sqrt(Sqr(Sqr(AveC))/(Sqr(Sqr(AveC))+14000));
525*3ac0a46fSAndroid Build Coastguard Worker     t    = 0.627+(0.055*cos((Aveh-254)/(180/M_PI))-
526*3ac0a46fSAndroid Build Coastguard Worker            0.040*cos((2*Aveh-136)/(180/M_PI))+
527*3ac0a46fSAndroid Build Coastguard Worker            0.070*cos((3*Aveh-31)/(180/M_PI))+
528*3ac0a46fSAndroid Build Coastguard Worker            0.049*cos((4*Aveh+114)/(180/M_PI))-
529*3ac0a46fSAndroid Build Coastguard Worker            0.015*cos((5*Aveh-103)/(180/M_PI)));
530*3ac0a46fSAndroid Build Coastguard Worker 
531*3ac0a46fSAndroid Build Coastguard Worker     dh    = dc*(g*t+1-g);
532*3ac0a46fSAndroid Build Coastguard Worker     rh    = -0.260*cos((Aveh-308)/(180/M_PI))-
533*3ac0a46fSAndroid Build Coastguard Worker            0.379*cos((2*Aveh-160)/(180/M_PI))-
534*3ac0a46fSAndroid Build Coastguard Worker            0.636*cos((3*Aveh+254)/(180/M_PI))+
535*3ac0a46fSAndroid Build Coastguard Worker            0.226*cos((4*Aveh+140)/(180/M_PI))-
536*3ac0a46fSAndroid Build Coastguard Worker            0.194*cos((5*Aveh+280)/(180/M_PI));
537*3ac0a46fSAndroid Build Coastguard Worker 
538*3ac0a46fSAndroid Build Coastguard Worker     rc = sqrt((AveC*AveC*AveC*AveC*AveC*AveC)/((AveC*AveC*AveC*AveC*AveC*AveC)+70000000));
539*3ac0a46fSAndroid Build Coastguard Worker     rt = rh*rc;
540*3ac0a46fSAndroid Build Coastguard Worker 
541*3ac0a46fSAndroid Build Coastguard Worker     bfd = sqrt(Sqr(deltaL)+Sqr(deltaC/dc)+Sqr(deltah/dh)+(rt*(deltaC/dc)*(deltah/dh)));
542*3ac0a46fSAndroid Build Coastguard Worker 
543*3ac0a46fSAndroid Build Coastguard Worker     return bfd;
544*3ac0a46fSAndroid Build Coastguard Worker }
545*3ac0a46fSAndroid Build Coastguard Worker 
546*3ac0a46fSAndroid Build Coastguard Worker 
547*3ac0a46fSAndroid Build Coastguard Worker //  cmc - CMC(l:c) difference between Lab1, Lab2
cmsCMCdeltaE(const cmsCIELab * Lab1,const cmsCIELab * Lab2,cmsFloat64Number l,cmsFloat64Number c)548*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number CMSEXPORT cmsCMCdeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2, cmsFloat64Number l, cmsFloat64Number c)
549*3ac0a46fSAndroid Build Coastguard Worker {
550*3ac0a46fSAndroid Build Coastguard Worker   cmsFloat64Number dE,dL,dC,dh,sl,sc,sh,t,f,cmc;
551*3ac0a46fSAndroid Build Coastguard Worker   cmsCIELCh LCh1, LCh2;
552*3ac0a46fSAndroid Build Coastguard Worker 
553*3ac0a46fSAndroid Build Coastguard Worker   if (Lab1 ->L == 0 && Lab2 ->L == 0) return 0;
554*3ac0a46fSAndroid Build Coastguard Worker 
555*3ac0a46fSAndroid Build Coastguard Worker   cmsLab2LCh(&LCh1, Lab1);
556*3ac0a46fSAndroid Build Coastguard Worker   cmsLab2LCh(&LCh2, Lab2);
557*3ac0a46fSAndroid Build Coastguard Worker 
558*3ac0a46fSAndroid Build Coastguard Worker 
559*3ac0a46fSAndroid Build Coastguard Worker   dL = Lab2->L-Lab1->L;
560*3ac0a46fSAndroid Build Coastguard Worker   dC = LCh2.C-LCh1.C;
561*3ac0a46fSAndroid Build Coastguard Worker 
562*3ac0a46fSAndroid Build Coastguard Worker   dE = cmsDeltaE(Lab1, Lab2);
563*3ac0a46fSAndroid Build Coastguard Worker 
564*3ac0a46fSAndroid Build Coastguard Worker   if (Sqr(dE)>(Sqr(dL)+Sqr(dC)))
565*3ac0a46fSAndroid Build Coastguard Worker             dh = sqrt(Sqr(dE)-Sqr(dL)-Sqr(dC));
566*3ac0a46fSAndroid Build Coastguard Worker   else
567*3ac0a46fSAndroid Build Coastguard Worker             dh =0;
568*3ac0a46fSAndroid Build Coastguard Worker 
569*3ac0a46fSAndroid Build Coastguard Worker   if ((LCh1.h > 164) && (LCh1.h < 345))
570*3ac0a46fSAndroid Build Coastguard Worker       t = 0.56 + fabs(0.2 * cos(((LCh1.h + 168)/(180/M_PI))));
571*3ac0a46fSAndroid Build Coastguard Worker   else
572*3ac0a46fSAndroid Build Coastguard Worker       t = 0.36 + fabs(0.4 * cos(((LCh1.h + 35 )/(180/M_PI))));
573*3ac0a46fSAndroid Build Coastguard Worker 
574*3ac0a46fSAndroid Build Coastguard Worker    sc  = 0.0638   * LCh1.C / (1 + 0.0131  * LCh1.C) + 0.638;
575*3ac0a46fSAndroid Build Coastguard Worker    sl  = 0.040975 * Lab1->L /(1 + 0.01765 * Lab1->L);
576*3ac0a46fSAndroid Build Coastguard Worker 
577*3ac0a46fSAndroid Build Coastguard Worker    if (Lab1->L<16)
578*3ac0a46fSAndroid Build Coastguard Worker          sl = 0.511;
579*3ac0a46fSAndroid Build Coastguard Worker 
580*3ac0a46fSAndroid Build Coastguard Worker    f   = sqrt((LCh1.C * LCh1.C * LCh1.C * LCh1.C)/((LCh1.C * LCh1.C * LCh1.C * LCh1.C)+1900));
581*3ac0a46fSAndroid Build Coastguard Worker    sh  = sc*(t*f+1-f);
582*3ac0a46fSAndroid Build Coastguard Worker    cmc = sqrt(Sqr(dL/(l*sl))+Sqr(dC/(c*sc))+Sqr(dh/sh));
583*3ac0a46fSAndroid Build Coastguard Worker 
584*3ac0a46fSAndroid Build Coastguard Worker    return cmc;
585*3ac0a46fSAndroid Build Coastguard Worker }
586*3ac0a46fSAndroid Build Coastguard Worker 
587*3ac0a46fSAndroid Build Coastguard Worker // dE2000 The weightings KL, KC and KH can be modified to reflect the relative
588*3ac0a46fSAndroid Build Coastguard Worker // importance of lightness, chroma and hue in different industrial applications
cmsCIE2000DeltaE(const cmsCIELab * Lab1,const cmsCIELab * Lab2,cmsFloat64Number Kl,cmsFloat64Number Kc,cmsFloat64Number Kh)589*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2,
590*3ac0a46fSAndroid Build Coastguard Worker                                   cmsFloat64Number Kl, cmsFloat64Number Kc, cmsFloat64Number Kh)
591*3ac0a46fSAndroid Build Coastguard Worker {
592*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number L1  = Lab1->L;
593*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number a1  = Lab1->a;
594*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number b1  = Lab1->b;
595*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number C   = sqrt( Sqr(a1) + Sqr(b1) );
596*3ac0a46fSAndroid Build Coastguard Worker 
597*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number Ls = Lab2 ->L;
598*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number as = Lab2 ->a;
599*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number bs = Lab2 ->b;
600*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number Cs = sqrt( Sqr(as) + Sqr(bs) );
601*3ac0a46fSAndroid Build Coastguard Worker 
602*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number G = 0.5 * ( 1 - sqrt(pow((C + Cs) / 2 , 7.0) / (pow((C + Cs) / 2, 7.0) + pow(25.0, 7.0) ) ));
603*3ac0a46fSAndroid Build Coastguard Worker 
604*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number a_p = (1 + G ) * a1;
605*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number b_p = b1;
606*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number C_p = sqrt( Sqr(a_p) + Sqr(b_p));
607*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number h_p = atan2deg(b_p, a_p);
608*3ac0a46fSAndroid Build Coastguard Worker 
609*3ac0a46fSAndroid Build Coastguard Worker 
610*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number a_ps = (1 + G) * as;
611*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number b_ps = bs;
612*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number C_ps = sqrt(Sqr(a_ps) + Sqr(b_ps));
613*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number h_ps = atan2deg(b_ps, a_ps);
614*3ac0a46fSAndroid Build Coastguard Worker 
615*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number meanC_p =(C_p + C_ps) / 2;
616*3ac0a46fSAndroid Build Coastguard Worker 
617*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number hps_plus_hp  = h_ps + h_p;
618*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number hps_minus_hp = h_ps - h_p;
619*3ac0a46fSAndroid Build Coastguard Worker 
620*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number meanh_p = fabs(hps_minus_hp) <= 180.000001 ? (hps_plus_hp)/2 :
621*3ac0a46fSAndroid Build Coastguard Worker                             (hps_plus_hp) < 360 ? (hps_plus_hp + 360)/2 :
622*3ac0a46fSAndroid Build Coastguard Worker                                                  (hps_plus_hp - 360)/2;
623*3ac0a46fSAndroid Build Coastguard Worker 
624*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number delta_h = (hps_minus_hp) <= -180.000001 ?  (hps_minus_hp + 360) :
625*3ac0a46fSAndroid Build Coastguard Worker                             (hps_minus_hp) > 180 ? (hps_minus_hp - 360) :
626*3ac0a46fSAndroid Build Coastguard Worker                                                     (hps_minus_hp);
627*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number delta_L = (Ls - L1);
628*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number delta_C = (C_ps - C_p );
629*3ac0a46fSAndroid Build Coastguard Worker 
630*3ac0a46fSAndroid Build Coastguard Worker 
631*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number delta_H =2 * sqrt(C_ps*C_p) * sin(RADIANS(delta_h) / 2);
632*3ac0a46fSAndroid Build Coastguard Worker 
633*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number T = 1 - 0.17 * cos(RADIANS(meanh_p-30))
634*3ac0a46fSAndroid Build Coastguard Worker                  + 0.24 * cos(RADIANS(2*meanh_p))
635*3ac0a46fSAndroid Build Coastguard Worker                  + 0.32 * cos(RADIANS(3*meanh_p + 6))
636*3ac0a46fSAndroid Build Coastguard Worker                  - 0.2  * cos(RADIANS(4*meanh_p - 63));
637*3ac0a46fSAndroid Build Coastguard Worker 
638*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number Sl = 1 + (0.015 * Sqr((Ls + L1) /2- 50) )/ sqrt(20 + Sqr( (Ls+L1)/2 - 50) );
639*3ac0a46fSAndroid Build Coastguard Worker 
640*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number Sc = 1 + 0.045 * (C_p + C_ps)/2;
641*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number Sh = 1 + 0.015 * ((C_ps + C_p)/2) * T;
642*3ac0a46fSAndroid Build Coastguard Worker 
643*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number delta_ro = 30 * exp( -Sqr(((meanh_p - 275 ) / 25)));
644*3ac0a46fSAndroid Build Coastguard Worker 
645*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number Rc = 2 * sqrt(( pow(meanC_p, 7.0) )/( pow(meanC_p, 7.0) + pow(25.0, 7.0)));
646*3ac0a46fSAndroid Build Coastguard Worker 
647*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number Rt = -sin(2 * RADIANS(delta_ro)) * Rc;
648*3ac0a46fSAndroid Build Coastguard Worker 
649*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number deltaE00 = sqrt( Sqr(delta_L /(Sl * Kl)) +
650*3ac0a46fSAndroid Build Coastguard Worker                             Sqr(delta_C/(Sc * Kc))  +
651*3ac0a46fSAndroid Build Coastguard Worker                             Sqr(delta_H/(Sh * Kh))  +
652*3ac0a46fSAndroid Build Coastguard Worker                             Rt*(delta_C/(Sc * Kc)) * (delta_H / (Sh * Kh)));
653*3ac0a46fSAndroid Build Coastguard Worker 
654*3ac0a46fSAndroid Build Coastguard Worker     return deltaE00;
655*3ac0a46fSAndroid Build Coastguard Worker }
656*3ac0a46fSAndroid Build Coastguard Worker 
657*3ac0a46fSAndroid Build Coastguard Worker // This function returns a number of gridpoints to be used as LUT table. It assumes same number
658*3ac0a46fSAndroid Build Coastguard Worker // of gripdpoints in all dimensions. Flags may override the choice.
_cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace,cmsUInt32Number dwFlags)659*3ac0a46fSAndroid Build Coastguard Worker cmsUInt32Number CMSEXPORT _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags)
660*3ac0a46fSAndroid Build Coastguard Worker {
661*3ac0a46fSAndroid Build Coastguard Worker     cmsUInt32Number nChannels;
662*3ac0a46fSAndroid Build Coastguard Worker 
663*3ac0a46fSAndroid Build Coastguard Worker     // Already specified?
664*3ac0a46fSAndroid Build Coastguard Worker     if (dwFlags & 0x00FF0000) {
665*3ac0a46fSAndroid Build Coastguard Worker             // Yes, grab'em
666*3ac0a46fSAndroid Build Coastguard Worker             return (dwFlags >> 16) & 0xFF;
667*3ac0a46fSAndroid Build Coastguard Worker     }
668*3ac0a46fSAndroid Build Coastguard Worker 
669*3ac0a46fSAndroid Build Coastguard Worker     nChannels = cmsChannelsOf(Colorspace);
670*3ac0a46fSAndroid Build Coastguard Worker 
671*3ac0a46fSAndroid Build Coastguard Worker     // HighResPrecalc is maximum resolution
672*3ac0a46fSAndroid Build Coastguard Worker     if (dwFlags & cmsFLAGS_HIGHRESPRECALC) {
673*3ac0a46fSAndroid Build Coastguard Worker 
674*3ac0a46fSAndroid Build Coastguard Worker         if (nChannels > 4)
675*3ac0a46fSAndroid Build Coastguard Worker                 return 7;       // 7 for Hifi
676*3ac0a46fSAndroid Build Coastguard Worker 
677*3ac0a46fSAndroid Build Coastguard Worker         if (nChannels == 4)     // 23 for CMYK
678*3ac0a46fSAndroid Build Coastguard Worker                 return 23;
679*3ac0a46fSAndroid Build Coastguard Worker 
680*3ac0a46fSAndroid Build Coastguard Worker         return 49;      // 49 for RGB and others
681*3ac0a46fSAndroid Build Coastguard Worker     }
682*3ac0a46fSAndroid Build Coastguard Worker 
683*3ac0a46fSAndroid Build Coastguard Worker 
684*3ac0a46fSAndroid Build Coastguard Worker     // LowResPrecal is lower resolution
685*3ac0a46fSAndroid Build Coastguard Worker     if (dwFlags & cmsFLAGS_LOWRESPRECALC) {
686*3ac0a46fSAndroid Build Coastguard Worker 
687*3ac0a46fSAndroid Build Coastguard Worker         if (nChannels > 4)
688*3ac0a46fSAndroid Build Coastguard Worker                 return 6;       // 6 for more than 4 channels
689*3ac0a46fSAndroid Build Coastguard Worker 
690*3ac0a46fSAndroid Build Coastguard Worker         if (nChannels == 1)
691*3ac0a46fSAndroid Build Coastguard Worker                 return 33;      // For monochrome
692*3ac0a46fSAndroid Build Coastguard Worker 
693*3ac0a46fSAndroid Build Coastguard Worker         return 17;              // 17 for remaining
694*3ac0a46fSAndroid Build Coastguard Worker     }
695*3ac0a46fSAndroid Build Coastguard Worker 
696*3ac0a46fSAndroid Build Coastguard Worker     // Default values
697*3ac0a46fSAndroid Build Coastguard Worker     if (nChannels > 4)
698*3ac0a46fSAndroid Build Coastguard Worker                 return 7;       // 7 for Hifi
699*3ac0a46fSAndroid Build Coastguard Worker 
700*3ac0a46fSAndroid Build Coastguard Worker     if (nChannels == 4)
701*3ac0a46fSAndroid Build Coastguard Worker                 return 17;      // 17 for CMYK
702*3ac0a46fSAndroid Build Coastguard Worker 
703*3ac0a46fSAndroid Build Coastguard Worker     return 33;                  // 33 for RGB
704*3ac0a46fSAndroid Build Coastguard Worker }
705*3ac0a46fSAndroid Build Coastguard Worker 
706*3ac0a46fSAndroid Build Coastguard Worker 
_cmsEndPointsBySpace(cmsColorSpaceSignature Space,cmsUInt16Number ** White,cmsUInt16Number ** Black,cmsUInt32Number * nOutputs)707*3ac0a46fSAndroid Build Coastguard Worker cmsBool  _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
708*3ac0a46fSAndroid Build Coastguard Worker                              cmsUInt16Number **White,
709*3ac0a46fSAndroid Build Coastguard Worker                              cmsUInt16Number **Black,
710*3ac0a46fSAndroid Build Coastguard Worker                              cmsUInt32Number *nOutputs)
711*3ac0a46fSAndroid Build Coastguard Worker {
712*3ac0a46fSAndroid Build Coastguard Worker        // Only most common spaces
713*3ac0a46fSAndroid Build Coastguard Worker 
714*3ac0a46fSAndroid Build Coastguard Worker        static cmsUInt16Number RGBblack[4]  = { 0, 0, 0 };
715*3ac0a46fSAndroid Build Coastguard Worker        static cmsUInt16Number RGBwhite[4]  = { 0xffff, 0xffff, 0xffff };
716*3ac0a46fSAndroid Build Coastguard Worker        static cmsUInt16Number CMYKblack[4] = { 0xffff, 0xffff, 0xffff, 0xffff };   // 400% of ink
717*3ac0a46fSAndroid Build Coastguard Worker        static cmsUInt16Number CMYKwhite[4] = { 0, 0, 0, 0 };
718*3ac0a46fSAndroid Build Coastguard Worker        static cmsUInt16Number LABblack[4]  = { 0, 0x8080, 0x8080 };               // V4 Lab encoding
719*3ac0a46fSAndroid Build Coastguard Worker        static cmsUInt16Number LABwhite[4]  = { 0xFFFF, 0x8080, 0x8080 };
720*3ac0a46fSAndroid Build Coastguard Worker        static cmsUInt16Number CMYblack[4]  = { 0xffff, 0xffff, 0xffff };
721*3ac0a46fSAndroid Build Coastguard Worker        static cmsUInt16Number CMYwhite[4]  = { 0, 0, 0 };
722*3ac0a46fSAndroid Build Coastguard Worker        static cmsUInt16Number Grayblack[4] = { 0 };
723*3ac0a46fSAndroid Build Coastguard Worker        static cmsUInt16Number GrayWhite[4] = { 0xffff };
724*3ac0a46fSAndroid Build Coastguard Worker 
725*3ac0a46fSAndroid Build Coastguard Worker        switch (Space) {
726*3ac0a46fSAndroid Build Coastguard Worker 
727*3ac0a46fSAndroid Build Coastguard Worker        case cmsSigGrayData: if (White)    *White = GrayWhite;
728*3ac0a46fSAndroid Build Coastguard Worker                            if (Black)    *Black = Grayblack;
729*3ac0a46fSAndroid Build Coastguard Worker                            if (nOutputs) *nOutputs = 1;
730*3ac0a46fSAndroid Build Coastguard Worker                            return TRUE;
731*3ac0a46fSAndroid Build Coastguard Worker 
732*3ac0a46fSAndroid Build Coastguard Worker        case cmsSigRgbData:  if (White)    *White = RGBwhite;
733*3ac0a46fSAndroid Build Coastguard Worker                            if (Black)    *Black = RGBblack;
734*3ac0a46fSAndroid Build Coastguard Worker                            if (nOutputs) *nOutputs = 3;
735*3ac0a46fSAndroid Build Coastguard Worker                            return TRUE;
736*3ac0a46fSAndroid Build Coastguard Worker 
737*3ac0a46fSAndroid Build Coastguard Worker        case cmsSigLabData:  if (White)    *White = LABwhite;
738*3ac0a46fSAndroid Build Coastguard Worker                            if (Black)    *Black = LABblack;
739*3ac0a46fSAndroid Build Coastguard Worker                            if (nOutputs) *nOutputs = 3;
740*3ac0a46fSAndroid Build Coastguard Worker                            return TRUE;
741*3ac0a46fSAndroid Build Coastguard Worker 
742*3ac0a46fSAndroid Build Coastguard Worker        case cmsSigCmykData: if (White)    *White = CMYKwhite;
743*3ac0a46fSAndroid Build Coastguard Worker                            if (Black)    *Black = CMYKblack;
744*3ac0a46fSAndroid Build Coastguard Worker                            if (nOutputs) *nOutputs = 4;
745*3ac0a46fSAndroid Build Coastguard Worker                            return TRUE;
746*3ac0a46fSAndroid Build Coastguard Worker 
747*3ac0a46fSAndroid Build Coastguard Worker        case cmsSigCmyData:  if (White)    *White = CMYwhite;
748*3ac0a46fSAndroid Build Coastguard Worker                            if (Black)    *Black = CMYblack;
749*3ac0a46fSAndroid Build Coastguard Worker                            if (nOutputs) *nOutputs = 3;
750*3ac0a46fSAndroid Build Coastguard Worker                            return TRUE;
751*3ac0a46fSAndroid Build Coastguard Worker 
752*3ac0a46fSAndroid Build Coastguard Worker        default:;
753*3ac0a46fSAndroid Build Coastguard Worker        }
754*3ac0a46fSAndroid Build Coastguard Worker 
755*3ac0a46fSAndroid Build Coastguard Worker   return FALSE;
756*3ac0a46fSAndroid Build Coastguard Worker }
757*3ac0a46fSAndroid Build Coastguard Worker 
758*3ac0a46fSAndroid Build Coastguard Worker 
759*3ac0a46fSAndroid Build Coastguard Worker 
760*3ac0a46fSAndroid Build Coastguard Worker // Several utilities -------------------------------------------------------
761*3ac0a46fSAndroid Build Coastguard Worker 
762*3ac0a46fSAndroid Build Coastguard Worker // Translate from our colorspace to ICC representation
763*3ac0a46fSAndroid Build Coastguard Worker 
_cmsICCcolorSpace(int OurNotation)764*3ac0a46fSAndroid Build Coastguard Worker cmsColorSpaceSignature CMSEXPORT _cmsICCcolorSpace(int OurNotation)
765*3ac0a46fSAndroid Build Coastguard Worker {
766*3ac0a46fSAndroid Build Coastguard Worker        switch (OurNotation) {
767*3ac0a46fSAndroid Build Coastguard Worker 
768*3ac0a46fSAndroid Build Coastguard Worker        case 1:
769*3ac0a46fSAndroid Build Coastguard Worker        case PT_GRAY: return cmsSigGrayData;
770*3ac0a46fSAndroid Build Coastguard Worker 
771*3ac0a46fSAndroid Build Coastguard Worker        case 2:
772*3ac0a46fSAndroid Build Coastguard Worker        case PT_RGB:  return cmsSigRgbData;
773*3ac0a46fSAndroid Build Coastguard Worker 
774*3ac0a46fSAndroid Build Coastguard Worker        case PT_CMY:  return cmsSigCmyData;
775*3ac0a46fSAndroid Build Coastguard Worker        case PT_CMYK: return cmsSigCmykData;
776*3ac0a46fSAndroid Build Coastguard Worker        case PT_YCbCr:return cmsSigYCbCrData;
777*3ac0a46fSAndroid Build Coastguard Worker        case PT_YUV:  return cmsSigLuvData;
778*3ac0a46fSAndroid Build Coastguard Worker        case PT_XYZ:  return cmsSigXYZData;
779*3ac0a46fSAndroid Build Coastguard Worker 
780*3ac0a46fSAndroid Build Coastguard Worker        case PT_LabV2:
781*3ac0a46fSAndroid Build Coastguard Worker        case PT_Lab:  return cmsSigLabData;
782*3ac0a46fSAndroid Build Coastguard Worker 
783*3ac0a46fSAndroid Build Coastguard Worker        case PT_YUVK: return cmsSigLuvKData;
784*3ac0a46fSAndroid Build Coastguard Worker        case PT_HSV:  return cmsSigHsvData;
785*3ac0a46fSAndroid Build Coastguard Worker        case PT_HLS:  return cmsSigHlsData;
786*3ac0a46fSAndroid Build Coastguard Worker        case PT_Yxy:  return cmsSigYxyData;
787*3ac0a46fSAndroid Build Coastguard Worker 
788*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH1: return cmsSigMCH1Data;
789*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH2: return cmsSigMCH2Data;
790*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH3: return cmsSigMCH3Data;
791*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH4: return cmsSigMCH4Data;
792*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH5: return cmsSigMCH5Data;
793*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH6: return cmsSigMCH6Data;
794*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH7: return cmsSigMCH7Data;
795*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH8: return cmsSigMCH8Data;
796*3ac0a46fSAndroid Build Coastguard Worker 
797*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH9:  return cmsSigMCH9Data;
798*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH10: return cmsSigMCHAData;
799*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH11: return cmsSigMCHBData;
800*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH12: return cmsSigMCHCData;
801*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH13: return cmsSigMCHDData;
802*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH14: return cmsSigMCHEData;
803*3ac0a46fSAndroid Build Coastguard Worker        case PT_MCH15: return cmsSigMCHFData;
804*3ac0a46fSAndroid Build Coastguard Worker 
805*3ac0a46fSAndroid Build Coastguard Worker        default:  return (cmsColorSpaceSignature) 0;
806*3ac0a46fSAndroid Build Coastguard Worker        }
807*3ac0a46fSAndroid Build Coastguard Worker }
808*3ac0a46fSAndroid Build Coastguard Worker 
809*3ac0a46fSAndroid Build Coastguard Worker 
_cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace)810*3ac0a46fSAndroid Build Coastguard Worker int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace)
811*3ac0a46fSAndroid Build Coastguard Worker {
812*3ac0a46fSAndroid Build Coastguard Worker     switch (ProfileSpace) {
813*3ac0a46fSAndroid Build Coastguard Worker 
814*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigGrayData: return  PT_GRAY;
815*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigRgbData:  return  PT_RGB;
816*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigCmyData:  return  PT_CMY;
817*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigCmykData: return  PT_CMYK;
818*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigYCbCrData:return  PT_YCbCr;
819*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigLuvData:  return  PT_YUV;
820*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigXYZData:  return  PT_XYZ;
821*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigLabData:  return  PT_Lab;
822*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigLuvKData: return  PT_YUVK;
823*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigHsvData:  return  PT_HSV;
824*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigHlsData:  return  PT_HLS;
825*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigYxyData:  return  PT_Yxy;
826*3ac0a46fSAndroid Build Coastguard Worker 
827*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig1colorData:
828*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH1Data: return PT_MCH1;
829*3ac0a46fSAndroid Build Coastguard Worker 
830*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig2colorData:
831*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH2Data: return PT_MCH2;
832*3ac0a46fSAndroid Build Coastguard Worker 
833*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig3colorData:
834*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH3Data: return PT_MCH3;
835*3ac0a46fSAndroid Build Coastguard Worker 
836*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig4colorData:
837*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH4Data: return PT_MCH4;
838*3ac0a46fSAndroid Build Coastguard Worker 
839*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig5colorData:
840*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH5Data: return PT_MCH5;
841*3ac0a46fSAndroid Build Coastguard Worker 
842*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig6colorData:
843*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH6Data: return PT_MCH6;
844*3ac0a46fSAndroid Build Coastguard Worker 
845*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH7Data:
846*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig7colorData:return PT_MCH7;
847*3ac0a46fSAndroid Build Coastguard Worker 
848*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH8Data:
849*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig8colorData:return PT_MCH8;
850*3ac0a46fSAndroid Build Coastguard Worker 
851*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH9Data:
852*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig9colorData:return PT_MCH9;
853*3ac0a46fSAndroid Build Coastguard Worker 
854*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHAData:
855*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig10colorData:return PT_MCH10;
856*3ac0a46fSAndroid Build Coastguard Worker 
857*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHBData:
858*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig11colorData:return PT_MCH11;
859*3ac0a46fSAndroid Build Coastguard Worker 
860*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHCData:
861*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig12colorData:return PT_MCH12;
862*3ac0a46fSAndroid Build Coastguard Worker 
863*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHDData:
864*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig13colorData:return PT_MCH13;
865*3ac0a46fSAndroid Build Coastguard Worker 
866*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHEData:
867*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig14colorData:return PT_MCH14;
868*3ac0a46fSAndroid Build Coastguard Worker 
869*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHFData:
870*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig15colorData:return PT_MCH15;
871*3ac0a46fSAndroid Build Coastguard Worker 
872*3ac0a46fSAndroid Build Coastguard Worker     default:  return (cmsColorSpaceSignature) 0;
873*3ac0a46fSAndroid Build Coastguard Worker     }
874*3ac0a46fSAndroid Build Coastguard Worker }
875*3ac0a46fSAndroid Build Coastguard Worker 
876*3ac0a46fSAndroid Build Coastguard Worker 
cmsChannelsOfColorSpace(cmsColorSpaceSignature ColorSpace)877*3ac0a46fSAndroid Build Coastguard Worker cmsInt32Number CMSEXPORT cmsChannelsOfColorSpace(cmsColorSpaceSignature ColorSpace)
878*3ac0a46fSAndroid Build Coastguard Worker {
879*3ac0a46fSAndroid Build Coastguard Worker     switch (ColorSpace) {
880*3ac0a46fSAndroid Build Coastguard Worker 
881*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH1Data:
882*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig1colorData:
883*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigGrayData: return 1;
884*3ac0a46fSAndroid Build Coastguard Worker 
885*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH2Data:
886*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig2colorData:  return 2;
887*3ac0a46fSAndroid Build Coastguard Worker 
888*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigXYZData:
889*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigLabData:
890*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigLuvData:
891*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigYCbCrData:
892*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigYxyData:
893*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigRgbData:
894*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigHsvData:
895*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigHlsData:
896*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigCmyData:
897*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH3Data:
898*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig3colorData:  return 3;
899*3ac0a46fSAndroid Build Coastguard Worker 
900*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigLuvKData:
901*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigCmykData:
902*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH4Data:
903*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig4colorData:  return 4;
904*3ac0a46fSAndroid Build Coastguard Worker 
905*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH5Data:
906*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig5colorData:  return 5;
907*3ac0a46fSAndroid Build Coastguard Worker 
908*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH6Data:
909*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig6colorData:  return 6;
910*3ac0a46fSAndroid Build Coastguard Worker 
911*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH7Data:
912*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig7colorData:  return  7;
913*3ac0a46fSAndroid Build Coastguard Worker 
914*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH8Data:
915*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig8colorData:  return  8;
916*3ac0a46fSAndroid Build Coastguard Worker 
917*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCH9Data:
918*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig9colorData:  return  9;
919*3ac0a46fSAndroid Build Coastguard Worker 
920*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHAData:
921*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig10colorData: return 10;
922*3ac0a46fSAndroid Build Coastguard Worker 
923*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHBData:
924*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig11colorData: return 11;
925*3ac0a46fSAndroid Build Coastguard Worker 
926*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHCData:
927*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig12colorData: return 12;
928*3ac0a46fSAndroid Build Coastguard Worker 
929*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHDData:
930*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig13colorData: return 13;
931*3ac0a46fSAndroid Build Coastguard Worker 
932*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHEData:
933*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig14colorData: return 14;
934*3ac0a46fSAndroid Build Coastguard Worker 
935*3ac0a46fSAndroid Build Coastguard Worker     case cmsSigMCHFData:
936*3ac0a46fSAndroid Build Coastguard Worker     case cmsSig15colorData: return 15;
937*3ac0a46fSAndroid Build Coastguard Worker 
938*3ac0a46fSAndroid Build Coastguard Worker     default: return -1;
939*3ac0a46fSAndroid Build Coastguard Worker     }
940*3ac0a46fSAndroid Build Coastguard Worker }
941*3ac0a46fSAndroid Build Coastguard Worker 
942*3ac0a46fSAndroid Build Coastguard Worker /**
943*3ac0a46fSAndroid Build Coastguard Worker * DEPRECATED: Provided for compatibility only
944*3ac0a46fSAndroid Build Coastguard Worker */
cmsChannelsOf(cmsColorSpaceSignature ColorSpace)945*3ac0a46fSAndroid Build Coastguard Worker cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace)
946*3ac0a46fSAndroid Build Coastguard Worker {
947*3ac0a46fSAndroid Build Coastguard Worker     int n = cmsChannelsOfColorSpace(ColorSpace);
948*3ac0a46fSAndroid Build Coastguard Worker     if (n < 0) return 3;
949*3ac0a46fSAndroid Build Coastguard Worker     return (cmsUInt32Number)n;
950*3ac0a46fSAndroid Build Coastguard Worker }