Backout bug 449422.
[wine-gecko.git] / modules / lcms / src / cmspcs.c
blob286441825da1447bb2d00fb9ba20554972373194
1 //
2 // Little cms
3 // Copyright (C) 1998-2007 Marti Maria
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the Software
10 // is furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
17 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 // inter PCS conversions XYZ <-> CIE L* a* b*
25 #include "lcms.h"
30 CIE 15:2004 CIELab is defined as:
32 L* = 116*f(Y/Yn) - 16 0 <= L* <= 100
33 a* = 500*[f(X/Xn) - f(Y/Yn)]
34 b* = 200*[f(Y/Yn) - f(Z/Zn)]
36 and
38 f(t) = t^(1/3) 1 >= t > (24/116)^3
39 (841/108)*t + (16/116) 0 <= t <= (24/116)^3
42 Reverse transform is:
44 X = Xn*[a* / 500 + (L* + 16) / 116] ^ 3 if (X/Xn) > (24/116)
45 = Xn*(a* / 500 + L* / 116) / 7.787 if (X/Xn) <= (24/116)
49 Following ICC. PCS in Lab is coded as:
51 8 bit Lab PCS:
53 L* 0..100 into a 0..ff byte.
54 a* t + 128 range is -128.0 +127.0
57 16 bit Lab PCS:
59 L* 0..100 into a 0..ff00 word.
60 a* t + 128 range is -128.0 +127.9961
64 We are always playing with 16 bits-data, so I will ignore the
65 8-bits encoding scheme.
68 Interchange Space Component Actual Range Encoded Range
69 CIE XYZ X 0 -> 1.99997 0x0000 -> 0xffff
70 CIE XYZ Y 0 -> 1.99997 0x0000 -> 0xffff
71 CIE XYZ Z 0 -> 1.99997 0x0000 -> 0xffff
73 Version 2,3
74 -----------
76 CIELAB (16 bit) L* 0 -> 100.0 0x0000 -> 0xff00
77 CIELAB (16 bit) a* -128.0 -> +127.996 0x0000 -> 0x8000 -> 0xffff
78 CIELAB (16 bit) b* -128.0 -> +127.996 0x0000 -> 0x8000 -> 0xffff
81 Version 4
82 ---------
84 CIELAB (16 bit) L* 0 -> 100.0 0x0000 -> 0xffff
85 CIELAB (16 bit) a* -128.0 -> +127 0x0000 -> 0x8080 -> 0xffff
86 CIELAB (16 bit) b* -128.0 -> +127 0x0000 -> 0x8080 -> 0xffff
93 // On most modern computers, D > 4 M (i.e. a division takes more than 4
94 // multiplications worth of time), so it is probably preferable to compute
95 // a 24 bit result directly.
97 // #define ITERATE 1
99 static
100 float CubeRoot(float x)
102 float fr, r;
103 int ex, shx;
105 /* Argument reduction */
106 fr = (float) frexp(x, &ex); /* separate into mantissa and exponent */
107 shx = ex % 3;
109 if (shx > 0)
110 shx -= 3; /* compute shx such that (ex - shx) is divisible by 3 */
112 ex = (ex - shx) / 3; /* exponent of cube root */
113 fr = (float) ldexp(fr, shx);
115 /* 0.125 <= fr < 1.0 */
117 #ifdef ITERATE
118 /* Compute seed with a quadratic approximation */
120 fr = (-0.46946116F * fr + 1.072302F) * fr + 0.3812513F;/* 0.5<=fr<1 */
121 r = ldexp(fr, ex); /* 6 bits of precision */
123 /* Newton-Raphson iterations */
125 r = (float)(2.0/3.0) * r + (float)(1.0/3.0) * x / (r * r); /* 12 bits */
126 r = (float)(2.0/3.0) * r + (float)(1.0/3.0) * x / (r * r); /* 24 bits */
127 #else /* ITERATE */
129 /* Use quartic rational polynomial with error < 2^(-24) */
131 fr = (float) (((((45.2548339756803022511987494 * fr +
132 192.2798368355061050458134625) * fr +
133 119.1654824285581628956914143) * fr +
134 13.43250139086239872172837314) * fr +
135 0.1636161226585754240958355063)
137 ((((14.80884093219134573786480845 * fr +
138 151.9714051044435648658557668) * fr +
139 168.5254414101568283957668343) * fr +
140 33.9905941350215598754191872) * fr +
141 1.0));
142 r = (float) ldexp(fr, ex); /* 24 bits of precision */
143 #endif
144 return r;
147 static
148 double f(double t)
151 const double Limit = (24.0/116.0) * (24.0/116.0) * (24.0/116.0);
153 if (t <= Limit)
154 return (841.0/108.0) * t + (16.0/116.0);
155 else
156 return CubeRoot((float) t);
160 static
161 double f_1(double t)
163 const double Limit = (24.0/116.0);
165 if (t <= Limit)
167 double tmp;
169 tmp = (108.0/841.0) * (t - (16.0/116.0));
170 if (tmp <= 0.0) return 0.0;
171 else return tmp;
174 return t * t * t;
179 void LCMSEXPORT cmsXYZ2Lab(LPcmsCIEXYZ WhitePoint, LPcmsCIELab Lab, const cmsCIEXYZ* xyz)
181 double fx, fy, fz;
183 if (xyz -> X == 0 && xyz -> Y == 0 && xyz -> Z == 0)
185 Lab -> L = 0;
186 Lab -> a = 0;
187 Lab -> b = 0;
188 return;
191 if (WhitePoint == NULL)
192 WhitePoint = cmsD50_XYZ();
194 fx = f(xyz->X / WhitePoint->X);
195 fy = f(xyz->Y / WhitePoint->Y);
196 fz = f(xyz->Z / WhitePoint->Z);
198 Lab->L = 116.0* fy - 16.;
200 Lab->a = 500.0*(fx - fy);
201 Lab->b = 200.0*(fy - fz);
206 void cmsXYZ2LabEncoded(WORD XYZ[3], WORD Lab[3])
208 Fixed32 X, Y, Z;
209 double x, y, z, L, a, b;
210 double fx, fy, fz;
211 Fixed32 wL, wa, wb;
213 X = (Fixed32) XYZ[0] << 1;
214 Y = (Fixed32) XYZ[1] << 1;
215 Z = (Fixed32) XYZ[2] << 1;
218 if (X==0 && Y==0 && Z==0) {
220 Lab[0] = 0;
221 Lab[1] = Lab[2] = 0x8000;
222 return;
225 // PCS is in D50
228 x = FIXED_TO_DOUBLE(X) / D50X;
229 y = FIXED_TO_DOUBLE(Y) / D50Y;
230 z = FIXED_TO_DOUBLE(Z) / D50Z;
233 fx = f(x);
234 fy = f(y);
235 fz = f(z);
237 L = 116.* fy - 16.;
239 a = 500.*(fx - fy);
240 b = 200.*(fy - fz);
242 a += 128.;
243 b += 128.;
245 wL = (int) (L * 652.800 + .5);
246 wa = (int) (a * 256.0 + .5);
247 wb = (int) (b * 256.0 + .5);
250 Lab[0] = Clamp_L(wL);
251 Lab[1] = Clamp_ab(wa);
252 Lab[2] = Clamp_ab(wb);
262 void LCMSEXPORT cmsLab2XYZ(LPcmsCIEXYZ WhitePoint, LPcmsCIEXYZ xyz, const cmsCIELab* Lab)
264 double x, y, z;
266 if (Lab -> L <= 0) {
267 xyz -> X = 0;
268 xyz -> Y = 0;
269 xyz -> Z = 0;
270 return;
274 if (WhitePoint == NULL)
275 WhitePoint = cmsD50_XYZ();
277 y = (Lab-> L + 16.0) / 116.0;
278 x = y + 0.002 * Lab -> a;
279 z = y - 0.005 * Lab -> b;
281 xyz -> X = f_1(x) * WhitePoint -> X;
282 xyz -> Y = f_1(y) * WhitePoint -> Y;
283 xyz -> Z = f_1(z) * WhitePoint -> Z;
289 void cmsLab2XYZEncoded(WORD Lab[3], WORD XYZ[3])
291 double L, a, b;
292 double X, Y, Z, x, y, z;
295 L = ((double) Lab[0] * 100.0) / 65280.0;
296 if (L==0.0) {
298 XYZ[0] = 0; XYZ[1] = 0; XYZ[2] = 0;
299 return;
302 a = ((double) Lab[1] / 256.0) - 128.0;
303 b = ((double) Lab[2] / 256.0) - 128.0;
305 y = (L + 16.) / 116.0;
306 x = y + 0.002 * a;
307 z = y - 0.005 * b;
309 X = f_1(x) * D50X;
310 Y = f_1(y) * D50Y;
311 Z = f_1(z) * D50Z;
313 // Convert to 1.15 fixed format PCS
316 XYZ[0] = _cmsClampWord((int) floor(X * 32768.0 + 0.5));
317 XYZ[1] = _cmsClampWord((int) floor(Y * 32768.0 + 0.5));
318 XYZ[2] = _cmsClampWord((int) floor(Z * 32768.0 + 0.5));
323 static
324 double L2float3(WORD v)
326 Fixed32 fix32;
328 fix32 = (Fixed32) v;
329 return (double) fix32 / 652.800;
333 // the a/b part
335 static
336 double ab2float3(WORD v)
338 Fixed32 fix32;
340 fix32 = (Fixed32) v;
341 return ((double) fix32/256.0)-128.0;
344 static
345 WORD L2Fix3(double L)
347 return (WORD) (L * 652.800 + 0.5);
350 static
351 WORD ab2Fix3(double ab)
353 return (WORD) ((ab + 128.0) * 256.0 + 0.5);
357 // ICC 4.0 -- ICC has changed PCS Lab encoding.
359 static
360 WORD L2Fix4(double L)
362 return (WORD) (L * 655.35 + 0.5);
365 static
366 WORD ab2Fix4(double ab)
368 return (WORD) ((ab + 128.0) * 257.0 + 0.5);
371 static
372 double L2float4(WORD v)
374 Fixed32 fix32;
376 fix32 = (Fixed32) v;
377 return (double) fix32 / 655.35;
381 // the a/b part
383 static
384 double ab2float4(WORD v)
386 Fixed32 fix32;
388 fix32 = (Fixed32) v;
389 return ((double) fix32/257.0)-128.0;
393 void LCMSEXPORT cmsLabEncoded2Float(LPcmsCIELab Lab, const WORD wLab[3])
395 Lab->L = L2float3(wLab[0]);
396 Lab->a = ab2float3(wLab[1]);
397 Lab->b = ab2float3(wLab[2]);
401 void LCMSEXPORT cmsLabEncoded2Float4(LPcmsCIELab Lab, const WORD wLab[3])
403 Lab->L = L2float4(wLab[0]);
404 Lab->a = ab2float4(wLab[1]);
405 Lab->b = ab2float4(wLab[2]);
408 static
409 double Clamp_L_double(double L)
411 if (L < 0) L = 0;
412 if (L > 100) L = 100;
414 return L;
418 static
419 double Clamp_ab_double(double ab)
421 if (ab < -128) ab = -128.0;
422 if (ab > +127.9961) ab = +127.9961;
424 return ab;
427 void LCMSEXPORT cmsFloat2LabEncoded(WORD wLab[3], const cmsCIELab* fLab)
429 cmsCIELab Lab;
432 Lab.L = Clamp_L_double(fLab ->L);
433 Lab.a = Clamp_ab_double(fLab ->a);
434 Lab.b = Clamp_ab_double(fLab ->b);
436 wLab[0] = L2Fix3(Lab.L);
437 wLab[1] = ab2Fix3(Lab.a);
438 wLab[2] = ab2Fix3(Lab.b);
442 void LCMSEXPORT cmsFloat2LabEncoded4(WORD wLab[3], const cmsCIELab* fLab)
444 cmsCIELab Lab;
447 Lab.L = fLab ->L;
448 Lab.a = fLab ->a;
449 Lab.b = fLab ->b;
452 if (Lab.L < 0) Lab.L = 0;
453 if (Lab.L > 100.) Lab.L = 100.;
455 if (Lab.a < -128.) Lab.a = -128.;
456 if (Lab.a > 127.) Lab.a = 127.;
457 if (Lab.b < -128.) Lab.b = -128.;
458 if (Lab.b > 127.) Lab.b = 127.;
461 wLab[0] = L2Fix4(Lab.L);
462 wLab[1] = ab2Fix4(Lab.a);
463 wLab[2] = ab2Fix4(Lab.b);
469 void LCMSEXPORT cmsLab2LCh(LPcmsCIELCh LCh, const cmsCIELab* Lab)
471 double a, b;
473 LCh -> L = Clamp_L_double(Lab -> L);
475 a = Clamp_ab_double(Lab -> a);
476 b = Clamp_ab_double(Lab -> b);
478 LCh -> C = pow(a * a + b * b, 0.5);
480 if (a == 0 && b == 0)
481 LCh -> h = 0;
482 else
483 LCh -> h = atan2(b, a);
486 LCh -> h *= (180. / M_PI);
489 while (LCh -> h >= 360.) // Not necessary, but included as a check.
490 LCh -> h -= 360.;
492 while (LCh -> h < 0)
493 LCh -> h += 360.;
500 void LCMSEXPORT cmsLCh2Lab(LPcmsCIELab Lab, const cmsCIELCh* LCh)
503 double h = (LCh -> h * M_PI) / 180.0;
505 Lab -> L = Clamp_L_double(LCh -> L);
506 Lab -> a = Clamp_ab_double(LCh -> C * cos(h));
507 Lab -> b = Clamp_ab_double(LCh -> C * sin(h));
515 // In XYZ All 3 components are encoded using 1.15 fixed point
517 static
518 WORD XYZ2Fix(double d)
520 return (WORD) floor(d * 32768.0 + 0.5);
524 void LCMSEXPORT cmsFloat2XYZEncoded(WORD XYZ[3], const cmsCIEXYZ* fXYZ)
526 cmsCIEXYZ xyz;
528 xyz.X = fXYZ -> X;
529 xyz.Y = fXYZ -> Y;
530 xyz.Z = fXYZ -> Z;
533 // Clamp to encodeable values.
534 // 1.99997 is reserved as out-of-gamut marker
537 if (xyz.Y <= 0) {
539 xyz.X = 0;
540 xyz.Y = 0;
541 xyz.Z = 0;
545 if (xyz.X > 1.99996)
546 xyz.X = 1.99996;
548 if (xyz.X < 0)
549 xyz.X = 0;
551 if (xyz.Y > 1.99996)
552 xyz.Y = 1.99996;
554 if (xyz.Y < 0)
555 xyz.Y = 0;
558 if (xyz.Z > 1.99996)
559 xyz.Z = 1.99996;
561 if (xyz.Z < 0)
562 xyz.Z = 0;
566 XYZ[0] = XYZ2Fix(xyz.X);
567 XYZ[1] = XYZ2Fix(xyz.Y);
568 XYZ[2] = XYZ2Fix(xyz.Z);
573 // To convert from Fixed 1.15 point to double
575 static
576 double XYZ2float(WORD v)
578 Fixed32 fix32;
580 // From 1.15 to 15.16
582 fix32 = v << 1;
584 // From fixed 15.16 to double
586 return FIXED_TO_DOUBLE(fix32);
590 void LCMSEXPORT cmsXYZEncoded2Float(LPcmsCIEXYZ fXYZ, const WORD XYZ[3])
593 fXYZ -> X = XYZ2float(XYZ[0]);
594 fXYZ -> Y = XYZ2float(XYZ[1]);
595 fXYZ -> Z = XYZ2float(XYZ[2]);