Hoyt's FORK of DemoIccMAX 2.1.17.hoyt
Documentation for Hoyt's FORK of DemoIccMAX
Loading...
Searching...
No Matches
IccApplyBPC.cpp
Go to the documentation of this file.
1/** @file
2File: IccApplyBPC.cpp
3
4Contains: Implementation of Black Point Compensation calculations.
5
6Version: V1
7
8Copyright: (c) see ICC Software License
9*/
10
11/*
12* The ICC Software License, Version 0.2
13*
14*
15* Copyright (c) 2003-2012 The International Color Consortium. All rights
16* reserved.
17*
18* Redistribution and use in source and binary forms, with or without
19* modification, are permitted provided that the following conditions
20* are met:
21*
22* 1. Redistributions of source code must retain the above copyright
23* notice, this list of conditions and the following disclaimer.
24*
25* 2. Redistributions in binary form must reproduce the above copyright
26* notice, this list of conditions and the following disclaimer in
27* the documentation and/or other materials provided with the
28* distribution.
29*
30* 3. In the absence of prior written permission, the names "ICC" and "The
31* International Color Consortium" must not be used to imply that the
32* ICC organization endorses or promotes products derived from this
33* software.
34*
35*
36* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39* DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
40* ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47* SUCH DAMAGE.
48* ====================================================================
49*
50* This software consists of voluntary contributions made by many
51* individuals on behalf of the The International Color Consortium.
52*
53*
54* Membership in the ICC is encouraged when this software is used for
55* commercial purposes.
56*
57*
58* For more information on The International Color Consortium, please
59* see <http://www.color.org/>.
60*
61*
62*/
63
64//////////////////////////////////////////////////////////////////////
65// HISTORY:
66//
67// -Initial implementation by Rohit Patil 12-10-2008
68//
69//////////////////////////////////////////////////////////////////////
70
71#include "IccApplyBPC.h"
72#include <math.h>
73
74#define IsSpacePCS(x) ((x)==icSigXYZData || (x)==icSigLabData)
75
76/**
77**************************************************************************
78* Name: CIccApplyBPCHint::GetNewAdjustPCSXform
79*
80* Purpose:
81* Returns a new CIccApplyBPC object. Returned object should be deleted
82* by the caller.
83*
84**************************************************************************
85*/
86IIccAdjustPCSXform* CIccApplyBPCHint::GetNewAdjustPCSXform() const
87{
88 return new CIccApplyBPC();
89}
90
91//////////////////////////////////////////////////////////////////////
92// CIccApplyBPC utility functions
93//////////////////////////////////////////////////////////////////////
94
95// converts lab to pcs
96void CIccApplyBPC::lab2pcs(icFloatNumber* pixel, const CIccProfile* pProfile) const
97{
98 switch (pProfile->m_Header.pcs)
99 {
100 case icSigLabData:
101 icLabToPcs(pixel);
102 break;
103
104 case icSigXYZData:
105 icLabtoXYZ(pixel);
106 icXyzToPcs(pixel);
107 break;
108
109 default:
110 break;
111 }
112}
113
114// converts pcs to lab
115void CIccApplyBPC::pcs2lab(icFloatNumber* pixel, const CIccProfile* pProfile) const
116{
117 switch (pProfile->m_Header.pcs)
118 {
119 case icSigLabData:
120 icLabFromPcs(pixel);
121 break;
122
123 case icSigXYZData:
124 icXyzFromPcs(pixel);
125 icXYZtoLab(pixel);
126 break;
127
128 default:
129 break;
130 }
131}
132
133// calculates sum of product of x^j and y^k polynomials
135{
136 icFloatNumber dSum = 0.0;
137
138 int i;
139 if (j && k) {
140 for (i=0; i<n; i++) {
141 dSum += (icFloatNumber)(pow(x[i], j)*pow(y[i], k));
142 }
143 }
144 else if (j) {
145 for (i=0; i<n; i++) {
146 dSum += (icFloatNumber)pow(x[i], j);
147 }
148 }
149 else if (k) {
150 for (i=0; i<n; i++) {
151 dSum += (icFloatNumber)pow(y[i], k);
152 }
153 }
154 else {
155 dSum = icFloatNumber(n);
156 }
157
158 return dSum;
159}
160
161// fits a quadratic curve through x,y points and returns the vertex of the parabola
163{
164 icFloatNumber vert = 0.0;
165
166 if (n>2) { // need at least three points to solve three linear equations
167 icFloatNumber s00, s10, s20, s30, s40, s01, s11, s21, denom;
168 s00 = calcsum(x, y, n, 0, 0);
169 s10 = calcsum(x, y, n, 1, 0);
170 s20 = calcsum(x, y, n, 2, 0);
171 s30 = calcsum(x, y, n, 3, 0);
172 s40 = calcsum(x, y, n, 4, 0);
173 s01 = calcsum(x, y, n, 0, 1);
174 s11 = calcsum(x, y, n, 1, 1);
175 s21 = calcsum(x, y, n, 2, 1);
176 denom = (icFloatNumber)(s00*s20*s40 - s10*s10*s40 - s00*s30*s30 + 2.0*s10*s20*s30 - s20*s20*s20);
177 if (fabs(denom)>0.0) {
178 // t and u are the coefficients of the quadratic equation y = tx^2 + ux + c
179 // the three equations with 3 unknowns can be written as
180 // [s40 s30 s20][t] [s21]
181 // [s30 s20 s10][u] = [s11]
182 // [s20 s10 s00][c] [s01]
183 icFloatNumber t = (s01*s10*s30 - s11*s00*s30 - s01*s20*s20 + s11*s10*s20 + s21*s00*s20 - s21*s10*s10)/denom;
184
185 icFloatNumber u = (s11*s00*s40 - s01*s10*s40 + s01*s20*s30 - s21*s00*s30 - s11*s20*s20 + s21*s10*s20)/denom;
186
187 icFloatNumber c = (s01*s20*s40 - s11*s10*s40 - s01*s30*s30 + s11*s20*s30 + s21*s10*s30 - s21*s20*s20)/denom;
188
189 // vertex is (-u + sqrt(u^2 - 4tc))/2t
190 vert = (icFloatNumber)((-1.0 * u + sqrt(u*u - 4*t*c)) / (2.0 * t));
191 }
192 }
193
194 return vert;
195}
196
197/**
198**************************************************************************
199* Name: CIccApplyBPC::CalculateFactors
200*
201* Purpose:
202* This function does the suitable calculations to setup black point
203* compensation.
204*
205* Args:
206* pXform = pointer to the Xform object that calls this function
207*
208* Return:
209* true = all calculations done
210* false = an error occurred
211**************************************************************************
212*/
213bool CIccApplyBPC::CalcFactors(const CIccProfile* pProfile, const CIccXform* pXform, icFloatNumber* Scale, icFloatNumber* Offset) const
214{
215 if (!pProfile || !pXform)
216 return false;
217
218 if (pXform->GetIntent()==icAbsoluteColorimetric) { // black point compensation not supported
219 return false;
220 }
221
222 switch (pProfile->m_Header.deviceClass)
223 { // These profile classes not supported
224 case icSigLinkClass:
226 //case icSigColorSpaceClass:
228 return false;
229 default:
230 break;
231 }
232
233 icFloatNumber XYZbp[3]; // storage for black point XYZ
234
235 // calculate the black point
236 if (!calcBlackPoint(pProfile, pXform, XYZbp)) {
237 return false;
238 }
239
240 // calculate the scale and offset
241 if (pXform->IsInput()) { // use PRM black as destination black
242 Scale[0] = (icFloatNumber)((1.0 - icPerceptualRefBlackY)/(1.0 - XYZbp[1]));
243 }
244 else { // use PRM black as source black
245 Scale[0] = (icFloatNumber)((1.0 - XYZbp[1])/(1.0 - icPerceptualRefBlackY));
246 }
247
248 Scale[1] = Scale[0];
249 Scale[2] = Scale[0];
250
251 Offset[0] = (icFloatNumber)((1.0 - Scale[0]) * icPerceptualRefWhiteX);
252 Offset[1] = (icFloatNumber)((1.0 - Scale[1]) * icPerceptualRefWhiteY);
253 Offset[2] = (icFloatNumber)((1.0 - Scale[2]) * icPerceptualRefWhiteZ);
254
255 icXyzToPcs(Offset);
256
257 return true;
258}
259
260/**
261**************************************************************************
262* Name: CIccApplyBPC::calcBlackPoint
263*
264* Purpose:
265* Calculates the black point of a profile
266*
267**************************************************************************
268*/
269bool CIccApplyBPC::calcBlackPoint(const CIccProfile* pProfile, const CIccXform* pXform, icFloatNumber* XYZb) const
270{
271 if (pXform->IsInput()) { // profile used as input/source profile
272 return calcSrcBlackPoint(pProfile, pXform, XYZb);
273 }
274 else { // profile used as output profile
275 return calcDstBlackPoint(pProfile, pXform, XYZb);
276 }
277
278 return true;
279}
280
281/**
282**************************************************************************
283* Name: CIccApplyBPC::calcSrcBlackPoint
284*
285* Purpose:
286* Calculates the black point of a source profile
287*
288**************************************************************************
289*/
290bool CIccApplyBPC::calcSrcBlackPoint(const CIccProfile* pProfile, const CIccXform* pXform, icFloatNumber* XYZb) const
291{
292 icFloatNumber Pixel[16];
293 if ((pProfile->m_Header.colorSpace == icSigCmykData) && (pProfile->m_Header.deviceClass == icSigOutputClass)) {
294
295 // calculate intermediate CMYK
296 XYZb[0] = XYZb[1] = XYZb[2] = 0.0;
297
298 // convert the Lab of 0,0,0 to relevant PCS
299 lab2pcs(XYZb, pProfile);
300
301 //convert the PCS value to CMYK
302 if (!pixelXfm(Pixel, XYZb, pProfile->m_Header.pcs, icPerceptual, pProfile)) {
303 return false;
304 }
305 }
306 else {
307 switch (pProfile->m_Header.colorSpace) {
308 case icSigRgbData:
309 Pixel[0] = 0.0;
310 Pixel[1] = 0.0;
311 Pixel[2] = 0.0;
312 break;
313
314 case icSigGrayData:
315 Pixel[0] = 0.0;
316 break;
317
318 case icSigCmykData:
319 case icSigCmyData:
320 case icSig2colorData:
321 case icSig3colorData:
322 case icSig4colorData:
323 case icSig5colorData:
324 case icSig6colorData:
325 case icSig7colorData:
326 case icSig8colorData:
327 case icSig9colorData:
328 case icSig10colorData:
329 case icSig11colorData:
330 case icSig12colorData:
331 case icSig13colorData:
332 case icSig14colorData:
333 case icSig15colorData:
334 {
335 icUInt32Number nSamples = icGetSpaceSamples(pProfile->m_Header.colorSpace);
336 for (icUInt32Number i=0; i<nSamples; i++) {
337 Pixel[i] = 1.0;
338 }
339 }
340 break;
341
342 default:
343 return false;
344 }
345 }
346
347 // convert the device value to PCS
348 if (!pixelXfm(XYZb, Pixel, pProfile->m_Header.colorSpace, pXform->GetIntent(), pProfile)) {
349 return false;
350 }
351
352 // convert PCS to Lab
353 pcs2lab(XYZb, pProfile);
354
355 // set a* b* to zero for cmyk profiles
356 if (pProfile->m_Header.colorSpace == icSigCmykData) {
357 XYZb[1] = XYZb[2] = 0.0;
358 }
359
360 // clip L* to 50
361 if (XYZb[0]>50.0) {
362 XYZb[0] = 50.0;
363 }
364
365 // convert Lab to XYZ
366 icLabtoXYZ(XYZb);
367 return true;
368}
369
370/**
371**************************************************************************
372* Name: CIccApplyBPC::calcDstBlackPoint
373*
374* Purpose:
375* Calculates the black point of a destination profile
376*
377**************************************************************************
378*/
379bool CIccApplyBPC::calcDstBlackPoint(const CIccProfile* pProfile, const CIccXform* pXform, icFloatNumber* XYZb) const
380{
381 icRenderingIntent nIntent = pXform->GetIntent();
382 icFloatNumber Pixel[3];
383 icFloatNumber pcsPixel[3];
384
385 // check if the profile is lut based gray, rgb or cmyk
386 if (pProfile->IsTagPresent(icSigBToA0Tag) &&
387 (pProfile->m_Header.colorSpace==icSigGrayData || pProfile->m_Header.colorSpace==icSigRgbData || pProfile->m_Header.colorSpace==icSigCmykData))
388 { // do the complicated and lengthy black point estimation
389
390 // get the black transform
391 CIccCmm* pCmm = getBlackXfm(nIntent, pProfile);
392 if (!pCmm) {
393 return false;
394 }
395
396 // set the initial Lab
397 icFloatNumber iniLab[3] = {0.0, 0.0, 0.0};
398
399 // calculate minL
400 pcsPixel[0] = 0.0;
401 pcsPixel[1] = iniLab[1];
402 pcsPixel[2] = iniLab[2];
403 lab2pcs(pcsPixel, pProfile);
404 if (pCmm->Apply(Pixel, pcsPixel)!=icCmmStatOk) {
405 delete pCmm;
406 return false;
407 }
408 pcs2lab(Pixel, pProfile);
409 icFloatNumber MinL = Pixel[0];
410
411 // calculate MaxL
412 pcsPixel[0] = 100.0;
413 pcsPixel[1] = iniLab[1];
414 pcsPixel[2] = iniLab[2];
415 lab2pcs(pcsPixel, pProfile);
416 if (pCmm->Apply(Pixel, pcsPixel)!=icCmmStatOk) {
417 delete pCmm;
418 return false;
419 }
420 pcs2lab(Pixel, pProfile);
421 icFloatNumber MaxL = Pixel[0];
422
423 // check if quadratic estimation needs to be done
424 bool bStraightMidRange = false;
425
426 // if the intent is relative
427 if (nIntent==icRelativeColorimetric)
428 {
429 // calculate initial Lab as source black point
430 if (!calcSrcBlackPoint(pProfile, pXform, iniLab)) {
431 delete pCmm;
432 return false;
433 }
434
435 // convert the XYZ to lab
436 icXYZtoLab(iniLab);
437
438 // check mid range L* values
439 icFloatNumber lcnt=0.0, roundtripL;
440 bStraightMidRange = true;
441 while (lcnt<100.1)
442 {
443 pcsPixel[0] = icFloatNumber(lcnt);
444 pcsPixel[1] = iniLab[1];
445 pcsPixel[2] = iniLab[2];
446 lab2pcs(pcsPixel, pProfile);
447 if (pCmm->Apply(Pixel, pcsPixel)!=icCmmStatOk) {
448 delete pCmm;
449 return false;
450 }
451 pcs2lab(Pixel, pProfile);
452 roundtripL = Pixel[0];
453
454 if (roundtripL>(MinL + 0.2 * (MaxL - MinL))) {
455 if (fabs(roundtripL - lcnt)>4.0) {
456 bStraightMidRange = false;
457 break;
458 }
459 }
460
461 lcnt += 1.0;
462 }
463 }
464
465 // quadratic estimation is not needed
466 if (bStraightMidRange) { // initial Lab is the destination black point
467 XYZb[0] = iniLab[0];
468 XYZb[1] = iniLab[1];
469 XYZb[2] = iniLab[2];
470 icLabtoXYZ(XYZb);
471 delete pCmm;
472 return true;
473 }
474
475 // find the black point using the least squares error quadratic curve fitting
476
477 // calculate y values
478 icFloatNumber x[101], y[101];
479 icFloatNumber lo=0.03f, hi=0.25f;
480 int i, n;
481 if (nIntent==icRelativeColorimetric) {
482 lo = 0.1f;
483 hi = 0.5f;
484 }
485
486 for (i=0; i<101; i++) {
487 x[i] = icFloatNumber(i);
488 pcsPixel[0] = x[i];
489 pcsPixel[1] = iniLab[1];
490 pcsPixel[2] = iniLab[2];
491 lab2pcs(pcsPixel, pProfile);
492 if (pCmm->Apply(Pixel, pcsPixel)!=icCmmStatOk) {
493 delete pCmm;
494 return false;
495 }
496 pcs2lab(Pixel, pProfile);
497 y[i] = (Pixel[0] - MinL)/(MaxL - MinL);
498 }
499
500 // check for y values in the range and rearrange
501 n = 0;
502 for (i=0; i<101; i++) {
503 if (y[i]>=lo && y[i]<hi) {
504 x[n] = x[i];
505 y[n] = y[i];
506 n++;
507 }
508 }
509
510 if (!n) {
511 delete pCmm;
512 return false;
513 }
514
515 // fit and get the vertex of quadratic curve
516 XYZb[0] = calcQuadraticVertex(x, y, n);
517 if (XYZb[0]<0.0) { // clip to zero L* if the vertex is negative
518 XYZb[0] = 0.0;
519 }
520 XYZb[1] = iniLab[1];
521 XYZb[2] = iniLab[2];
522 icLabtoXYZ(XYZb);
523
524 delete pCmm;
525 }
526 else { // use the procedure for source black point
527 return calcSrcBlackPoint(pProfile, pXform, XYZb);
528 }
529
530 return true;
531}
532
533/**
534**************************************************************************
535* Name: CIccApplyBPC::pixelXfm
536*
537* Purpose:
538* Applies the specified transform to the source pixel
539*
540**************************************************************************
541*/
543 icRenderingIntent nIntent, const CIccProfile *pProfile) const
544{
545 // create the cmm object
546 CIccCmm cmm(SrcSpace, icSigUnknownData, !IsSpacePCS(SrcSpace));
547
548 // first create a copy of the profile because the copy will be owned by the cmm
549 CIccProfile* pICC = new CIccProfile(*pProfile);
550 if (!pICC) return false;
551
552 // add the xform
553 if (cmm.AddXform(pICC, nIntent, icInterpTetrahedral, NULL, icXformLutColorimetric, pICC->m_Header.version >= icVersionNumberV5 ? false : true)!=icCmmStatOk) {
554 delete pICC;
555 return false;
556 }
557
558 // get the cmm ready to do transforms
559 if (cmm.Begin()!=icCmmStatOk) {
560 return false;
561 }
562
563 // Apply the pixel
564 if (cmm.Apply(DstPixel, SrcPixel)!=icCmmStatOk) {
565 return false;
566 }
567
568 return true;
569}
570
571/**
572**************************************************************************
573* Name: CIccApplyBPC::blackXfm
574*
575* Purpose:
576* PCS -> PCS round trip transform, always uses relative intent on the device -> pcs transform
577*
578**************************************************************************
579*/
580CIccCmm* CIccApplyBPC::getBlackXfm(icRenderingIntent nIntent, const CIccProfile *pProfile) const
581{
582 // create the cmm object
583 CIccCmm* pCmm = new CIccCmm(pProfile->m_Header.pcs, icSigUnknownData, false);
584 if (!pCmm) return NULL;
585
586 // first create a copy of the profile because the copy will be owned by the cmm
587 CIccProfile* pICC1 = new CIccProfile(*pProfile);
588 if (!pICC1) {
589 delete pCmm;
590 return NULL;
591 }
592
593 // add the xform
594 if (pCmm->AddXform(pICC1, nIntent, icInterpTetrahedral, NULL, icXformLutColor, pICC1->m_Header.version >= icVersionNumberV5 ? false : true)!=icCmmStatOk) {
595 delete pICC1;
596 delete pCmm;
597 return NULL;
598 }
599
600 // create another copy of the profile because the copy will be owned by the cmm
601 CIccProfile* pICC2 = new CIccProfile(*pProfile);
602 if (!pICC2) {
603 delete pCmm;
604 return NULL;
605 }
606
607 // add the xform
608 if (pCmm->AddXform(pICC2, icRelativeColorimetric, icInterpTetrahedral, NULL, icXformLutColor, pICC2->m_Header.version >= icVersionNumberV5 ? false : true)!=icCmmStatOk) { // uses the relative intent on the device to Lab side
609 delete pICC2;
610 delete pCmm;
611 return NULL;
612 }
613
614 // get the cmm ready to do transforms
615 if (pCmm->Begin()!=icCmmStatOk) {
616 delete pCmm;
617 return NULL;
618 }
619
620 return pCmm;
621}
#define IsSpacePCS(x)
File: IccApplyBPC.h.
@ icXformLutColorimetric
Definition IccCmm.h:135
@ icXformLutColor
Definition IccCmm.h:126
#define icPerceptualRefWhiteX
Definition IccCmm.h:143
@ icInterpTetrahedral
Definition IccCmm.h:115
#define icPerceptualRefBlackY
Definition IccCmm.h:140
#define icPerceptualRefWhiteZ
Definition IccCmm.h:145
@ icCmmStatOk
Definition IccCmm.h:92
#define icPerceptualRefWhiteY
Definition IccCmm.h:144
float icFloatNumber
All floating point operations/variables in IccProfLib use the icFloatNumber data type.
Definition IccDefs.h:100
void icXyzToPcs(icFloatNumber *XYZ)
Definition IccUtil.cpp:941
void icXyzFromPcs(icFloatNumber *XYZ)
Floating point encoding of XYZ in PCS is in range 0.0 to 1.0 (Note: X=1.0 is encoded as about 0....
Definition IccUtil.cpp:934
icUInt32Number icGetSpaceSamples(icColorSpaceSignature sig)
Definition IccUtil.cpp:1303
void icLabFromPcs(icFloatNumber *Lab)
Floating point encoding of Lab in PCS is in range 0.0 to 1.0.
Definition IccUtil.cpp:919
void icLabToPcs(icFloatNumber *Lab)
Definition IccUtil.cpp:927
void icLabtoXYZ(icFloatNumber *XYZ, const icFloatNumber *Lab, const icFloatNumber *WhiteXYZ)
Definition IccUtil.cpp:830
void icXYZtoLab(icFloatNumber *Lab, const icFloatNumber *XYZ, const icFloatNumber *WhiteXYZ)
Definition IccUtil.cpp:846
unsigned int icUInt32Number
virtual IIccAdjustPCSXform * GetNewAdjustPCSXform() const
Name: CIccApplyBPCHint::GetNewAdjustPCSXform.
Type: Class.
bool calcSrcBlackPoint(const CIccProfile *pProfile, const CIccXform *pXform, icFloatNumber *XYZb) const
Name: CIccApplyBPC::calcSrcBlackPoint.
bool calcDstBlackPoint(const CIccProfile *pProfile, const CIccXform *pXform, icFloatNumber *XYZb) const
Name: CIccApplyBPC::calcDstBlackPoint.
bool pixelXfm(icFloatNumber *DstPixel, icFloatNumber *SrcPixel, icColorSpaceSignature SrcSpace, icRenderingIntent nIntent, const CIccProfile *pProfile) const
Name: CIccApplyBPC::pixelXfm.
void pcs2lab(icFloatNumber *pixel, const CIccProfile *pProfile) const
CIccCmm * getBlackXfm(icRenderingIntent nIntent, const CIccProfile *pProfile) const
Name: CIccApplyBPC::blackXfm.
bool calcBlackPoint(const CIccProfile *pProfile, const CIccXform *pXform, icFloatNumber *XYZb) const
Name: CIccApplyBPC::calcBlackPoint.
virtual bool CalcFactors(const CIccProfile *pProfile, const CIccXform *pXfm, icFloatNumber *Scale, icFloatNumber *Offset) const
Name: CIccApplyBPC::CalculateFactors.
icFloatNumber calcsum(icFloatNumber *x, icFloatNumber *y, int n, int j, int k) const
void lab2pcs(icFloatNumber *pixel, const CIccProfile *pProfile) const
icFloatNumber calcQuadraticVertex(icFloatNumber *x, icFloatNumber *y, int n) const
@ icSigAbstractClass
@ icSigOutputClass
@ icSigNamedColorClass
@ icSigLinkClass
icColorSpaceSignature
Color Space Signatures.
@ icSig14colorData
@ icSigLabData
@ icSig2colorData
@ icSig8colorData
@ icSig10colorData
@ icSig7colorData
@ icSig9colorData
@ icSigXYZData
@ icSig13colorData
@ icSig6colorData
@ icSigCmykData
@ icSigRgbData
@ icSig4colorData
@ icSig12colorData
@ icSig11colorData
@ icSigCmyData
@ icSigGrayData
@ icSig15colorData
@ icSig3colorData
@ icSig5colorData
#define icSigUnknownData
#define icVersionNumberV5
@ icSigBToA0Tag
icRenderingIntent
Rendering Intents, used in the profile header.
@ icPerceptual
@ icRelativeColorimetric
@ icAbsoluteColorimetric