1 //---------------------------------------------------------------------------------
3 // Little Color Management System
4 // Copyright (c) 1998-2010 Marti Maria Saguer
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the Software
11 // is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 //---------------------------------------------------------------------------------
27 #include "lcms2_internal.h"
29 // inter PCS conversions XYZ <-> CIE L* a* b*
33 CIE 15:2004 CIELab is defined as:
35 L* = 116*f(Y/Yn) - 16 0 <= L* <= 100
36 a* = 500*[f(X/Xn) - f(Y/Yn)]
37 b* = 200*[f(Y/Yn) - f(Z/Zn)]
41 f(t) = t^(1/3) 1 >= t > (24/116)^3
42 (841/108)*t + (16/116) 0 <= t <= (24/116)^3
47 X = Xn*[a* / 500 + (L* + 16) / 116] ^ 3 if (X/Xn) > (24/116)
48 = Xn*(a* / 500 + L* / 116) / 7.787 if (X/Xn) <= (24/116)
52 PCS in Lab2 is encoded as:
56 L* 0..100 into a 0..ff byte.
57 a* t + 128 range is -128.0 +127.0
62 L* 0..100 into a 0..ff00 word.
63 a* t + 128 range is -128.0 +127.9961
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
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
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
91 void CMSEXPORT
cmsXYZ2xyY(cmsCIExyY
* Dest
, const cmsCIEXYZ
* Source
)
93 cmsFloat64Number ISum
;
95 ISum
= 1./(Source
-> X
+ Source
-> Y
+ Source
-> Z
);
97 Dest
-> x
= (Source
-> X
) * ISum
;
98 Dest
-> y
= (Source
-> Y
) * ISum
;
99 Dest
-> Y
= Source
-> Y
;
102 void CMSEXPORT
cmsxyY2XYZ(cmsCIEXYZ
* Dest
, const cmsCIExyY
* Source
)
104 Dest
-> X
= (Source
-> x
/ Source
-> y
) * Source
-> Y
;
105 Dest
-> Y
= Source
-> Y
;
106 Dest
-> Z
= ((1 - Source
-> x
- Source
-> y
) / Source
-> y
) * Source
-> Y
;
110 cmsFloat64Number
f(cmsFloat64Number t
)
112 const cmsFloat64Number Limit
= (24.0/116.0) * (24.0/116.0) * (24.0/116.0);
115 return (841.0/108.0) * t
+ (16.0/116.0);
117 return pow(t
, 1.0/3.0);
121 cmsFloat64Number
f_1(cmsFloat64Number t
)
123 const cmsFloat64Number Limit
= (24.0/116.0);
126 return (108.0/841.0) * (t
- (16.0/116.0));
133 // Standard XYZ to Lab. it can handle negative XZY numbers in some cases
134 void CMSEXPORT
cmsXYZ2Lab(const cmsCIEXYZ
* WhitePoint
, cmsCIELab
* Lab
, const cmsCIEXYZ
* xyz
)
136 cmsFloat64Number fx
, fy
, fz
;
138 if (WhitePoint
== NULL
)
139 WhitePoint
= cmsD50_XYZ();
141 fx
= f(xyz
->X
/ WhitePoint
->X
);
142 fy
= f(xyz
->Y
/ WhitePoint
->Y
);
143 fz
= f(xyz
->Z
/ WhitePoint
->Z
);
145 Lab
->L
= 116.0*fy
- 16.0;
146 Lab
->a
= 500.0*(fx
- fy
);
147 Lab
->b
= 200.0*(fy
- fz
);
151 // Standard XYZ to Lab. It can return negative XYZ in some cases
152 void CMSEXPORT
cmsLab2XYZ(const cmsCIEXYZ
* WhitePoint
, cmsCIEXYZ
* xyz
, const cmsCIELab
* Lab
)
154 cmsFloat64Number x
, y
, z
;
156 if (WhitePoint
== NULL
)
157 WhitePoint
= cmsD50_XYZ();
159 y
= (Lab
-> L
+ 16.0) / 116.0;
160 x
= y
+ 0.002 * Lab
-> a
;
161 z
= y
- 0.005 * Lab
-> b
;
163 xyz
-> X
= f_1(x
) * WhitePoint
-> X
;
164 xyz
-> Y
= f_1(y
) * WhitePoint
-> Y
;
165 xyz
-> Z
= f_1(z
) * WhitePoint
-> Z
;
170 cmsFloat64Number
L2float2(cmsUInt16Number v
)
172 return (cmsFloat64Number
) v
/ 652.800;
177 cmsFloat64Number
ab2float2(cmsUInt16Number v
)
179 return ((cmsFloat64Number
) v
/ 256.0) - 128.0;
183 cmsUInt16Number
L2Fix2(cmsFloat64Number L
)
185 return _cmsQuickSaturateWord(L
* 652.8);
189 cmsUInt16Number
ab2Fix2(cmsFloat64Number ab
)
191 return _cmsQuickSaturateWord((ab
+ 128.0) * 256.0);
196 cmsFloat64Number
L2float4(cmsUInt16Number v
)
198 return (cmsFloat64Number
) v
/ 655.35;
203 cmsFloat64Number
ab2float4(cmsUInt16Number v
)
205 return ((cmsFloat64Number
) v
/ 257.0) - 128.0;
209 void CMSEXPORT
cmsLabEncoded2FloatV2(cmsCIELab
* Lab
, const cmsUInt16Number wLab
[3])
211 Lab
->L
= L2float2(wLab
[0]);
212 Lab
->a
= ab2float2(wLab
[1]);
213 Lab
->b
= ab2float2(wLab
[2]);
217 void CMSEXPORT
cmsLabEncoded2Float(cmsCIELab
* Lab
, const cmsUInt16Number wLab
[3])
219 Lab
->L
= L2float4(wLab
[0]);
220 Lab
->a
= ab2float4(wLab
[1]);
221 Lab
->b
= ab2float4(wLab
[2]);
225 cmsFloat64Number
Clamp_L_doubleV2(cmsFloat64Number L
)
227 const cmsFloat64Number L_max
= (cmsFloat64Number
) (0xFFFF * 100.0) / 0xFF00;
230 if (L
> L_max
) L
= L_max
;
237 cmsFloat64Number
Clamp_ab_doubleV2(cmsFloat64Number ab
)
239 if (ab
< MIN_ENCODEABLE_ab2
) ab
= MIN_ENCODEABLE_ab2
;
240 if (ab
> MAX_ENCODEABLE_ab2
) ab
= MAX_ENCODEABLE_ab2
;
245 void CMSEXPORT
cmsFloat2LabEncodedV2(cmsUInt16Number wLab
[3], const cmsCIELab
* fLab
)
249 Lab
.L
= Clamp_L_doubleV2(fLab
->L
);
250 Lab
.a
= Clamp_ab_doubleV2(fLab
->a
);
251 Lab
.b
= Clamp_ab_doubleV2(fLab
->b
);
253 wLab
[0] = L2Fix2(Lab
.L
);
254 wLab
[1] = ab2Fix2(Lab
.a
);
255 wLab
[2] = ab2Fix2(Lab
.b
);
260 cmsFloat64Number
Clamp_L_doubleV4(cmsFloat64Number L
)
263 if (L
> 100.0) L
= 100.0;
269 cmsFloat64Number
Clamp_ab_doubleV4(cmsFloat64Number ab
)
271 if (ab
< MIN_ENCODEABLE_ab4
) ab
= MIN_ENCODEABLE_ab4
;
272 if (ab
> MAX_ENCODEABLE_ab4
) ab
= MAX_ENCODEABLE_ab4
;
278 cmsUInt16Number
L2Fix4(cmsFloat64Number L
)
280 return _cmsQuickSaturateWord(L
* 655.35);
284 cmsUInt16Number
ab2Fix4(cmsFloat64Number ab
)
286 return _cmsQuickSaturateWord((ab
+ 128.0) * 257.0);
289 void CMSEXPORT
cmsFloat2LabEncoded(cmsUInt16Number wLab
[3], const cmsCIELab
* fLab
)
293 Lab
.L
= Clamp_L_doubleV4(fLab
->L
);
294 Lab
.a
= Clamp_ab_doubleV4(fLab
->a
);
295 Lab
.b
= Clamp_ab_doubleV4(fLab
->b
);
297 wLab
[0] = L2Fix4(Lab
.L
);
298 wLab
[1] = ab2Fix4(Lab
.a
);
299 wLab
[2] = ab2Fix4(Lab
.b
);
302 // Auxiliar: convert to Radians
304 cmsFloat64Number
RADIANS(cmsFloat64Number deg
)
306 return (deg
* M_PI
) / 180.;
310 // Auxiliar: atan2 but operating in degrees and returning 0 if a==b==0
312 cmsFloat64Number
atan2deg(cmsFloat64Number a
, cmsFloat64Number b
)
316 if (a
== 0 && b
== 0)
335 cmsFloat64Number
Sqr(cmsFloat64Number v
)
339 // From cylindrical coordinates. No check is performed, then negative values are allowed
340 void CMSEXPORT
cmsLab2LCh(cmsCIELCh
* LCh
, const cmsCIELab
* Lab
)
343 LCh
-> C
= pow(Sqr(Lab
->a
) + Sqr(Lab
->b
), 0.5);
344 LCh
-> h
= atan2deg(Lab
->b
, Lab
->a
);
348 // To cylindrical coordinates. No check is performed, then negative values are allowed
349 void CMSEXPORT
cmsLCh2Lab(cmsCIELab
* Lab
, const cmsCIELCh
* LCh
)
351 cmsFloat64Number h
= (LCh
-> h
* M_PI
) / 180.0;
354 Lab
-> a
= LCh
-> C
* cos(h
);
355 Lab
-> b
= LCh
-> C
* sin(h
);
358 // In XYZ All 3 components are encoded using 1.15 fixed point
360 cmsUInt16Number
XYZ2Fix(cmsFloat64Number d
)
362 return _cmsQuickSaturateWord(d
* 32768.0);
365 void CMSEXPORT
cmsFloat2XYZEncoded(cmsUInt16Number XYZ
[3], const cmsCIEXYZ
* fXYZ
)
373 // Clamp to encodeable values.
381 if (xyz
.X
> MAX_ENCODEABLE_XYZ
)
382 xyz
.X
= MAX_ENCODEABLE_XYZ
;
387 if (xyz
.Y
> MAX_ENCODEABLE_XYZ
)
388 xyz
.Y
= MAX_ENCODEABLE_XYZ
;
393 if (xyz
.Z
> MAX_ENCODEABLE_XYZ
)
394 xyz
.Z
= MAX_ENCODEABLE_XYZ
;
400 XYZ
[0] = XYZ2Fix(xyz
.X
);
401 XYZ
[1] = XYZ2Fix(xyz
.Y
);
402 XYZ
[2] = XYZ2Fix(xyz
.Z
);
406 // To convert from Fixed 1.15 point to cmsFloat64Number
408 cmsFloat64Number
XYZ2float(cmsUInt16Number v
)
410 cmsS15Fixed16Number fix32
;
412 // From 1.15 to 15.16
415 // From fixed 15.16 to cmsFloat64Number
416 return _cms15Fixed16toDouble(fix32
);
420 void CMSEXPORT
cmsXYZEncoded2Float(cmsCIEXYZ
* fXYZ
, const cmsUInt16Number XYZ
[3])
422 fXYZ
-> X
= XYZ2float(XYZ
[0]);
423 fXYZ
-> Y
= XYZ2float(XYZ
[1]);
424 fXYZ
-> Z
= XYZ2float(XYZ
[2]);
428 // Returns dE on two Lab values
429 cmsFloat64Number CMSEXPORT
cmsDeltaE(const cmsCIELab
* Lab1
, const cmsCIELab
* Lab2
)
431 cmsFloat64Number dL
, da
, db
;
433 dL
= fabs(Lab1
-> L
- Lab2
-> L
);
434 da
= fabs(Lab1
-> a
- Lab2
-> a
);
435 db
= fabs(Lab1
-> b
- Lab2
-> b
);
437 return pow(Sqr(dL
) + Sqr(da
) + Sqr(db
), 0.5);
441 // Return the CIE94 Delta E
442 cmsFloat64Number CMSEXPORT
cmsCIE94DeltaE(const cmsCIELab
* Lab1
, const cmsCIELab
* Lab2
)
444 cmsCIELCh LCh1
, LCh2
;
445 cmsFloat64Number dE
, dL
, dC
, dh
, dhsq
;
446 cmsFloat64Number c12
, sc
, sh
;
448 dL
= fabs(Lab1
->L
- Lab2
->L
);
450 cmsLab2LCh(&LCh1
, Lab1
);
451 cmsLab2LCh(&LCh2
, Lab2
);
453 dC
= fabs(LCh1
.C
- LCh2
.C
);
454 dE
= cmsDeltaE(Lab1
, Lab2
);
456 dhsq
= Sqr(dE
) - Sqr(dL
) - Sqr(dC
);
462 c12
= sqrt(LCh1
.C
* LCh2
.C
);
464 sc
= 1.0 + (0.048 * c12
);
465 sh
= 1.0 + (0.014 * c12
);
467 return sqrt(Sqr(dL
) + Sqr(dC
) / Sqr(sc
) + Sqr(dh
) / Sqr(sh
));
473 cmsFloat64Number
ComputeLBFD(const cmsCIELab
* Lab
)
477 if (Lab
->L
> 7.996969)
478 yt
= (Sqr((Lab
->L
+16)/116)*((Lab
->L
+16)/116))*100;
480 yt
= 100 * (Lab
->L
/ 903.3);
482 return (54.6 * (M_LOG10E
* (log(yt
+ 1.5))) - 9.6);
487 // bfd - gets BFD(1:1) difference between Lab1, Lab2
488 cmsFloat64Number CMSEXPORT
cmsBFDdeltaE(const cmsCIELab
* Lab1
, const cmsCIELab
* Lab2
)
490 cmsFloat64Number lbfd1
,lbfd2
,AveC
,Aveh
,dE
,deltaL
,
491 deltaC
,deltah
,dc
,t
,g
,dh
,rh
,rc
,rt
,bfd
;
492 cmsCIELCh LCh1
, LCh2
;
495 lbfd1
= ComputeLBFD(Lab1
);
496 lbfd2
= ComputeLBFD(Lab2
);
497 deltaL
= lbfd2
- lbfd1
;
499 cmsLab2LCh(&LCh1
, Lab1
);
500 cmsLab2LCh(&LCh2
, Lab2
);
502 deltaC
= LCh2
.C
- LCh1
.C
;
503 AveC
= (LCh1
.C
+LCh2
.C
)/2;
504 Aveh
= (LCh1
.h
+LCh2
.h
)/2;
506 dE
= cmsDeltaE(Lab1
, Lab2
);
508 if (Sqr(dE
)>(Sqr(Lab2
->L
-Lab1
->L
)+Sqr(deltaC
)))
509 deltah
= sqrt(Sqr(dE
)-Sqr(Lab2
->L
-Lab1
->L
)-Sqr(deltaC
));
514 dc
= 0.035 * AveC
/ (1 + 0.00365 * AveC
)+0.521;
515 g
= sqrt(Sqr(Sqr(AveC
))/(Sqr(Sqr(AveC
))+14000));
516 t
= 0.627+(0.055*cos((Aveh
-254)/(180/M_PI
))-
517 0.040*cos((2*Aveh
-136)/(180/M_PI
))+
518 0.070*cos((3*Aveh
-31)/(180/M_PI
))+
519 0.049*cos((4*Aveh
+114)/(180/M_PI
))-
520 0.015*cos((5*Aveh
-103)/(180/M_PI
)));
523 rh
= -0.260*cos((Aveh
-308)/(180/M_PI
))-
524 0.379*cos((2*Aveh
-160)/(180/M_PI
))-
525 0.636*cos((3*Aveh
+254)/(180/M_PI
))+
526 0.226*cos((4*Aveh
+140)/(180/M_PI
))-
527 0.194*cos((5*Aveh
+280)/(180/M_PI
));
529 rc
= sqrt((AveC
*AveC
*AveC
*AveC
*AveC
*AveC
)/((AveC
*AveC
*AveC
*AveC
*AveC
*AveC
)+70000000));
532 bfd
= sqrt(Sqr(deltaL
)+Sqr(deltaC
/dc
)+Sqr(deltah
/dh
)+(rt
*(deltaC
/dc
)*(deltah
/dh
)));
538 // cmc - CMC(l:c) difference between Lab1, Lab2
539 cmsFloat64Number CMSEXPORT
cmsCMCdeltaE(const cmsCIELab
* Lab1
, const cmsCIELab
* Lab2
, cmsFloat64Number l
, cmsFloat64Number c
)
541 cmsFloat64Number dE
,dL
,dC
,dh
,sl
,sc
,sh
,t
,f
,cmc
;
542 cmsCIELCh LCh1
, LCh2
;
544 if (Lab1
->L
== 0 && Lab2
->L
== 0) return 0;
546 cmsLab2LCh(&LCh1
, Lab1
);
547 cmsLab2LCh(&LCh2
, Lab2
);
550 dL
= Lab2
->L
-Lab1
->L
;
553 dE
= cmsDeltaE(Lab1
, Lab2
);
555 if (Sqr(dE
)>(Sqr(dL
)+Sqr(dC
)))
556 dh
= sqrt(Sqr(dE
)-Sqr(dL
)-Sqr(dC
));
560 if ((LCh1
.h
> 164) && (LCh1
.h
< 345))
561 t
= 0.56 + fabs(0.2 * cos(((LCh1
.h
+ 168)/(180/M_PI
))));
563 t
= 0.36 + fabs(0.4 * cos(((LCh1
.h
+ 35 )/(180/M_PI
))));
565 sc
= 0.0638 * LCh1
.C
/ (1 + 0.0131 * LCh1
.C
) + 0.638;
566 sl
= 0.040975 * Lab1
->L
/(1 + 0.01765 * Lab1
->L
);
571 f
= sqrt((LCh1
.C
* LCh1
.C
* LCh1
.C
* LCh1
.C
)/((LCh1
.C
* LCh1
.C
* LCh1
.C
* LCh1
.C
)+1900));
573 cmc
= sqrt(Sqr(dL
/(l
*sl
))+Sqr(dC
/(c
*sc
))+Sqr(dh
/sh
));
578 // dE2000 The weightings KL, KC and KH can be modified to reflect the relative
579 // importance of lightness, chroma and hue in different industrial applications
580 cmsFloat64Number CMSEXPORT
cmsCIE2000DeltaE(const cmsCIELab
* Lab1
, const cmsCIELab
* Lab2
,
581 cmsFloat64Number Kl
, cmsFloat64Number Kc
, cmsFloat64Number Kh
)
583 cmsFloat64Number L1
= Lab1
->L
;
584 cmsFloat64Number a1
= Lab1
->a
;
585 cmsFloat64Number b1
= Lab1
->b
;
586 cmsFloat64Number C
= sqrt( Sqr(a1
) + Sqr(b1
) );
588 cmsFloat64Number Ls
= Lab2
->L
;
589 cmsFloat64Number as
= Lab2
->a
;
590 cmsFloat64Number bs
= Lab2
->b
;
591 cmsFloat64Number Cs
= sqrt( Sqr(as
) + Sqr(bs
) );
593 cmsFloat64Number G
= 0.5 * ( 1 - sqrt(pow((C
+ Cs
) / 2 , 7.0) / (pow((C
+ Cs
) / 2, 7.0) + pow(25.0, 7.0) ) ));
595 cmsFloat64Number a_p
= (1 + G
) * a1
;
596 cmsFloat64Number b_p
= b1
;
597 cmsFloat64Number C_p
= sqrt( Sqr(a_p
) + Sqr(b_p
));
598 cmsFloat64Number h_p
= atan2deg(b_p
, a_p
);
601 cmsFloat64Number a_ps
= (1 + G
) * as
;
602 cmsFloat64Number b_ps
= bs
;
603 cmsFloat64Number C_ps
= sqrt(Sqr(a_ps
) + Sqr(b_ps
));
604 cmsFloat64Number h_ps
= atan2deg(b_ps
, a_ps
);
606 cmsFloat64Number meanC_p
=(C_p
+ C_ps
) / 2;
608 cmsFloat64Number hps_plus_hp
= h_ps
+ h_p
;
609 cmsFloat64Number hps_minus_hp
= h_ps
- h_p
;
611 cmsFloat64Number meanh_p
= fabs(hps_minus_hp
) <= 180.000001 ? (hps_plus_hp
)/2 :
612 (hps_plus_hp
) < 360 ? (hps_plus_hp
+ 360)/2 :
613 (hps_plus_hp
- 360)/2;
615 cmsFloat64Number delta_h
= (hps_minus_hp
) <= -180.000001 ? (hps_minus_hp
+ 360) :
616 (hps_minus_hp
) > 180 ? (hps_minus_hp
- 360) :
618 cmsFloat64Number delta_L
= (Ls
- L1
);
619 cmsFloat64Number delta_C
= (C_ps
- C_p
);
622 cmsFloat64Number delta_H
=2 * sqrt(C_ps
*C_p
) * sin(RADIANS(delta_h
) / 2);
624 cmsFloat64Number T
= 1 - 0.17 * cos(RADIANS(meanh_p
-30))
625 + 0.24 * cos(RADIANS(2*meanh_p
))
626 + 0.32 * cos(RADIANS(3*meanh_p
+ 6))
627 - 0.2 * cos(RADIANS(4*meanh_p
- 63));
629 cmsFloat64Number Sl
= 1 + (0.015 * Sqr((Ls
+ L1
) /2- 50) )/ sqrt(20 + Sqr( (Ls
+L1
)/2 - 50) );
631 cmsFloat64Number Sc
= 1 + 0.045 * (C_p
+ C_ps
)/2;
632 cmsFloat64Number Sh
= 1 + 0.015 * ((C_ps
+ C_p
)/2) * T
;
634 cmsFloat64Number delta_ro
= 30 * exp( -Sqr(((meanh_p
- 275 ) / 25)));
636 cmsFloat64Number Rc
= 2 * sqrt(( pow(meanC_p
, 7.0) )/( pow(meanC_p
, 7.0) + pow(25.0, 7.0)));
638 cmsFloat64Number Rt
= -sin(2 * RADIANS(delta_ro
)) * Rc
;
640 cmsFloat64Number deltaE00
= sqrt( Sqr(delta_L
/(Sl
* Kl
)) +
641 Sqr(delta_C
/(Sc
* Kc
)) +
642 Sqr(delta_H
/(Sh
* Kh
)) +
643 Rt
*(delta_C
/(Sc
* Kc
)) * (delta_H
/ (Sh
* Kh
)));
648 // This function returns a number of gridpoints to be used as LUT table. It assumes same number
649 // of gripdpoints in all dimensions. Flags may override the choice.
650 int _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace
, cmsUInt32Number dwFlags
)
654 // Already specified?
655 if (dwFlags
& 0x00FF0000) {
657 return (dwFlags
>> 16) & 0xFF;
660 nChannels
= cmsChannelsOf(Colorspace
);
662 // HighResPrecalc is maximum resolution
663 if (dwFlags
& cmsFLAGS_HIGHRESPRECALC
) {
666 return 7; // 7 for Hifi
668 if (nChannels
== 4) // 23 for CMYK
671 return 49; // 49 for RGB and others
675 // LowResPrecal is lower resolution
676 if (dwFlags
& cmsFLAGS_LOWRESPRECALC
) {
679 return 6; // 6 for more than 4 channels
682 return 33; // For monochrome
684 return 17; // 17 for remaining
689 return 7; // 7 for Hifi
692 return 17; // 17 for CMYK
694 return 33; // 33 for RGB
698 cmsBool
_cmsEndPointsBySpace(cmsColorSpaceSignature Space
,
699 cmsUInt16Number
**White
,
700 cmsUInt16Number
**Black
,
701 cmsUInt32Number
*nOutputs
)
703 // Only most common spaces
705 static cmsUInt16Number RGBblack
[4] = { 0, 0, 0 };
706 static cmsUInt16Number RGBwhite
[4] = { 0xffff, 0xffff, 0xffff };
707 static cmsUInt16Number CMYKblack
[4] = { 0xffff, 0xffff, 0xffff, 0xffff }; // 400% of ink
708 static cmsUInt16Number CMYKwhite
[4] = { 0, 0, 0, 0 };
709 static cmsUInt16Number LABblack
[4] = { 0, 0x8080, 0x8080 }; // V4 Lab encoding
710 static cmsUInt16Number LABwhite
[4] = { 0xFFFF, 0x8080, 0x8080 };
711 static cmsUInt16Number CMYblack
[4] = { 0xffff, 0xffff, 0xffff };
712 static cmsUInt16Number CMYwhite
[4] = { 0, 0, 0 };
713 static cmsUInt16Number Grayblack
[4] = { 0 };
714 static cmsUInt16Number GrayWhite
[4] = { 0xffff };
718 case cmsSigGrayData
: if (White
) *White
= GrayWhite
;
719 if (Black
) *Black
= Grayblack
;
720 if (nOutputs
) *nOutputs
= 1;
723 case cmsSigRgbData
: if (White
) *White
= RGBwhite
;
724 if (Black
) *Black
= RGBblack
;
725 if (nOutputs
) *nOutputs
= 3;
728 case cmsSigLabData
: if (White
) *White
= LABwhite
;
729 if (Black
) *Black
= LABblack
;
730 if (nOutputs
) *nOutputs
= 3;
733 case cmsSigCmykData
: if (White
) *White
= CMYKwhite
;
734 if (Black
) *Black
= CMYKblack
;
735 if (nOutputs
) *nOutputs
= 4;
738 case cmsSigCmyData
: if (White
) *White
= CMYwhite
;
739 if (Black
) *Black
= CMYblack
;
740 if (nOutputs
) *nOutputs
= 3;
751 // Several utilities -------------------------------------------------------
753 // Translate from our colorspace to ICC representation
755 cmsColorSpaceSignature CMSEXPORT
_cmsICCcolorSpace(int OurNotation
)
757 switch (OurNotation
) {
760 case PT_GRAY
: return cmsSigGrayData
;
763 case PT_RGB
: return cmsSigRgbData
;
765 case PT_CMY
: return cmsSigCmyData
;
766 case PT_CMYK
: return cmsSigCmykData
;
767 case PT_YCbCr
:return cmsSigYCbCrData
;
768 case PT_YUV
: return cmsSigLuvData
;
769 case PT_XYZ
: return cmsSigXYZData
;
772 case PT_Lab
: return cmsSigLabData
;
774 case PT_YUVK
: return cmsSigLuvKData
;
775 case PT_HSV
: return cmsSigHsvData
;
776 case PT_HLS
: return cmsSigHlsData
;
777 case PT_Yxy
: return cmsSigYxyData
;
779 case PT_MCH1
: return cmsSigMCH1Data
;
780 case PT_MCH2
: return cmsSigMCH2Data
;
781 case PT_MCH3
: return cmsSigMCH3Data
;
782 case PT_MCH4
: return cmsSigMCH4Data
;
783 case PT_MCH5
: return cmsSigMCH5Data
;
784 case PT_MCH6
: return cmsSigMCH6Data
;
785 case PT_MCH7
: return cmsSigMCH7Data
;
786 case PT_MCH8
: return cmsSigMCH8Data
;
788 case PT_MCH9
: return cmsSigMCH9Data
;
789 case PT_MCH10
: return cmsSigMCHAData
;
790 case PT_MCH11
: return cmsSigMCHBData
;
791 case PT_MCH12
: return cmsSigMCHCData
;
792 case PT_MCH13
: return cmsSigMCHDData
;
793 case PT_MCH14
: return cmsSigMCHEData
;
794 case PT_MCH15
: return cmsSigMCHFData
;
796 default: return (cmsColorSpaceSignature
) (-1);
801 int CMSEXPORT
_cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace
)
803 switch (ProfileSpace
) {
805 case cmsSigGrayData
: return PT_GRAY
;
806 case cmsSigRgbData
: return PT_RGB
;
807 case cmsSigCmyData
: return PT_CMY
;
808 case cmsSigCmykData
: return PT_CMYK
;
809 case cmsSigYCbCrData
:return PT_YCbCr
;
810 case cmsSigLuvData
: return PT_YUV
;
811 case cmsSigXYZData
: return PT_XYZ
;
812 case cmsSigLabData
: return PT_Lab
;
813 case cmsSigLuvKData
: return PT_YUVK
;
814 case cmsSigHsvData
: return PT_HSV
;
815 case cmsSigHlsData
: return PT_HLS
;
816 case cmsSigYxyData
: return PT_Yxy
;
818 case cmsSig1colorData
:
819 case cmsSigMCH1Data
: return PT_MCH1
;
821 case cmsSig2colorData
:
822 case cmsSigMCH2Data
: return PT_MCH2
;
824 case cmsSig3colorData
:
825 case cmsSigMCH3Data
: return PT_MCH3
;
827 case cmsSig4colorData
:
828 case cmsSigMCH4Data
: return PT_MCH4
;
830 case cmsSig5colorData
:
831 case cmsSigMCH5Data
: return PT_MCH5
;
833 case cmsSig6colorData
:
834 case cmsSigMCH6Data
: return PT_MCH6
;
837 case cmsSig7colorData
:return PT_MCH7
;
840 case cmsSig8colorData
:return PT_MCH8
;
843 case cmsSig9colorData
:return PT_MCH9
;
846 case cmsSig10colorData
:return PT_MCH10
;
849 case cmsSig11colorData
:return PT_MCH11
;
852 case cmsSig12colorData
:return PT_MCH12
;
855 case cmsSig13colorData
:return PT_MCH13
;
858 case cmsSig14colorData
:return PT_MCH14
;
861 case cmsSig15colorData
:return PT_MCH15
;
863 default: return (cmsColorSpaceSignature
) (-1);
868 cmsUInt32Number CMSEXPORT
cmsChannelsOf(cmsColorSpaceSignature ColorSpace
)
870 switch (ColorSpace
) {
873 case cmsSig1colorData
:
874 case cmsSigGrayData
: return 1;
877 case cmsSig2colorData
: return 2;
882 case cmsSigYCbCrData
:
889 case cmsSig3colorData
: return 3;
894 case cmsSig4colorData
: return 4;
897 case cmsSig5colorData
: return 5;
900 case cmsSig6colorData
: return 6;
903 case cmsSig7colorData
: return 7;
906 case cmsSig8colorData
: return 8;
909 case cmsSig9colorData
: return 9;
912 case cmsSig10colorData
: return 10;
915 case cmsSig11colorData
: return 11;
918 case cmsSig12colorData
: return 12;
921 case cmsSig13colorData
: return 13;
924 case cmsSig14colorData
: return 14;
927 case cmsSig15colorData
: return 15;