xref: /aosp_15_r20/external/pdfium/third_party/lcms/src/cmscam02.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 // CIECAM 02 appearance model. Many thanks to Jordi Vilar for the debugging.
30*3ac0a46fSAndroid Build Coastguard Worker 
31*3ac0a46fSAndroid Build Coastguard Worker // ---------- Implementation --------------------------------------------
32*3ac0a46fSAndroid Build Coastguard Worker 
33*3ac0a46fSAndroid Build Coastguard Worker typedef struct  {
34*3ac0a46fSAndroid Build Coastguard Worker 
35*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number XYZ[3];
36*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number RGB[3];
37*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number RGBc[3];
38*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number RGBp[3];
39*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number RGBpa[3];
40*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number a, b, h, e, H, A, J, Q, s, t, C, M;
41*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number abC[2];
42*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number abs[2];
43*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number abM[2];
44*3ac0a46fSAndroid Build Coastguard Worker 
45*3ac0a46fSAndroid Build Coastguard Worker } CAM02COLOR;
46*3ac0a46fSAndroid Build Coastguard Worker 
47*3ac0a46fSAndroid Build Coastguard Worker typedef struct  {
48*3ac0a46fSAndroid Build Coastguard Worker 
49*3ac0a46fSAndroid Build Coastguard Worker     CAM02COLOR adoptedWhite;
50*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number LA, Yb;
51*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number F, c, Nc;
52*3ac0a46fSAndroid Build Coastguard Worker     cmsUInt32Number surround;
53*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number n, Nbb, Ncb, z, FL, D;
54*3ac0a46fSAndroid Build Coastguard Worker 
55*3ac0a46fSAndroid Build Coastguard Worker     cmsContext ContextID;
56*3ac0a46fSAndroid Build Coastguard Worker 
57*3ac0a46fSAndroid Build Coastguard Worker } cmsCIECAM02;
58*3ac0a46fSAndroid Build Coastguard Worker 
59*3ac0a46fSAndroid Build Coastguard Worker 
60*3ac0a46fSAndroid Build Coastguard Worker static
compute_n(cmsCIECAM02 * pMod)61*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number compute_n(cmsCIECAM02* pMod)
62*3ac0a46fSAndroid Build Coastguard Worker {
63*3ac0a46fSAndroid Build Coastguard Worker     return (pMod -> Yb / pMod -> adoptedWhite.XYZ[1]);
64*3ac0a46fSAndroid Build Coastguard Worker }
65*3ac0a46fSAndroid Build Coastguard Worker 
66*3ac0a46fSAndroid Build Coastguard Worker static
compute_z(cmsCIECAM02 * pMod)67*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number compute_z(cmsCIECAM02* pMod)
68*3ac0a46fSAndroid Build Coastguard Worker {
69*3ac0a46fSAndroid Build Coastguard Worker     return (1.48 + pow(pMod -> n, 0.5));
70*3ac0a46fSAndroid Build Coastguard Worker }
71*3ac0a46fSAndroid Build Coastguard Worker 
72*3ac0a46fSAndroid Build Coastguard Worker static
computeNbb(cmsCIECAM02 * pMod)73*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number computeNbb(cmsCIECAM02* pMod)
74*3ac0a46fSAndroid Build Coastguard Worker {
75*3ac0a46fSAndroid Build Coastguard Worker     return (0.725 * pow((1.0 / pMod -> n), 0.2));
76*3ac0a46fSAndroid Build Coastguard Worker }
77*3ac0a46fSAndroid Build Coastguard Worker 
78*3ac0a46fSAndroid Build Coastguard Worker static
computeFL(cmsCIECAM02 * pMod)79*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number computeFL(cmsCIECAM02* pMod)
80*3ac0a46fSAndroid Build Coastguard Worker {
81*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number k, FL;
82*3ac0a46fSAndroid Build Coastguard Worker 
83*3ac0a46fSAndroid Build Coastguard Worker     k = 1.0 / ((5.0 * pMod->LA) + 1.0);
84*3ac0a46fSAndroid Build Coastguard Worker     FL = 0.2 * pow(k, 4.0) * (5.0 * pMod->LA) + 0.1 *
85*3ac0a46fSAndroid Build Coastguard Worker         (pow((1.0 - pow(k, 4.0)), 2.0)) *
86*3ac0a46fSAndroid Build Coastguard Worker         (pow((5.0 * pMod->LA), (1.0 / 3.0)));
87*3ac0a46fSAndroid Build Coastguard Worker 
88*3ac0a46fSAndroid Build Coastguard Worker     return FL;
89*3ac0a46fSAndroid Build Coastguard Worker }
90*3ac0a46fSAndroid Build Coastguard Worker 
91*3ac0a46fSAndroid Build Coastguard Worker static
computeD(cmsCIECAM02 * pMod)92*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number computeD(cmsCIECAM02* pMod)
93*3ac0a46fSAndroid Build Coastguard Worker {
94*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number D;
95*3ac0a46fSAndroid Build Coastguard Worker 
96*3ac0a46fSAndroid Build Coastguard Worker     D = pMod->F - (1.0/3.6)*(exp(((-pMod ->LA-42) / 92.0)));
97*3ac0a46fSAndroid Build Coastguard Worker 
98*3ac0a46fSAndroid Build Coastguard Worker     return D;
99*3ac0a46fSAndroid Build Coastguard Worker }
100*3ac0a46fSAndroid Build Coastguard Worker 
101*3ac0a46fSAndroid Build Coastguard Worker 
102*3ac0a46fSAndroid Build Coastguard Worker static
XYZtoCAT02(CAM02COLOR clr)103*3ac0a46fSAndroid Build Coastguard Worker CAM02COLOR XYZtoCAT02(CAM02COLOR clr)
104*3ac0a46fSAndroid Build Coastguard Worker {
105*3ac0a46fSAndroid Build Coastguard Worker     clr.RGB[0] = (clr.XYZ[0] *  0.7328) + (clr.XYZ[1] *  0.4296) + (clr.XYZ[2] * -0.1624);
106*3ac0a46fSAndroid Build Coastguard Worker     clr.RGB[1] = (clr.XYZ[0] * -0.7036) + (clr.XYZ[1] *  1.6975) + (clr.XYZ[2] *  0.0061);
107*3ac0a46fSAndroid Build Coastguard Worker     clr.RGB[2] = (clr.XYZ[0] *  0.0030) + (clr.XYZ[1] *  0.0136) + (clr.XYZ[2] *  0.9834);
108*3ac0a46fSAndroid Build Coastguard Worker 
109*3ac0a46fSAndroid Build Coastguard Worker     return clr;
110*3ac0a46fSAndroid Build Coastguard Worker }
111*3ac0a46fSAndroid Build Coastguard Worker 
112*3ac0a46fSAndroid Build Coastguard Worker static
ChromaticAdaptation(CAM02COLOR clr,cmsCIECAM02 * pMod)113*3ac0a46fSAndroid Build Coastguard Worker CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
114*3ac0a46fSAndroid Build Coastguard Worker {
115*3ac0a46fSAndroid Build Coastguard Worker     cmsUInt32Number i;
116*3ac0a46fSAndroid Build Coastguard Worker 
117*3ac0a46fSAndroid Build Coastguard Worker     for (i = 0; i < 3; i++) {
118*3ac0a46fSAndroid Build Coastguard Worker         clr.RGBc[i] = ((pMod -> adoptedWhite.XYZ[1] *
119*3ac0a46fSAndroid Build Coastguard Worker             (pMod->D / pMod -> adoptedWhite.RGB[i])) +
120*3ac0a46fSAndroid Build Coastguard Worker             (1.0 - pMod->D)) * clr.RGB[i];
121*3ac0a46fSAndroid Build Coastguard Worker     }
122*3ac0a46fSAndroid Build Coastguard Worker 
123*3ac0a46fSAndroid Build Coastguard Worker     return clr;
124*3ac0a46fSAndroid Build Coastguard Worker }
125*3ac0a46fSAndroid Build Coastguard Worker 
126*3ac0a46fSAndroid Build Coastguard Worker 
127*3ac0a46fSAndroid Build Coastguard Worker static
CAT02toHPE(CAM02COLOR clr)128*3ac0a46fSAndroid Build Coastguard Worker CAM02COLOR CAT02toHPE(CAM02COLOR clr)
129*3ac0a46fSAndroid Build Coastguard Worker {
130*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number M[9];
131*3ac0a46fSAndroid Build Coastguard Worker 
132*3ac0a46fSAndroid Build Coastguard Worker     M[0] =(( 0.38971 *  1.096124) + (0.68898 * 0.454369) + (-0.07868 * -0.009628));
133*3ac0a46fSAndroid Build Coastguard Worker     M[1] =(( 0.38971 * -0.278869) + (0.68898 * 0.473533) + (-0.07868 * -0.005698));
134*3ac0a46fSAndroid Build Coastguard Worker     M[2] =(( 0.38971 *  0.182745) + (0.68898 * 0.072098) + (-0.07868 *  1.015326));
135*3ac0a46fSAndroid Build Coastguard Worker     M[3] =((-0.22981 *  1.096124) + (1.18340 * 0.454369) + ( 0.04641 * -0.009628));
136*3ac0a46fSAndroid Build Coastguard Worker     M[4] =((-0.22981 * -0.278869) + (1.18340 * 0.473533) + ( 0.04641 * -0.005698));
137*3ac0a46fSAndroid Build Coastguard Worker     M[5] =((-0.22981 *  0.182745) + (1.18340 * 0.072098) + ( 0.04641 *  1.015326));
138*3ac0a46fSAndroid Build Coastguard Worker     M[6] =(-0.009628);
139*3ac0a46fSAndroid Build Coastguard Worker     M[7] =(-0.005698);
140*3ac0a46fSAndroid Build Coastguard Worker     M[8] =( 1.015326);
141*3ac0a46fSAndroid Build Coastguard Worker 
142*3ac0a46fSAndroid Build Coastguard Worker     clr.RGBp[0] = (clr.RGBc[0] * M[0]) +  (clr.RGBc[1] * M[1]) + (clr.RGBc[2] * M[2]);
143*3ac0a46fSAndroid Build Coastguard Worker     clr.RGBp[1] = (clr.RGBc[0] * M[3]) +  (clr.RGBc[1] * M[4]) + (clr.RGBc[2] * M[5]);
144*3ac0a46fSAndroid Build Coastguard Worker     clr.RGBp[2] = (clr.RGBc[0] * M[6]) +  (clr.RGBc[1] * M[7]) + (clr.RGBc[2] * M[8]);
145*3ac0a46fSAndroid Build Coastguard Worker 
146*3ac0a46fSAndroid Build Coastguard Worker     return  clr;
147*3ac0a46fSAndroid Build Coastguard Worker }
148*3ac0a46fSAndroid Build Coastguard Worker 
149*3ac0a46fSAndroid Build Coastguard Worker static
NonlinearCompression(CAM02COLOR clr,cmsCIECAM02 * pMod)150*3ac0a46fSAndroid Build Coastguard Worker CAM02COLOR NonlinearCompression(CAM02COLOR clr, cmsCIECAM02* pMod)
151*3ac0a46fSAndroid Build Coastguard Worker {
152*3ac0a46fSAndroid Build Coastguard Worker     cmsUInt32Number i;
153*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number temp;
154*3ac0a46fSAndroid Build Coastguard Worker 
155*3ac0a46fSAndroid Build Coastguard Worker     for (i = 0; i < 3; i++) {
156*3ac0a46fSAndroid Build Coastguard Worker         if (clr.RGBp[i] < 0) {
157*3ac0a46fSAndroid Build Coastguard Worker 
158*3ac0a46fSAndroid Build Coastguard Worker             temp = pow((-1.0 * pMod->FL * clr.RGBp[i] / 100.0), 0.42);
159*3ac0a46fSAndroid Build Coastguard Worker             clr.RGBpa[i] = (-1.0 * 400.0 * temp) / (temp + 27.13) + 0.1;
160*3ac0a46fSAndroid Build Coastguard Worker         }
161*3ac0a46fSAndroid Build Coastguard Worker         else {
162*3ac0a46fSAndroid Build Coastguard Worker             temp = pow((pMod->FL * clr.RGBp[i] / 100.0), 0.42);
163*3ac0a46fSAndroid Build Coastguard Worker             clr.RGBpa[i] = (400.0 * temp) / (temp + 27.13) + 0.1;
164*3ac0a46fSAndroid Build Coastguard Worker         }
165*3ac0a46fSAndroid Build Coastguard Worker     }
166*3ac0a46fSAndroid Build Coastguard Worker 
167*3ac0a46fSAndroid Build Coastguard Worker     clr.A = (((2.0 * clr.RGBpa[0]) + clr.RGBpa[1] +
168*3ac0a46fSAndroid Build Coastguard Worker         (clr.RGBpa[2] / 20.0)) - 0.305) * pMod->Nbb;
169*3ac0a46fSAndroid Build Coastguard Worker 
170*3ac0a46fSAndroid Build Coastguard Worker     return clr;
171*3ac0a46fSAndroid Build Coastguard Worker }
172*3ac0a46fSAndroid Build Coastguard Worker 
173*3ac0a46fSAndroid Build Coastguard Worker static
ComputeCorrelates(CAM02COLOR clr,cmsCIECAM02 * pMod)174*3ac0a46fSAndroid Build Coastguard Worker CAM02COLOR ComputeCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
175*3ac0a46fSAndroid Build Coastguard Worker {
176*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number a, b, temp, e, t, r2d, d2r;
177*3ac0a46fSAndroid Build Coastguard Worker 
178*3ac0a46fSAndroid Build Coastguard Worker     a = clr.RGBpa[0] - (12.0 * clr.RGBpa[1] / 11.0) + (clr.RGBpa[2] / 11.0);
179*3ac0a46fSAndroid Build Coastguard Worker     b = (clr.RGBpa[0] + clr.RGBpa[1] - (2.0 * clr.RGBpa[2])) / 9.0;
180*3ac0a46fSAndroid Build Coastguard Worker 
181*3ac0a46fSAndroid Build Coastguard Worker     r2d = (180.0 / 3.141592654);
182*3ac0a46fSAndroid Build Coastguard Worker     if (a == 0) {
183*3ac0a46fSAndroid Build Coastguard Worker         if (b == 0)     clr.h = 0;
184*3ac0a46fSAndroid Build Coastguard Worker         else if (b > 0) clr.h = 90;
185*3ac0a46fSAndroid Build Coastguard Worker         else            clr.h = 270;
186*3ac0a46fSAndroid Build Coastguard Worker     }
187*3ac0a46fSAndroid Build Coastguard Worker     else if (a > 0) {
188*3ac0a46fSAndroid Build Coastguard Worker         temp = b / a;
189*3ac0a46fSAndroid Build Coastguard Worker         if (b > 0)       clr.h = (r2d * atan(temp));
190*3ac0a46fSAndroid Build Coastguard Worker         else if (b == 0) clr.h = 0;
191*3ac0a46fSAndroid Build Coastguard Worker         else             clr.h = (r2d * atan(temp)) + 360;
192*3ac0a46fSAndroid Build Coastguard Worker     }
193*3ac0a46fSAndroid Build Coastguard Worker     else {
194*3ac0a46fSAndroid Build Coastguard Worker         temp = b / a;
195*3ac0a46fSAndroid Build Coastguard Worker         clr.h = (r2d * atan(temp)) + 180;
196*3ac0a46fSAndroid Build Coastguard Worker     }
197*3ac0a46fSAndroid Build Coastguard Worker 
198*3ac0a46fSAndroid Build Coastguard Worker     d2r = (3.141592654 / 180.0);
199*3ac0a46fSAndroid Build Coastguard Worker     e = ((12500.0 / 13.0) * pMod->Nc * pMod->Ncb) *
200*3ac0a46fSAndroid Build Coastguard Worker         (cos((clr.h * d2r + 2.0)) + 3.8);
201*3ac0a46fSAndroid Build Coastguard Worker 
202*3ac0a46fSAndroid Build Coastguard Worker     if (clr.h < 20.14) {
203*3ac0a46fSAndroid Build Coastguard Worker         temp = ((clr.h + 122.47)/1.2) + ((20.14 - clr.h)/0.8);
204*3ac0a46fSAndroid Build Coastguard Worker         clr.H = 300 + (100*((clr.h + 122.47)/1.2)) / temp;
205*3ac0a46fSAndroid Build Coastguard Worker     }
206*3ac0a46fSAndroid Build Coastguard Worker     else if (clr.h < 90.0) {
207*3ac0a46fSAndroid Build Coastguard Worker         temp = ((clr.h - 20.14)/0.8) + ((90.00 - clr.h)/0.7);
208*3ac0a46fSAndroid Build Coastguard Worker         clr.H = (100*((clr.h - 20.14)/0.8)) / temp;
209*3ac0a46fSAndroid Build Coastguard Worker     }
210*3ac0a46fSAndroid Build Coastguard Worker     else if (clr.h < 164.25) {
211*3ac0a46fSAndroid Build Coastguard Worker         temp = ((clr.h - 90.00)/0.7) + ((164.25 - clr.h)/1.0);
212*3ac0a46fSAndroid Build Coastguard Worker         clr.H = 100 + ((100*((clr.h - 90.00)/0.7)) / temp);
213*3ac0a46fSAndroid Build Coastguard Worker     }
214*3ac0a46fSAndroid Build Coastguard Worker     else if (clr.h < 237.53) {
215*3ac0a46fSAndroid Build Coastguard Worker         temp = ((clr.h - 164.25)/1.0) + ((237.53 - clr.h)/1.2);
216*3ac0a46fSAndroid Build Coastguard Worker         clr.H = 200 + ((100*((clr.h - 164.25)/1.0)) / temp);
217*3ac0a46fSAndroid Build Coastguard Worker     }
218*3ac0a46fSAndroid Build Coastguard Worker     else {
219*3ac0a46fSAndroid Build Coastguard Worker         temp = ((clr.h - 237.53)/1.2) + ((360 - clr.h + 20.14)/0.8);
220*3ac0a46fSAndroid Build Coastguard Worker         clr.H = 300 + ((100*((clr.h - 237.53)/1.2)) / temp);
221*3ac0a46fSAndroid Build Coastguard Worker     }
222*3ac0a46fSAndroid Build Coastguard Worker 
223*3ac0a46fSAndroid Build Coastguard Worker     clr.J = 100.0 * pow((clr.A / pMod->adoptedWhite.A),
224*3ac0a46fSAndroid Build Coastguard Worker         (pMod->c * pMod->z));
225*3ac0a46fSAndroid Build Coastguard Worker 
226*3ac0a46fSAndroid Build Coastguard Worker     clr.Q = (4.0 / pMod->c) * pow((clr.J / 100.0), 0.5) *
227*3ac0a46fSAndroid Build Coastguard Worker         (pMod->adoptedWhite.A + 4.0) * pow(pMod->FL, 0.25);
228*3ac0a46fSAndroid Build Coastguard Worker 
229*3ac0a46fSAndroid Build Coastguard Worker     t = (e * pow(((a * a) + (b * b)), 0.5)) /
230*3ac0a46fSAndroid Build Coastguard Worker         (clr.RGBpa[0] + clr.RGBpa[1] +
231*3ac0a46fSAndroid Build Coastguard Worker         ((21.0 / 20.0) * clr.RGBpa[2]));
232*3ac0a46fSAndroid Build Coastguard Worker 
233*3ac0a46fSAndroid Build Coastguard Worker     clr.C = pow(t, 0.9) * pow((clr.J / 100.0), 0.5) *
234*3ac0a46fSAndroid Build Coastguard Worker         pow((1.64 - pow(0.29, pMod->n)), 0.73);
235*3ac0a46fSAndroid Build Coastguard Worker 
236*3ac0a46fSAndroid Build Coastguard Worker     clr.M = clr.C * pow(pMod->FL, 0.25);
237*3ac0a46fSAndroid Build Coastguard Worker     clr.s = 100.0 * pow((clr.M / clr.Q), 0.5);
238*3ac0a46fSAndroid Build Coastguard Worker 
239*3ac0a46fSAndroid Build Coastguard Worker     return clr;
240*3ac0a46fSAndroid Build Coastguard Worker }
241*3ac0a46fSAndroid Build Coastguard Worker 
242*3ac0a46fSAndroid Build Coastguard Worker 
243*3ac0a46fSAndroid Build Coastguard Worker static
InverseCorrelates(CAM02COLOR clr,cmsCIECAM02 * pMod)244*3ac0a46fSAndroid Build Coastguard Worker CAM02COLOR InverseCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
245*3ac0a46fSAndroid Build Coastguard Worker {
246*3ac0a46fSAndroid Build Coastguard Worker 
247*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number t, e, p1, p2, p3, p4, p5, hr, d2r;
248*3ac0a46fSAndroid Build Coastguard Worker     d2r = 3.141592654 / 180.0;
249*3ac0a46fSAndroid Build Coastguard Worker 
250*3ac0a46fSAndroid Build Coastguard Worker     t = pow( (clr.C / (pow((clr.J / 100.0), 0.5) *
251*3ac0a46fSAndroid Build Coastguard Worker         (pow((1.64 - pow(0.29, pMod->n)), 0.73)))),
252*3ac0a46fSAndroid Build Coastguard Worker         (1.0 / 0.9) );
253*3ac0a46fSAndroid Build Coastguard Worker     e = ((12500.0 / 13.0) * pMod->Nc * pMod->Ncb) *
254*3ac0a46fSAndroid Build Coastguard Worker         (cos((clr.h * d2r + 2.0)) + 3.8);
255*3ac0a46fSAndroid Build Coastguard Worker 
256*3ac0a46fSAndroid Build Coastguard Worker     clr.A = pMod->adoptedWhite.A * pow(
257*3ac0a46fSAndroid Build Coastguard Worker            (clr.J / 100.0),
258*3ac0a46fSAndroid Build Coastguard Worker            (1.0 / (pMod->c * pMod->z)));
259*3ac0a46fSAndroid Build Coastguard Worker 
260*3ac0a46fSAndroid Build Coastguard Worker     p1 = e / t;
261*3ac0a46fSAndroid Build Coastguard Worker     p2 = (clr.A / pMod->Nbb) + 0.305;
262*3ac0a46fSAndroid Build Coastguard Worker     p3 = 21.0 / 20.0;
263*3ac0a46fSAndroid Build Coastguard Worker 
264*3ac0a46fSAndroid Build Coastguard Worker     hr = clr.h * d2r;
265*3ac0a46fSAndroid Build Coastguard Worker 
266*3ac0a46fSAndroid Build Coastguard Worker     if (fabs(sin(hr)) >= fabs(cos(hr))) {
267*3ac0a46fSAndroid Build Coastguard Worker         p4 = p1 / sin(hr);
268*3ac0a46fSAndroid Build Coastguard Worker         clr.b = (p2 * (2.0 + p3) * (460.0 / 1403.0)) /
269*3ac0a46fSAndroid Build Coastguard Worker             (p4 + (2.0 + p3) * (220.0 / 1403.0) *
270*3ac0a46fSAndroid Build Coastguard Worker             (cos(hr) / sin(hr)) - (27.0 / 1403.0) +
271*3ac0a46fSAndroid Build Coastguard Worker             p3 * (6300.0 / 1403.0));
272*3ac0a46fSAndroid Build Coastguard Worker         clr.a = clr.b * (cos(hr) / sin(hr));
273*3ac0a46fSAndroid Build Coastguard Worker     }
274*3ac0a46fSAndroid Build Coastguard Worker     else {
275*3ac0a46fSAndroid Build Coastguard Worker         p5 = p1 / cos(hr);
276*3ac0a46fSAndroid Build Coastguard Worker         clr.a = (p2 * (2.0 + p3) * (460.0 / 1403.0)) /
277*3ac0a46fSAndroid Build Coastguard Worker             (p5 + (2.0 + p3) * (220.0 / 1403.0) -
278*3ac0a46fSAndroid Build Coastguard Worker             ((27.0 / 1403.0) - p3 * (6300.0 / 1403.0)) *
279*3ac0a46fSAndroid Build Coastguard Worker             (sin(hr) / cos(hr)));
280*3ac0a46fSAndroid Build Coastguard Worker         clr.b = clr.a * (sin(hr) / cos(hr));
281*3ac0a46fSAndroid Build Coastguard Worker     }
282*3ac0a46fSAndroid Build Coastguard Worker 
283*3ac0a46fSAndroid Build Coastguard Worker     clr.RGBpa[0] = ((460.0 / 1403.0) * p2) +
284*3ac0a46fSAndroid Build Coastguard Worker               ((451.0 / 1403.0) * clr.a) +
285*3ac0a46fSAndroid Build Coastguard Worker               ((288.0 / 1403.0) * clr.b);
286*3ac0a46fSAndroid Build Coastguard Worker     clr.RGBpa[1] = ((460.0 / 1403.0) * p2) -
287*3ac0a46fSAndroid Build Coastguard Worker               ((891.0 / 1403.0) * clr.a) -
288*3ac0a46fSAndroid Build Coastguard Worker               ((261.0 / 1403.0) * clr.b);
289*3ac0a46fSAndroid Build Coastguard Worker     clr.RGBpa[2] = ((460.0 / 1403.0) * p2) -
290*3ac0a46fSAndroid Build Coastguard Worker               ((220.0 / 1403.0) * clr.a) -
291*3ac0a46fSAndroid Build Coastguard Worker               ((6300.0 / 1403.0) * clr.b);
292*3ac0a46fSAndroid Build Coastguard Worker 
293*3ac0a46fSAndroid Build Coastguard Worker     return clr;
294*3ac0a46fSAndroid Build Coastguard Worker }
295*3ac0a46fSAndroid Build Coastguard Worker 
296*3ac0a46fSAndroid Build Coastguard Worker static
InverseNonlinearity(CAM02COLOR clr,cmsCIECAM02 * pMod)297*3ac0a46fSAndroid Build Coastguard Worker CAM02COLOR InverseNonlinearity(CAM02COLOR clr, cmsCIECAM02* pMod)
298*3ac0a46fSAndroid Build Coastguard Worker {
299*3ac0a46fSAndroid Build Coastguard Worker     cmsUInt32Number i;
300*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number c1;
301*3ac0a46fSAndroid Build Coastguard Worker 
302*3ac0a46fSAndroid Build Coastguard Worker     for (i = 0; i < 3; i++) {
303*3ac0a46fSAndroid Build Coastguard Worker         if ((clr.RGBpa[i] - 0.1) < 0) c1 = -1;
304*3ac0a46fSAndroid Build Coastguard Worker         else                               c1 = 1;
305*3ac0a46fSAndroid Build Coastguard Worker         clr.RGBp[i] = c1 * (100.0 / pMod->FL) *
306*3ac0a46fSAndroid Build Coastguard Worker             pow(((27.13 * fabs(clr.RGBpa[i] - 0.1)) /
307*3ac0a46fSAndroid Build Coastguard Worker             (400.0 - fabs(clr.RGBpa[i] - 0.1))),
308*3ac0a46fSAndroid Build Coastguard Worker             (1.0 / 0.42));
309*3ac0a46fSAndroid Build Coastguard Worker     }
310*3ac0a46fSAndroid Build Coastguard Worker 
311*3ac0a46fSAndroid Build Coastguard Worker     return clr;
312*3ac0a46fSAndroid Build Coastguard Worker }
313*3ac0a46fSAndroid Build Coastguard Worker 
314*3ac0a46fSAndroid Build Coastguard Worker static
HPEtoCAT02(CAM02COLOR clr)315*3ac0a46fSAndroid Build Coastguard Worker CAM02COLOR HPEtoCAT02(CAM02COLOR clr)
316*3ac0a46fSAndroid Build Coastguard Worker {
317*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number M[9];
318*3ac0a46fSAndroid Build Coastguard Worker 
319*3ac0a46fSAndroid Build Coastguard Worker     M[0] = (( 0.7328 *  1.910197) + (0.4296 * 0.370950));
320*3ac0a46fSAndroid Build Coastguard Worker     M[1] = (( 0.7328 * -1.112124) + (0.4296 * 0.629054));
321*3ac0a46fSAndroid Build Coastguard Worker     M[2] = (( 0.7328 *  0.201908) + (0.4296 * 0.000008) - 0.1624);
322*3ac0a46fSAndroid Build Coastguard Worker     M[3] = ((-0.7036 *  1.910197) + (1.6975 * 0.370950));
323*3ac0a46fSAndroid Build Coastguard Worker     M[4] = ((-0.7036 * -1.112124) + (1.6975 * 0.629054));
324*3ac0a46fSAndroid Build Coastguard Worker     M[5] = ((-0.7036 *  0.201908) + (1.6975 * 0.000008) + 0.0061);
325*3ac0a46fSAndroid Build Coastguard Worker     M[6] = (( 0.0030 *  1.910197) + (0.0136 * 0.370950));
326*3ac0a46fSAndroid Build Coastguard Worker     M[7] = (( 0.0030 * -1.112124) + (0.0136 * 0.629054));
327*3ac0a46fSAndroid Build Coastguard Worker     M[8] = (( 0.0030 *  0.201908) + (0.0136 * 0.000008) + 0.9834);
328*3ac0a46fSAndroid Build Coastguard Worker 
329*3ac0a46fSAndroid Build Coastguard Worker     clr.RGBc[0] = (clr.RGBp[0] * M[0]) + (clr.RGBp[1] * M[1]) + (clr.RGBp[2] * M[2]);
330*3ac0a46fSAndroid Build Coastguard Worker     clr.RGBc[1] = (clr.RGBp[0] * M[3]) + (clr.RGBp[1] * M[4]) + (clr.RGBp[2] * M[5]);
331*3ac0a46fSAndroid Build Coastguard Worker     clr.RGBc[2] = (clr.RGBp[0] * M[6]) + (clr.RGBp[1] * M[7]) + (clr.RGBp[2] * M[8]);
332*3ac0a46fSAndroid Build Coastguard Worker     return clr;
333*3ac0a46fSAndroid Build Coastguard Worker }
334*3ac0a46fSAndroid Build Coastguard Worker 
335*3ac0a46fSAndroid Build Coastguard Worker 
336*3ac0a46fSAndroid Build Coastguard Worker static
InverseChromaticAdaptation(CAM02COLOR clr,cmsCIECAM02 * pMod)337*3ac0a46fSAndroid Build Coastguard Worker CAM02COLOR InverseChromaticAdaptation(CAM02COLOR clr,  cmsCIECAM02* pMod)
338*3ac0a46fSAndroid Build Coastguard Worker {
339*3ac0a46fSAndroid Build Coastguard Worker     cmsUInt32Number i;
340*3ac0a46fSAndroid Build Coastguard Worker     for (i = 0; i < 3; i++) {
341*3ac0a46fSAndroid Build Coastguard Worker         clr.RGB[i] = clr.RGBc[i] /
342*3ac0a46fSAndroid Build Coastguard Worker             ((pMod->adoptedWhite.XYZ[1] * pMod->D / pMod->adoptedWhite.RGB[i]) + 1.0 - pMod->D);
343*3ac0a46fSAndroid Build Coastguard Worker     }
344*3ac0a46fSAndroid Build Coastguard Worker     return clr;
345*3ac0a46fSAndroid Build Coastguard Worker }
346*3ac0a46fSAndroid Build Coastguard Worker 
347*3ac0a46fSAndroid Build Coastguard Worker 
348*3ac0a46fSAndroid Build Coastguard Worker static
CAT02toXYZ(CAM02COLOR clr)349*3ac0a46fSAndroid Build Coastguard Worker CAM02COLOR CAT02toXYZ(CAM02COLOR clr)
350*3ac0a46fSAndroid Build Coastguard Worker {
351*3ac0a46fSAndroid Build Coastguard Worker     clr.XYZ[0] = (clr.RGB[0] *  1.096124) + (clr.RGB[1] * -0.278869) + (clr.RGB[2] *  0.182745);
352*3ac0a46fSAndroid Build Coastguard Worker     clr.XYZ[1] = (clr.RGB[0] *  0.454369) + (clr.RGB[1] *  0.473533) + (clr.RGB[2] *  0.072098);
353*3ac0a46fSAndroid Build Coastguard Worker     clr.XYZ[2] = (clr.RGB[0] * -0.009628) + (clr.RGB[1] * -0.005698) + (clr.RGB[2] *  1.015326);
354*3ac0a46fSAndroid Build Coastguard Worker 
355*3ac0a46fSAndroid Build Coastguard Worker     return clr;
356*3ac0a46fSAndroid Build Coastguard Worker }
357*3ac0a46fSAndroid Build Coastguard Worker 
358*3ac0a46fSAndroid Build Coastguard Worker 
cmsCIECAM02Init(cmsContext ContextID,const cmsViewingConditions * pVC)359*3ac0a46fSAndroid Build Coastguard Worker cmsHANDLE  CMSEXPORT cmsCIECAM02Init(cmsContext ContextID, const cmsViewingConditions* pVC)
360*3ac0a46fSAndroid Build Coastguard Worker {
361*3ac0a46fSAndroid Build Coastguard Worker     cmsCIECAM02* lpMod;
362*3ac0a46fSAndroid Build Coastguard Worker 
363*3ac0a46fSAndroid Build Coastguard Worker     _cmsAssert(pVC != NULL);
364*3ac0a46fSAndroid Build Coastguard Worker 
365*3ac0a46fSAndroid Build Coastguard Worker     if((lpMod = (cmsCIECAM02*) _cmsMallocZero(ContextID, sizeof(cmsCIECAM02))) == NULL) {
366*3ac0a46fSAndroid Build Coastguard Worker         return NULL;
367*3ac0a46fSAndroid Build Coastguard Worker     }
368*3ac0a46fSAndroid Build Coastguard Worker 
369*3ac0a46fSAndroid Build Coastguard Worker     lpMod ->ContextID = ContextID;
370*3ac0a46fSAndroid Build Coastguard Worker 
371*3ac0a46fSAndroid Build Coastguard Worker     lpMod ->adoptedWhite.XYZ[0] = pVC ->whitePoint.X;
372*3ac0a46fSAndroid Build Coastguard Worker     lpMod ->adoptedWhite.XYZ[1] = pVC ->whitePoint.Y;
373*3ac0a46fSAndroid Build Coastguard Worker     lpMod ->adoptedWhite.XYZ[2] = pVC ->whitePoint.Z;
374*3ac0a46fSAndroid Build Coastguard Worker 
375*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> LA       = pVC ->La;
376*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> Yb       = pVC ->Yb;
377*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> D        = pVC ->D_value;
378*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> surround = pVC ->surround;
379*3ac0a46fSAndroid Build Coastguard Worker 
380*3ac0a46fSAndroid Build Coastguard Worker     switch (lpMod -> surround) {
381*3ac0a46fSAndroid Build Coastguard Worker 
382*3ac0a46fSAndroid Build Coastguard Worker 
383*3ac0a46fSAndroid Build Coastguard Worker     case CUTSHEET_SURROUND:
384*3ac0a46fSAndroid Build Coastguard Worker         lpMod->F = 0.8;
385*3ac0a46fSAndroid Build Coastguard Worker         lpMod->c = 0.41;
386*3ac0a46fSAndroid Build Coastguard Worker         lpMod->Nc = 0.8;
387*3ac0a46fSAndroid Build Coastguard Worker         break;
388*3ac0a46fSAndroid Build Coastguard Worker 
389*3ac0a46fSAndroid Build Coastguard Worker     case DARK_SURROUND:
390*3ac0a46fSAndroid Build Coastguard Worker         lpMod -> F  = 0.8;
391*3ac0a46fSAndroid Build Coastguard Worker         lpMod -> c  = 0.525;
392*3ac0a46fSAndroid Build Coastguard Worker         lpMod -> Nc = 0.8;
393*3ac0a46fSAndroid Build Coastguard Worker         break;
394*3ac0a46fSAndroid Build Coastguard Worker 
395*3ac0a46fSAndroid Build Coastguard Worker     case DIM_SURROUND:
396*3ac0a46fSAndroid Build Coastguard Worker         lpMod -> F  = 0.9;
397*3ac0a46fSAndroid Build Coastguard Worker         lpMod -> c  = 0.59;
398*3ac0a46fSAndroid Build Coastguard Worker         lpMod -> Nc = 0.95;
399*3ac0a46fSAndroid Build Coastguard Worker         break;
400*3ac0a46fSAndroid Build Coastguard Worker 
401*3ac0a46fSAndroid Build Coastguard Worker     default:
402*3ac0a46fSAndroid Build Coastguard Worker         // Average surround
403*3ac0a46fSAndroid Build Coastguard Worker         lpMod -> F  = 1.0;
404*3ac0a46fSAndroid Build Coastguard Worker         lpMod -> c  = 0.69;
405*3ac0a46fSAndroid Build Coastguard Worker         lpMod -> Nc = 1.0;
406*3ac0a46fSAndroid Build Coastguard Worker     }
407*3ac0a46fSAndroid Build Coastguard Worker 
408*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> n   = compute_n(lpMod);
409*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> z   = compute_z(lpMod);
410*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> Nbb = computeNbb(lpMod);
411*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> FL  = computeFL(lpMod);
412*3ac0a46fSAndroid Build Coastguard Worker 
413*3ac0a46fSAndroid Build Coastguard Worker     if (lpMod -> D == D_CALCULATE) {
414*3ac0a46fSAndroid Build Coastguard Worker         lpMod -> D   = computeD(lpMod);
415*3ac0a46fSAndroid Build Coastguard Worker     }
416*3ac0a46fSAndroid Build Coastguard Worker 
417*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> Ncb = lpMod -> Nbb;
418*3ac0a46fSAndroid Build Coastguard Worker 
419*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> adoptedWhite = XYZtoCAT02(lpMod -> adoptedWhite);
420*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> adoptedWhite = ChromaticAdaptation(lpMod -> adoptedWhite, lpMod);
421*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite);
422*3ac0a46fSAndroid Build Coastguard Worker     lpMod -> adoptedWhite = NonlinearCompression(lpMod -> adoptedWhite, lpMod);
423*3ac0a46fSAndroid Build Coastguard Worker 
424*3ac0a46fSAndroid Build Coastguard Worker     return (cmsHANDLE) lpMod;
425*3ac0a46fSAndroid Build Coastguard Worker 
426*3ac0a46fSAndroid Build Coastguard Worker }
427*3ac0a46fSAndroid Build Coastguard Worker 
cmsCIECAM02Done(cmsHANDLE hModel)428*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsCIECAM02Done(cmsHANDLE hModel)
429*3ac0a46fSAndroid Build Coastguard Worker {
430*3ac0a46fSAndroid Build Coastguard Worker     cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
431*3ac0a46fSAndroid Build Coastguard Worker 
432*3ac0a46fSAndroid Build Coastguard Worker     if (lpMod) _cmsFree(lpMod ->ContextID, lpMod);
433*3ac0a46fSAndroid Build Coastguard Worker }
434*3ac0a46fSAndroid Build Coastguard Worker 
435*3ac0a46fSAndroid Build Coastguard Worker 
cmsCIECAM02Forward(cmsHANDLE hModel,const cmsCIEXYZ * pIn,cmsJCh * pOut)436*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsCIECAM02Forward(cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh* pOut)
437*3ac0a46fSAndroid Build Coastguard Worker {
438*3ac0a46fSAndroid Build Coastguard Worker     CAM02COLOR clr;
439*3ac0a46fSAndroid Build Coastguard Worker     cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
440*3ac0a46fSAndroid Build Coastguard Worker 
441*3ac0a46fSAndroid Build Coastguard Worker     _cmsAssert(lpMod != NULL);
442*3ac0a46fSAndroid Build Coastguard Worker     _cmsAssert(pIn != NULL);
443*3ac0a46fSAndroid Build Coastguard Worker     _cmsAssert(pOut != NULL);
444*3ac0a46fSAndroid Build Coastguard Worker 
445*3ac0a46fSAndroid Build Coastguard Worker     memset(&clr, 0, sizeof(clr));
446*3ac0a46fSAndroid Build Coastguard Worker 
447*3ac0a46fSAndroid Build Coastguard Worker     clr.XYZ[0] = pIn ->X;
448*3ac0a46fSAndroid Build Coastguard Worker     clr.XYZ[1] = pIn ->Y;
449*3ac0a46fSAndroid Build Coastguard Worker     clr.XYZ[2] = pIn ->Z;
450*3ac0a46fSAndroid Build Coastguard Worker 
451*3ac0a46fSAndroid Build Coastguard Worker     clr = XYZtoCAT02(clr);
452*3ac0a46fSAndroid Build Coastguard Worker     clr = ChromaticAdaptation(clr, lpMod);
453*3ac0a46fSAndroid Build Coastguard Worker     clr = CAT02toHPE(clr);
454*3ac0a46fSAndroid Build Coastguard Worker     clr = NonlinearCompression(clr, lpMod);
455*3ac0a46fSAndroid Build Coastguard Worker     clr = ComputeCorrelates(clr, lpMod);
456*3ac0a46fSAndroid Build Coastguard Worker 
457*3ac0a46fSAndroid Build Coastguard Worker     pOut ->J = clr.J;
458*3ac0a46fSAndroid Build Coastguard Worker     pOut ->C = clr.C;
459*3ac0a46fSAndroid Build Coastguard Worker     pOut ->h = clr.h;
460*3ac0a46fSAndroid Build Coastguard Worker }
461*3ac0a46fSAndroid Build Coastguard Worker 
cmsCIECAM02Reverse(cmsHANDLE hModel,const cmsJCh * pIn,cmsCIEXYZ * pOut)462*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ* pOut)
463*3ac0a46fSAndroid Build Coastguard Worker {
464*3ac0a46fSAndroid Build Coastguard Worker     CAM02COLOR clr;
465*3ac0a46fSAndroid Build Coastguard Worker     cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
466*3ac0a46fSAndroid Build Coastguard Worker 
467*3ac0a46fSAndroid Build Coastguard Worker     _cmsAssert(lpMod != NULL);
468*3ac0a46fSAndroid Build Coastguard Worker     _cmsAssert(pIn != NULL);
469*3ac0a46fSAndroid Build Coastguard Worker     _cmsAssert(pOut != NULL);
470*3ac0a46fSAndroid Build Coastguard Worker 
471*3ac0a46fSAndroid Build Coastguard Worker     memset(&clr, 0, sizeof(clr));
472*3ac0a46fSAndroid Build Coastguard Worker 
473*3ac0a46fSAndroid Build Coastguard Worker     clr.J = pIn -> J;
474*3ac0a46fSAndroid Build Coastguard Worker     clr.C = pIn -> C;
475*3ac0a46fSAndroid Build Coastguard Worker     clr.h = pIn -> h;
476*3ac0a46fSAndroid Build Coastguard Worker 
477*3ac0a46fSAndroid Build Coastguard Worker     clr = InverseCorrelates(clr, lpMod);
478*3ac0a46fSAndroid Build Coastguard Worker     clr = InverseNonlinearity(clr, lpMod);
479*3ac0a46fSAndroid Build Coastguard Worker     clr = HPEtoCAT02(clr);
480*3ac0a46fSAndroid Build Coastguard Worker     clr = InverseChromaticAdaptation(clr, lpMod);
481*3ac0a46fSAndroid Build Coastguard Worker     clr = CAT02toXYZ(clr);
482*3ac0a46fSAndroid Build Coastguard Worker 
483*3ac0a46fSAndroid Build Coastguard Worker     pOut ->X = clr.XYZ[0];
484*3ac0a46fSAndroid Build Coastguard Worker     pOut ->Y = clr.XYZ[1];
485*3ac0a46fSAndroid Build Coastguard Worker     pOut ->Z = clr.XYZ[2];
486*3ac0a46fSAndroid Build Coastguard Worker }
487