Hoyt's FORK of DemoIccMAX 2.1.17.hoyt
Documentation for Hoyt's FORK of DemoIccMAX
Loading...
Searching...
No Matches
IccTagLut.cpp
Go to the documentation of this file.
1/** @file
2 File: IccTagLut.cpp
3
4 Contains: Implementation of the Lut Tag classes
5
6 Version: V1
7
8 Copyright: � 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 Max Derhak 5-15-2003
68//
69// -Moved LUT tags to separate file 4-30-2005
70//
71//////////////////////////////////////////////////////////////////////
72
73#ifdef WIN32
74 #pragma warning( disable: 4786) //disable warning in <list.h>
75 #include <windows.h>
76#endif
77#include <stdio.h>
78#include <math.h>
79#include <string.h>
80#include <stdlib.h>
81#include "IccTag.h"
82#include "IccUtil.h"
83#include "IccProfile.h"
84#include "IccMpeBasic.h"
85
86#ifdef USEREFICCMAXNAMESPACE
87namespace refIccMAX {
88#endif
89
90/**
91****************************************************************************
92* Name: CIccCurve::Find
93*
94* Purpose: Read in the tag contents into a data block
95*
96* Args:
97* v = index to be searched,
98* v0 = index less than/equal to v,
99* p0 = the value at index v0,
100* v1 = index greater than/equal to v,
101* p1 = value at index v1
102*
103* Return: The value at the requested index
104*
105*****************************************************************************
106*/
110{
111 if (v<=v0)
112 return p0;
113 if (v>=v1)
114 return p1;
115
116 if (p1-p0 <= 0.00001) {
117 icFloatNumber d0 = (icFloatNumber)fabs(v-v0);
118 icFloatNumber d1 = (icFloatNumber)fabs(v1-v);
119
120 if (d0<d1)
121 return p0;
122 return p1;
123 }
124
125 icFloatNumber np = (icFloatNumber)((p0 + p1)/2.0);
126 icFloatNumber nv = Apply(np);
127
128 if (v<=nv) {
129 return Find(v, p0, v0, np, nv);
130 }
131 return Find(v, np, nv, p1, v1);
132}
133
134
135/**
136****************************************************************************
137* Name: CIccTagCurve::CIccTagCurve
138*
139* Purpose: Constructor
140*
141*****************************************************************************
142*/
144{
145 m_nSize = nSize <0 ? 0 : nSize;
146 if (m_nSize>0)
147 m_Curve = (icFloatNumber*)calloc(nSize, sizeof(icFloatNumber));
148 else
149 m_Curve = NULL;
150}
151
152
153/**
154****************************************************************************
155* Name: CIccTagCurve::CIccTagCurve
156*
157* Purpose: Copy Constructor
158*
159* Args:
160* ITCurve = The CIccTagCurve object to be copied
161*****************************************************************************
162*/
164{
165 m_nSize = ITCurve.m_nSize;
166 m_nMaxIndex = ITCurve.m_nMaxIndex;
167
168 m_Curve = (icFloatNumber*)calloc(m_nSize, sizeof(icFloatNumber));
169 memcpy(m_Curve, ITCurve.m_Curve, m_nSize*sizeof(icFloatNumber));
170}
171
172
173/**
174****************************************************************************
175* Name: CIccTagCurve::operator=
176*
177* Purpose: Copy Operator
178*
179* Args:
180* CurveTag = The CIccTagCurve object to be copied
181*****************************************************************************
182*/
184{
185 if (&CurveTag == this)
186 return *this;
187
188 m_nSize = CurveTag.m_nSize;
189 m_nMaxIndex = CurveTag.m_nMaxIndex;
190
191 if (m_Curve)
192 free(m_Curve);
193 m_Curve = (icFloatNumber*)calloc(m_nSize, sizeof(icFloatNumber));
194 memcpy(m_Curve, CurveTag.m_Curve, m_nSize*sizeof(icFloatNumber));
195
196 return *this;
197}
198
199
200/**
201****************************************************************************
202* Name: CIccTagCurve::~CIccTagCurve
203*
204* Purpose: Destructor
205*
206*****************************************************************************
207*/
209{
210 if (m_Curve)
211 free(m_Curve);
212}
213
214
215/**
216****************************************************************************
217* Name: CIccTagCurve::Read
218*
219* Purpose: Read in the tag contents into a data block
220*
221* Args:
222* size - # of bytes in tag,
223* pIO - IO object to read tag from
224*
225* Return:
226* true = successful, false = failure
227*****************************************************************************
228*/
230{
232
233 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
234 sizeof(icUInt32Number) +
235 sizeof(icUInt32Number);
236 if (headerSize > size)
237 return false;
238
239 if (!pIO) {
240 return false;
241 }
242
243 if (!pIO->Read32(&sig))
244 return false;
245
246 if (!pIO->Read32(&m_nReserved))
247 return false;
248
249 icUInt32Number nSize;
250
251 if (!pIO->Read32(&nSize))
252 return false;
253
254 if (headerSize + (icUInt64Number)nSize * sizeof(icUInt16Number) > size)
255 return false;
256
257 if (!SetSize(nSize, icInitNone))
258 return false;
259
260 if (m_nSize) {
261 if (pIO->ReadUInt16Float(m_Curve, m_nSize)!=(icInt32Number)m_nSize)
262 return false;
263 }
264
265 return true;
266}
267
268
269/**
270****************************************************************************
271* Name: CIccTagCurve::Write
272*
273* Purpose: Write the tag to a file
274*
275* Args:
276* pIO - The IO object to write tag to.
277*
278* Return:
279* true = succesful, false = failure
280*****************************************************************************
281*/
283{
284 icTagTypeSignature sig = GetType();
285
286 if (!pIO)
287 return false;
288
289 if (!pIO->Write32(&sig))
290 return false;
291
292 if (!pIO->Write32(&m_nReserved))
293 return false;
294
295 if (!pIO->Write32(&m_nSize))
296 return false;
297
298 if (m_nSize)
299 if (pIO->WriteUInt16Float(m_Curve, m_nSize)!=(icInt32Number)m_nSize)
300 return false;
301
302 pIO->Align32();
303
304 return true;
305}
306
307
308/**
309****************************************************************************
310* Name: CIccTagCurve::Describe
311*
312* Purpose: Dump data associated with the tag to a string
313*
314* Args:
315* sDescription - string to concatenate tag dump to
316*****************************************************************************
317*/
318void CIccTagCurve::Describe(std::string &sDescription, int nVerboseness)
319{
320 icChar buf[128], *ptr;
321
322 if (!m_nSize) {
323 sprintf(buf, "BEGIN_CURVE In_Out\n");
324 sDescription += buf;
325 sDescription += "Y = X\n";
326 }
327 else if (m_nSize==1) {
328 icFloatNumber dGamma = (icFloatNumber)(m_Curve[0] * 256.0);
329 sprintf(buf, "BEGIN_CURVE In_Out\n");
330 sDescription += buf;
331 sprintf(buf, "Y = X ^ %.4lf\n", dGamma);
332 sDescription += buf;
333 }
334 else {
335 int i;
336
337 sprintf(buf, "BEGIN_LUT In_Out 1 1\n");
338 sDescription += buf;
339
340 if (nVerboseness > 75) {
341 sDescription += "IN OUT\n";
342
343 for (i=0; i<(int)m_nSize; i++) {
344 ptr = buf;
345
346 icColorValue(buf, (icFloatNumber)i/(m_nSize-1), icSigMCH1Data, 1);
347 ptr += strlen(buf);
348
349 strcpy(ptr, " ");
350 ptr ++;
351
352 icColorValue(ptr, m_Curve[i], icSigMCH1Data, 1);
353
354 ptr += strlen(ptr);
355
356 strcpy(ptr, "\n");
357 sDescription += buf;
358 }
359 }
360 }
361}
362
363
364/**
365****************************************************************************
366* Name: CIccTagCurve::DumpLut
367*
368* Purpose: Dump data associated with the tag to a string. Basically has
369* the same function as Describe()
370*
371* Args:
372* sDescription = string to concatenate tag dump to,
373* szName = name of the curve to be printed,
374* csSig = color space signature of the LUT data,
375* nIndex = the channel number of color space
376*****************************************************************************
377*/
378void CIccTagCurve::DumpLut(std::string &sDescription, const icChar *szName,
379 icColorSpaceSignature csSig, int nIndex, int nVerboseness)
380{
381 icChar buf[128], *ptr;
382
383 if (!m_nSize) {
384 sprintf(buf, "BEGIN_CURVE %s\n", szName);
385 sDescription += buf;
386 sDescription += "Y = X\n";
387 }
388 else if (m_nSize==1) {
389 icFloatNumber dGamma = (icFloatNumber)(m_Curve[0] * 256.0);
390 sprintf(buf, "BEGIN_CURVE %s\n", szName);
391 sDescription += buf;
392 sprintf(buf, "Y = X ^ %.4lf\n", dGamma);
393 sDescription += buf;
394 }
395 else {
396 int i;
397
398 sprintf(buf, "BEGIN_LUT %s 1 1\n", szName);
399
400 if (nVerboseness > 75) {
401 sDescription += buf;
402 sDescription += "IN OUT\n";
403
404 sDescription.reserve(sDescription.size() + m_nSize * 20);
405
406 for (i=0; i<(int)m_nSize; i++) {
407 ptr = buf;
408
409 icColorValue(buf, (icFloatNumber)i/(m_nSize-1), csSig, nIndex);
410 ptr += strlen(buf);
411
412 strcpy(ptr, " ");
413 ptr ++;
414
415 icColorValue(ptr, m_Curve[i], csSig, nIndex);
416
417 ptr += strlen(ptr);
418
419 strcpy(ptr, "\n");
420
421 sDescription += buf;
422 }
423 }
424 }
425}
426
427
428/**
429****************************************************************************
430* Name: CIccTagCurve::SetSize
431*
432* Purpose: Sets the size of the curve array.
433*
434* Args:
435* nSize - number of entries in the curve,
436* nSizeOpt - flag to zero newly formed values
437*****************************************************************************
438*/
439bool CIccTagCurve::SetSize(icUInt32Number nSize, icTagCurveSizeInit nSizeOpt/*=icInitZero*/)
440{
441 if (nSize==m_nSize)
442 return true;
443
444 if (!nSize && m_Curve) {
445 free(m_Curve);
446 m_Curve = NULL;
447 }
448 else {
449 if (!m_Curve)
450 m_Curve = (icFloatNumber*)malloc(nSize*sizeof(icFloatNumber));
451 else
452 m_Curve = (icFloatNumber*)icRealloc(m_Curve, nSize*sizeof(icFloatNumber));
453
454 if (!m_Curve) {
455 m_nSize = 0;
456 return false;
457 }
458
459 switch (nSizeOpt) {
460 case icInitNone:
461 default:
462 break;
463
464 case icInitZero:
465 if (m_nSize < nSize) {
466 memset(&m_Curve[m_nSize], 0, (nSize-m_nSize)*sizeof(icFloatNumber));
467 }
468 break;
469
470 case icInitIdentity:
471 if (nSize>1) {
473 icFloatNumber last = (icFloatNumber)(nSize-1);
474
475 for (i=0; i<nSize; i++) {
476 m_Curve[i] = (icFloatNumber)i/last;
477 }
478 }
479 else if (nSize==1) {
480 //Encode a gamma 1.0 u8Fixed8Number converted to 16 bit as a 0.0 to 1.0 float
481 m_Curve[0] = (icFloatNumber)(0x0100) / (icFloatNumber)65535.0;
482 }
483 break;
484 }
485 }
486 m_nSize = nSize;
487 m_nMaxIndex = (icUInt16Number)(nSize - 1);
488
489 return true;
490}
491
492/**
493****************************************************************************
494* Name: refIccMAX::CIccTagCurve::SetGamma
495*
496* Purpose: Set the curve with a single gamma value.
497*
498* Args:
499* gamma - gamma value to use
500*****************************************************************************
501*/
503{
504 if (!SetSize(1, icInitNone))
505 return false;
506
507 icInt16Number whole = (icInt16Number)gamma;
508 icFloatNumber frac = gamma - (icFloatNumber)whole;
509
510 m_Curve[0] = (icFloatNumber)((whole * 256) + (frac*256.0)) / (icFloatNumber)65535.0;
511 return true;
512}
513
514/**
515****************************************************************************
516*
517*****************************************************************************
518*/
520static bool IsUnity(const icFloatNumber& num)
521{
522 return (num>(1.0-VERYSMALLNUM) && num<(1.0+VERYSMALLNUM));
523}
524
525/**
526****************************************************************************
527* Name: CIccTagCurve::IsIdentity
528*
529* Purpose: Checks if this is an identity curve.
530*
531* Return: true if the curve is an identity
532*
533*****************************************************************************
534*/
536{
537 if (!m_nSize) {
538 return true;
539 }
540
541 if (m_nSize==1) {
542 return IsUnity(icFloatNumber(m_Curve[0]*65535.0/256.0));
543 }
544
546 for (i=0; i<m_nSize; i++) {
547 if (fabs(m_Curve[i]-((icFloatNumber)i/(icFloatNumber)m_nMaxIndex))>VERYSMALLNUM) {
548 return false;
549 }
550 }
551
552 return true;
553}
554
555/**
556****************************************************************************
557* Name: CIccTagCurve::Apply
558*
559* Purpose: Applies the curve to the value passed.
560*
561* Args:
562* v = value to be passed through the curve.
563*
564* Return: The value modified by the curve.
565*
566*****************************************************************************
567*/
569{
570 if(v<0.0) v = 0.0;
571 else if(v>1.0) v = 1.0;
572
573 icUInt32Number nIndex = (icUInt32Number)(v * m_nMaxIndex);
574
575 if (!m_nSize) {
576 return v;
577 }
578 if (m_nSize==1) {
579 //Convert 0.0 to 1.0 float to 16bit and then convert from u8Fixed8Number
580 icFloatNumber dGamma = (icFloatNumber)(m_Curve[0] * 65535.0 / 256.0);
581 return (icFloatNumber)pow(v, dGamma);
582 }
583 if (nIndex == m_nMaxIndex) {
584 return m_Curve[nIndex];
585 }
586 else {
587 icFloatNumber nDif = v*m_nMaxIndex - nIndex;
588 icFloatNumber p0 = m_Curve[nIndex];
589
590 icFloatNumber rv = p0 + (m_Curve[nIndex+1]-p0)*nDif;
591 if (rv>1.0)
592 rv=1.0;
593
594 return rv;
595 }
596}
597
598
599/**
600******************************************************************************
601* Name: CIccTagCurve::Validate
602*
603* Purpose: Check tag data validity.
604*
605* Args:
606* sig = signature of tag being validated,
607* sReport = String to add report information to
608*
609* Return:
610* icValidateStatusOK if valid, or other error status.
611******************************************************************************
612*/
613icValidateStatus CIccTagCurve::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
614{
615 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
616
617 CIccInfo Info;
618 std::string sSigPathName = Info.GetSigPathName(sigPath);
620
622 if (m_nSize>1) {
623 if (m_Curve) {
624 if (m_Curve[0]>0.0 || m_Curve[m_nSize-1]<1.0) {
625 sReport += icMsgValidateWarning;
626 sReport += sSigPathName;
627 sReport += " - Curve cannot be accurately inverted.\n";
629 }
630 }
631 }
632 }
633
634 return rv;
635}
636
637
638/**
639****************************************************************************
640* Name: CIccTagParametricCurve::CIccTagParametricCurve
641*
642* Purpose: Constructor
643*
644*****************************************************************************
645*/
647{
648 m_nFunctionType = 0xffff;
649 m_nNumParam = 0;
650 m_dParam = NULL;
651 m_nReserved2 = 0;
652}
653
654
655/**
656****************************************************************************
657* Name: CIccTagParametricCurve::CIccTagParametricCurve
658*
659* Purpose: Copy Constructor
660*
661* Args:
662* ITPC = The CIccTagParametricCurve object to be copied
663*****************************************************************************
664*/
666{
667 m_nFunctionType = ITPC.m_nFunctionType;
668 m_nNumParam = ITPC.m_nNumParam;
669 m_nReserved2 = 0;
670
671 m_dParam = new icFloatNumber[m_nNumParam];
672 memcpy(m_dParam, ITPC.m_dParam, m_nNumParam*sizeof(icFloatNumber));
673}
674
675
676/**
677****************************************************************************
678* Name: CIccTagParametricCurve::operator=
679*
680* Purpose: Copy Operator
681*
682* Args:
683* ParamCurveTag = The CIccTagParametricCurve object to be copied
684*****************************************************************************
685*/
687{
688 if (&ParamCurveTag == this)
689 return *this;
690
691 m_nFunctionType = ParamCurveTag.m_nFunctionType;
692 m_nNumParam = ParamCurveTag.m_nNumParam;
693
694 if (m_dParam)
695 delete [] m_dParam;
696 m_dParam = new icFloatNumber[m_nNumParam];
697 memcpy(m_dParam, ParamCurveTag.m_dParam, m_nNumParam*sizeof(icFloatNumber));
698
699 return *this;
700}
701
702
703/**
704****************************************************************************
705* Name: CIccTagParametricCurve::~CIccTagParametricCurve
706*
707* Purpose: Destructor
708*
709*****************************************************************************
710*/
712{
713 if (m_dParam)
714 delete [] m_dParam;
715}
716
717
718/**
719****************************************************************************
720* Name: CIccTagParametricCurve::Read
721*
722* Purpose: Read in the tag contents into a data block
723*
724* Args:
725* size - # of bytes in tag,
726* pIO - IO object to read tag from
727*
728* Return:
729* true = successful, false = failure
730*****************************************************************************
731*/
733{
735 icUInt16Number nFunctionType;
736
737 icUInt32Number nHdrSize = sizeof(icTagTypeSignature) +
738 sizeof(icUInt32Number) +
739 2*sizeof(icUInt16Number);
740
741 if ( nHdrSize > size)
742 return false;
743
744 if (!pIO) {
745 return false;
746 }
747
748 if (!pIO->Read32(&sig) ||
749 !pIO->Read32(&m_nReserved) ||
750 !pIO->Read16(&nFunctionType) ||
751 !pIO->Read16(&m_nReserved2))
752 return false;
753
754 SetFunctionType(nFunctionType);
755
756 if (!m_nNumParam) {
757 m_nNumParam = (icUInt16Number)((size-nHdrSize) / sizeof(icS15Fixed16Number));
758 m_dParam = new icFloatNumber[m_nNumParam];
759 }
760
761 if (m_nNumParam) {
762 int i;
763 if (nHdrSize + m_nNumParam*sizeof(icS15Fixed16Number) > size)
764 return false;
765
766 for (i=0; i<m_nNumParam; i++) {
768 if (!pIO->Read32(&num, 1))
769 return false;
770 m_dParam[i]=icFtoD(num);
771 }
772 }
773
774 return true;
775}
776
777
778/**
779****************************************************************************
780* Name: CIccTagParametricCurve::Write
781*
782* Purpose: Write the tag to a file
783*
784* Args:
785* pIO - The IO object to write tag to.
786*
787* Return:
788* true = succesful, false = failure
789*****************************************************************************
790*/
792{
794
795 if (!pIO) {
796 return false;
797 }
798
799 sig = GetType();
800
801 if (!pIO->Write32(&sig) ||
802 !pIO->Write32(&m_nReserved) ||
803 !pIO->Write16(&m_nFunctionType) ||
804 !pIO->Write16(&m_nReserved2))
805 return false;
806
807 if (m_nNumParam) {
808 int i;
809 for (i=0; i<m_nNumParam; i++) {
810 icS15Fixed16Number num = icDtoF(m_dParam[i]);
811 if (!pIO->Write32(&num, 1))
812 return false;
813 }
814 }
815
816 if (!pIO->Align32())
817 return false;
818
819 return true;
820}
821
822
823/**
824****************************************************************************
825* Name: CIccTagParametricCurve::Describe
826*
827* Purpose: Dump data associated with the tag to a string
828*
829* Args:
830* sDescription - string to concatenate tag dump to
831*****************************************************************************
832*/
833void CIccTagParametricCurve::Describe(std::string &sDescription, int nVerboseness)
834{
835 icChar buf[128];
836
837 sprintf(buf, "FunctionType: %04Xh\n", m_nFunctionType);
838 sDescription += buf;
839
840 switch(m_nFunctionType) {
841case 0x0000:
842 sprintf(buf, "Y = X ^ %.4lf\n", m_dParam[0]);
843 sDescription += buf;
844 return;
845
846case 0x0001:
847 sprintf(buf, "Y = 0 when (X < %.4lf / %.4lf)\n",
848 -m_dParam[2], m_dParam[1]);
849 sDescription += buf;
850
851 sprintf(buf, "Y = (%.4lf * X + %.4lf) ^ %.4lf when (X >= %.4lf / %.4lf)\n",
852 m_dParam[1], m_dParam[2], m_dParam[0],
853 m_dParam[2], m_dParam[1]);
854 sDescription += buf;
855 return;
856
857case 0x0002:
858 sprintf(buf, "Y = %.4lf when (X < %.4lf / %.4lf)\n", m_dParam[3],
859 -m_dParam[2], m_dParam[1]);
860 sDescription += buf;
861
862 sprintf(buf, "Y = (%.4lf * X + %.4lf) ^ %.4lf + %.4lf when (X >= %.4lf / %.4lf)\n",
863 m_dParam[1], m_dParam[2], m_dParam[0],
864 m_dParam[3],
865 -m_dParam[2], m_dParam[1]);
866 sDescription += buf;
867 return;
868
869case 0x0003:
870 sprintf(buf, "Y = %lf * X when (X < %.4lf)\n",
871 m_dParam[3], m_dParam[4]);
872 sDescription += buf;
873
874 sprintf(buf, "Y = (%.4lf * X + %.4lf) ^ %.4lf when (X >= %.4lf)\n",
875 m_dParam[1], m_dParam[2], m_dParam[0],
876 m_dParam[4]);
877 sDescription += buf;
878 return;
879
880case 0x0004:
881 sprintf(buf, "Y = %lf * X + %.4lf when (X < %.4lf)\n",
882 m_dParam[3], m_dParam[6], m_dParam[4]);
883 sDescription += buf;
884
885 sprintf(buf, "Y = (%.4lf * X + %.4lf) ^ %.4lf + %.4lf when (X >= %.4lf)\n",
886 m_dParam[1], m_dParam[2], m_dParam[0],
887 m_dParam[5], m_dParam[4]);
888 sDescription += buf;
889 return;
890
891default:
892 int i;
893 sprintf(buf, "Unknown Function with %d parameters:\n", m_nNumParam);
894 sDescription += buf;
895
896 for (i=0; i<m_nNumParam; i++) {
897 sprintf(buf, "Param[%d] = %.4lf\n", i, m_dParam[i]);
898 sDescription += buf;
899 }
900 }
901}
902
903/**
904****************************************************************************
905* Name: CIccTagParametricCurve::DumpLut
906*
907* Purpose: Dump data associated with the tag to a string. Basically has
908* the same function as Describe()
909*
910* Args:
911* sDescription = string to concatenate tag dump to,
912* szName = name of the curve to be printed,
913* csSig = color space signature of the curve data,
914* nIndex = the channel number of color space
915*****************************************************************************
916*/
917void CIccTagParametricCurve::DumpLut(std::string &sDescription, const icChar *szName,
918 icColorSpaceSignature csSig, int nIndex, int nVerboseness)
919{
920 icChar buf[128];
921
922 sprintf(buf, "BEGIN_CURVE %s\n", szName);
923 sDescription += buf;
924 Describe(sDescription, nVerboseness);
925}
926
927
928/**
929****************************************************************************
930* Name: CIccTagParametricCurve::SetFunctionType
931*
932* Purpose: Sets the type of the function the Parametric curve represents
933*
934* Args:
935* nFunctionType = the type of the function encoded as 0-4
936*
937* Return:
938* always true!!
939*****************************************************************************
940*/
942{
943 icUInt16Number nNumParam;
944
945 switch(nFunctionType) {
946 case 0x0000:
947 nNumParam = 1;
948 break;
949
950 case 0x0001:
951 nNumParam = 3;
952 break;
953
954 case 0x0002:
955 nNumParam = 4;
956 break;
957
958 case 0x0003:
959 nNumParam = 5;
960 break;
961
962 case 0x0004:
963 nNumParam = 7;
964 break;
965
966 default:
967 nNumParam = 0;
968 }
969
970 if (m_dParam)
971 delete m_dParam;
972 m_nNumParam = nNumParam;
973 m_nFunctionType = nFunctionType;
974
975 if (m_nNumParam)
976 m_dParam = new icFloatNumber[m_nNumParam];
977 else
978 m_dParam = NULL;
979
980 return true;
981}
982
983
984/**
985****************************************************************************
986* Name: CIccTagParametricCurve::IsIdentity
987*
988* Purpose: Checks if this is an identity curve.
989*
990* Return: true if the curve is an identity
991*
992*****************************************************************************
993*/
995{
996 switch(m_nFunctionType) {
997 case 0x0000:
998 return IsUnity(m_dParam[0]);
999
1000 case 0x0001:
1001 case 0x0002:
1002 case 0x0003:
1003 case 0x0004:
1004 return false;
1005
1006 default:
1007 return true;
1008 }
1009}
1010
1011/**
1012****************************************************************************
1013* Name: CIccTagParametricCurve::Apply
1014*
1015* Purpose: Applies the curve to the value passed.
1016*
1017* Args:
1018* x = value to be passed through the curve.
1019*
1020* Return: The value modified by the curve.
1021*
1022*****************************************************************************
1023*/
1025{
1026 double a, b;
1027
1028 switch(m_nFunctionType) {
1029 case 0x0000:
1030 return (icFloatNumber)pow(X, m_dParam[0]);
1031
1032 case 0x0001:
1033 a=m_dParam[1];
1034 b=m_dParam[2];
1035
1036 if (X >= -b/a) {
1037 return (icFloatNumber)pow((double)a*X + b, (double)m_dParam[0]);
1038 }
1039 else {
1040 return 0;
1041 }
1042
1043 case 0x0002:
1044 a=m_dParam[1];
1045 b=m_dParam[2];
1046
1047 if (X >= -b/a) {
1048 return (icFloatNumber)pow((double)a*X + b, (double)m_dParam[0]) + m_dParam[3];
1049 }
1050 else {
1051 return m_dParam[3];
1052 }
1053
1054 case 0x0003:
1055 if (X >= m_dParam[4]) {
1056 return (icFloatNumber)pow((double)m_dParam[1]*X + m_dParam[2], (double)m_dParam[0]);
1057 }
1058 else {
1059 return m_dParam[3]*X;
1060 }
1061
1062 case 0x0004:
1063 if (X >= m_dParam[4]) {
1064 return (icFloatNumber)pow((double)m_dParam[1]*X + m_dParam[2], (double)m_dParam[0]) + m_dParam[5];
1065 }
1066 else {
1067 return m_dParam[3]*X + m_dParam[6];
1068 }
1069
1070 default:
1071 return X;
1072 }
1073}
1074
1075
1076/**
1077******************************************************************************
1078* Name: CIccTagParametricCurve::Validate
1079*
1080* Purpose: Check tag data validity.
1081*
1082* Args:
1083* sig = signature of tag being validated,
1084* sReport = String to add report information to
1085*
1086* Return:
1087* icValidateStatusOK if valid, or other error status.
1088******************************************************************************
1089*/
1090icValidateStatus CIccTagParametricCurve::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
1091{
1092 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
1093
1094 CIccInfo Info;
1095 std::string sSigPathName = Info.GetSigPathName(sigPath);
1097
1098 if (m_nReserved2!=0) {
1099 sReport += icMsgValidateNonCompliant;
1100 sReport += sSigPathName;
1101 sReport += " - Reserved Value must be zero.\n";
1102
1104 }
1105
1106 switch(m_nFunctionType) {
1107case 0x0000:
1108 if (m_nNumParam!=1) {
1109 sReport += icMsgValidateCriticalError;
1110 sReport += sSigPathName;
1111 sReport += " - Number of parameters inconsistent with function type.\n";
1113 }
1114 break;
1115
1116case 0x0001:
1117 if (m_nNumParam!=3) {
1118 sReport += icMsgValidateCriticalError;
1119 sReport += sSigPathName;
1120 sReport += " - Number of parameters inconsistent with function type.\n";
1122 }
1123 break;
1124
1125case 0x0002:
1126 if (m_nNumParam!=4) {
1127 sReport += icMsgValidateCriticalError;
1128 sReport += sSigPathName;
1129 sReport += " - Number of parameters inconsistent with function type.\n";
1131 }
1132 break;
1133
1134case 0x0003:
1135 if (m_nNumParam!=5) {
1136 sReport += icMsgValidateCriticalError;
1137 sReport += sSigPathName;
1138 sReport += " - Number of parameters inconsistent with function type.\n";
1140 }
1141 break;
1142
1143case 0x0004:
1144 if (m_nNumParam!=7) {
1145 sReport += icMsgValidateCriticalError;
1146 sReport += sSigPathName;
1147 sReport += " - Number of parameters inconsistent with function type.\n";
1149 }
1150 break;
1151
1152default:
1153 sReport += icMsgValidateCriticalError;
1154 sReport += sSigPathName;
1155 sReport += " - Unknown function type.\n";
1157 }
1158
1160 icFloatNumber lval = Apply(0.0);
1161 icFloatNumber uval = Apply(1.0);
1162 if (lval>0.0 || uval<1.0) {
1163 sReport += icMsgValidateWarning;
1164 sReport += sSigPathName;
1165 sReport += " - Curve cannot be accurately inverted.\n";
1167 }
1168 }
1169
1170 return rv;
1171}
1172
1173/**
1174****************************************************************************
1175* Name: CIccTagSegmentedCurve::CIccTagSegmentedCurve
1176*
1177* Purpose: Constructor
1178*
1179*****************************************************************************
1180*/
1182{
1183 m_pCurve = NULL;
1184}
1185
1186/**
1187****************************************************************************
1188* Name: CIccTagSegmentedCurve::CIccTagSegmentedCurve
1189*
1190* Purpose: Constructor
1191*
1192*****************************************************************************
1193*/
1195{
1196 if (ITSCurve.m_pCurve)
1197 m_pCurve = (CIccSegmentedCurve*)ITSCurve.m_pCurve->NewCopy();
1198 else
1199 m_pCurve = NULL;
1200}
1201
1202/**
1203****************************************************************************
1204* Name: CIccTagSegmentedCurve::CIccTagSegmentedCurve
1205*
1206* Purpose: copy operator
1207*
1208*****************************************************************************
1209*/
1211{
1212 if (m_pCurve)
1213 delete m_pCurve;
1214
1215 if (CurveTag.m_pCurve)
1216 m_pCurve = (CIccSegmentedCurve*)CurveTag.m_pCurve->NewCopy();
1217 else
1218 m_pCurve = NULL;
1219
1220 return *this;
1221}
1222
1223/**
1224****************************************************************************
1225* Name: CIccTagSegmentedCurve::~CIccTagSegmentedCurve
1226*
1227* Purpose: Destructor
1228*
1229*****************************************************************************
1230*/
1232{
1233 if (m_pCurve)
1234 delete m_pCurve;
1235}
1236
1237/**
1238****************************************************************************
1239* Name: CIccTagSegmentedCurve::Describe
1240*
1241* Purpose: gets information about the segmented curve
1242*
1243*****************************************************************************
1244*/
1245void CIccTagSegmentedCurve::Describe(std::string &sDescription, int nVerboseness)
1246{
1247 if (m_pCurve) {
1248 m_pCurve->Describe(sDescription, nVerboseness);
1249 }
1250 else {
1251 sDescription += "TagSegmentedCurve is undefined\n";
1252 }
1253}
1254
1255/**
1256****************************************************************************
1257* Name: CIccTagSegmentedCurve::DumpLut
1258*
1259* Purpose: gets information about segmented curve
1260*
1261*****************************************************************************
1262*/
1263void CIccTagSegmentedCurve::DumpLut(std::string &sDescription, const icChar *szName,
1264 icColorSpaceSignature csSig, int nIndex, int nVerboseness)
1265{
1266 icChar buf[128];
1267
1268 sprintf(buf, "BEGIN_SEGMENTED_CURVE %s\n", szName);
1269 sDescription += buf;
1270 Describe(sDescription, nVerboseness);
1271}
1272
1273/**
1274****************************************************************************
1275* Name: CIccTagSegmentedCurve::Read
1276*
1277* Purpose: read segmented curve from file
1278*
1279*****************************************************************************
1280*/
1282{
1283 CIccSegmentedCurve *pCurve = new CIccSegmentedCurve();
1284
1285 if (pCurve->Read(size, pIO)) {
1286 SetCurve(pCurve);
1287
1288 return true;
1289 }
1290
1291 return false;
1292}
1293
1294/**
1295****************************************************************************
1296* Name: CIccTagSegmentedCurve::Write
1297*
1298* Purpose: write segmented curve to file
1299*
1300*****************************************************************************
1301*/
1303{
1304 if (!m_pCurve)
1305 return false;
1306
1307 return m_pCurve->Write(pIO);
1308}
1309
1310/**
1311****************************************************************************
1312* Name: CIccTagSegmentedCurve::SetCurve
1313*
1314* Purpose: set the current curve object
1315*
1316*****************************************************************************
1317*/
1319{
1320 if (m_pCurve)
1321 delete m_pCurve;
1322
1323 m_pCurve = pCurve;
1324}
1325
1326/**
1327****************************************************************************
1328* Name: CIccTagSegmentedCurve::Begin
1329*
1330* Purpose: Get ready to call apply
1331*
1332*****************************************************************************
1333*/
1335{
1336 if (m_pCurve)
1337 m_pCurve->Begin(icElemInterpLinear, NULL);
1338}
1339
1340/**
1341****************************************************************************
1342* Name: CIccTagSegmentedCurve::Apply
1343*
1344* Purpose: convert input to output values using segmented curve
1345*
1346*****************************************************************************
1347*/
1349{
1350 if (m_pCurve)
1351 return m_pCurve->Apply(v);
1352
1353 return v;
1354}
1355
1356/**
1357****************************************************************************
1358* Name: CIccTagSegmentedCurve::Validate
1359*
1360* Purpose: Constructor
1361*
1362*****************************************************************************
1363*/
1364icValidateStatus CIccTagSegmentedCurve::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
1365{
1366 if (!m_pCurve) {
1367 sReport += "Invalid Segmented Curve Data!\n";
1368
1370 }
1371
1372 return m_pCurve->Validate(sigPath, sReport, NULL);
1373}
1374
1375
1376/**
1377****************************************************************************
1378* Name: CIccTagSegmentedCurve::IsIdentity
1379*
1380* Purpose: Constructor
1381*
1382*****************************************************************************
1383*/
1385{
1386 if (!m_pCurve)
1387 return true;
1388
1389 return false;
1390}
1391
1392
1393/**
1394****************************************************************************
1395* Name: CIccMatrix::CIccMatrix
1396*
1397* Purpose: Constructor
1398*
1399* Args:
1400* bUseConstants = true if the matrix contains additional row for constants
1401*****************************************************************************
1402*/
1403CIccMatrix::CIccMatrix(bool bUseConstants/*=true*/)
1404{
1405 m_bUseConstants = bUseConstants;
1406 m_e[0] = m_e[4] = m_e[8] = 1.0;
1407 m_e[1] = m_e[2] = m_e[3] =
1408 m_e[5] = m_e[6] = m_e[7] = 0.0;
1409
1410 if (!m_bUseConstants) {
1411 m_e[9] = m_e[10] = m_e[11] = 0.0;
1412 }
1413}
1414
1415
1416/**
1417****************************************************************************
1418* Name: CIccMatrix::CIccMatrix
1419*
1420* Purpose: Copy Constructor
1421*
1422* Args:
1423* MatrixClass = The CIccMatrix object to be copied
1424*****************************************************************************
1425*/
1427{
1428 m_bUseConstants = MatrixClass.m_bUseConstants;
1429 memcpy(m_e, MatrixClass.m_e, sizeof(m_e));
1430}
1431
1432
1433/**
1434****************************************************************************
1435* Name: CIccMatrix::operator=
1436*
1437* Purpose: Copy Operator
1438*
1439* Args:
1440* MatrixClass = The CIccMatrix object to be copied
1441*****************************************************************************
1442*/
1444{
1445 if (&MatrixClass == this)
1446 return *this;
1447
1448 m_bUseConstants = MatrixClass.m_bUseConstants;
1449 memcpy(m_e, MatrixClass.m_e, sizeof(m_e));
1450
1451 return *this;
1452}
1453
1454
1455/**
1456****************************************************************************
1457* Name: CIccTagParametricCurve::DumpLut
1458*
1459* Purpose: Dump the matrix data to a string.
1460*
1461* Args:
1462* sDescription = string to concatenate tag dump to,
1463* szName = name of the curve to be printed
1464*****************************************************************************
1465*/
1466void CIccMatrix::DumpLut(std::string &sDescription, const icChar *szName, int nVerboseness)
1467{
1468 icChar buf[128];
1469
1470 sprintf(buf, "BEGIN_MATRIX %s\n", szName);
1471 sDescription += buf;
1472
1473 if (!m_bUseConstants) {
1474 sprintf(buf, "%8.4lf %8.4lf %8.4lf\n",
1475 m_e[0], m_e[1], m_e[2]);
1476 sDescription += buf;
1477 sprintf(buf, "%8.4lf %8.4lf %8.4lf\n",
1478 m_e[3], m_e[4], m_e[5]);
1479 sDescription += buf;
1480 sprintf(buf, "%8.4lf %8.4lf %8.4lf\n",
1481 m_e[6], m_e[7], m_e[8]);
1482 sDescription += buf;
1483 }
1484 else {
1485 sprintf(buf, "%8.4lf %8.4lf %8.4lf + %8.4lf\n",
1486 m_e[0], m_e[1], m_e[2], m_e[9]);
1487 sDescription += buf;
1488 sprintf(buf, "%8.4lf %8.4lf %8.4lf + %8.4lf\n",
1489 m_e[3], m_e[4], m_e[5], m_e[10]);
1490 sDescription += buf;
1491 sprintf(buf, "%8.4lf %8.4lf %8.4lf + %8.4lf\n",
1492 m_e[6], m_e[7], m_e[8], m_e[11]);
1493 sDescription += buf;
1494 }
1495}
1496
1497/**
1498****************************************************************************
1499* Name: CIccMatrix::IsIdentity
1500*
1501* Purpose: Checks if the matrix is identity
1502*
1503* Return:
1504* true if matrix is identity and uses no constants, else false
1505*
1506*****************************************************************************
1507*/
1509{
1510 if (m_bUseConstants) {
1511 if (fabs(m_e[9])>0.0 || fabs(m_e[10])>0.0 || fabs(m_e[11])>0.0) {
1512 return false;
1513 }
1514 }
1515
1516 if (!IsUnity(m_e[0]) || !IsUnity(m_e[4]) || !IsUnity(m_e[8])) {
1517 return false;
1518 }
1519
1520 if (fabs(m_e[1])>0.0 || fabs(m_e[2])>0.0 || fabs(m_e[3])>0.0 ||
1521 fabs(m_e[5])>0.0 || fabs(m_e[6])>0.0 || fabs(m_e[7])>0.0)
1522 {
1523 return false;
1524 }
1525
1526 return true;
1527}
1528
1529/**
1530****************************************************************************
1531* Name: CIccMatrix::Apply
1532*
1533* Purpose: Multiplies the pixel by the matrix.
1534*
1535* Args:
1536* Pixel = Pixel to be multiplied by the matrix
1537*
1538*****************************************************************************
1539*/
1541{
1542 icFloatNumber a=Pixel[0];
1543 icFloatNumber b=Pixel[1];
1544 icFloatNumber c=Pixel[2];
1545
1546 icFloatNumber x = m_e[0]*a + m_e[1]*b + m_e[2]*c;
1547 icFloatNumber y = m_e[3]*a + m_e[4]*b + m_e[5]*c;
1548 icFloatNumber z = m_e[6]*a + m_e[7]*b + m_e[8]*c;
1549
1550 if (m_bUseConstants) {
1551 x += m_e[9];
1552 y += m_e[10];
1553 z += m_e[11];
1554 }
1555
1556 Pixel[0] = x;
1557 Pixel[1] = y;
1558 Pixel[2] = z;
1559}
1560
1561
1562/**
1563******************************************************************************
1564* Name: CIccMatrix::Validate
1565*
1566* Purpose: Check tag data validity.
1567*
1568* Args:
1569* sig = signature of tag being validated,
1570* sReport = String to add report information to
1571*
1572* Return:
1573* icValidateStatusOK if valid, or other error status.
1574******************************************************************************
1575*/
1576icValidateStatus CIccMatrix::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
1577{
1580
1582 if (pProfile->m_Header.pcs!=icSigXYZData) {
1583 CIccInfo Info;
1584 std::string sSigPathName = Info.GetSigPathName(sigPath);
1585 icFloatNumber sum=0.0;
1586 for (int i=0; i<9; i++) {
1587 sum += m_e[i];
1588 }
1589 if (m_e[0]!=1.0 || m_e[4]!=1.0 || m_e[9]!=1.0 || sum!=3.0) {
1590 sReport += icMsgValidateNonCompliant;
1591 sReport += sSigPathName;
1592 sReport += " - Matrix must be identity.\n";
1594 }
1595 }
1596 }
1597
1598 return rv;
1599}
1600
1601
1603{
1604 if (v<0)
1605 return 0;
1606 else if (v>1.0)
1607 return 1.0;
1608
1609 return v;
1610}
1611
1612/**
1613**************************************************************************
1614* Name: CIccApplyCLUT::CIccApplyCLUT
1615*
1616* Purpose:
1617* Constructor
1618**************************************************************************
1619*/
1621{
1622 m_df = NULL;
1623 m_s = NULL;
1624 m_g = NULL;
1625 m_ig = NULL;
1626}
1627
1628
1629/**
1630**************************************************************************
1631* Name: CIccApplyNDLutXform::~CIccApplyNDLutXform
1632*
1633* Purpose:
1634* Destructor
1635**************************************************************************
1636*/
1638{
1639 if (m_df)
1640 free(m_df);
1641 if (m_s)
1642 free(m_s);
1643 if (m_g)
1644 free(m_g);
1645 if (m_ig)
1646 free(m_ig);
1647}
1648
1649
1650/**
1651**************************************************************************
1652* Name: CIccApplyCLUT::Init
1653*
1654* Purpose:
1655* Initializer
1656**************************************************************************
1657*/
1659{
1660 if (nSrcChannels > 6) {
1661
1662 m_df = (icFloatNumber*)malloc(nNodes * sizeof(icFloatNumber));
1663 m_s = (icFloatNumber*)malloc(nSrcChannels * sizeof(icFloatNumber));
1664 m_g = (icFloatNumber*)malloc(nSrcChannels * sizeof(icFloatNumber));
1665 m_ig = (icUInt32Number*)malloc(nSrcChannels * sizeof(icUInt32Number));
1666
1667 if (!m_df || !m_s || !m_g || !m_ig)
1668 return false;
1669 }
1670 return true;
1671}
1672
1673/**
1674 ****************************************************************************
1675 * Name: CIccCLUT::CIccCLUT
1676 *
1677 * Purpose: Constructor
1678 *
1679 * Args:
1680 * nInputChannels = number of input channels,
1681 * nOutputChannels = number of output channels
1682 *
1683 *****************************************************************************
1684 */
1685CIccCLUT::CIccCLUT(icUInt8Number nInputChannels, icUInt16Number nOutputChannels, icUInt8Number nPrecision/*=2*/)
1686{
1687 m_nInput = nInputChannels;
1688 m_nOutput = nOutputChannels;
1689 m_nPrecision = nPrecision;
1690 m_pData = NULL;
1691 m_nOffset = NULL;
1692 memset(&m_nReserved2, 0 , sizeof(m_nReserved2));
1693
1695}
1696
1697
1698/**
1699 ****************************************************************************
1700 * Name: CIccCLUT::CIccCLUT
1701 *
1702 * Purpose: Copy Constructor
1703 *
1704 * Args:
1705 * ICLUT = The CIccCLUT object to be copied
1706 *****************************************************************************
1707 */
1709{
1710 m_pData = NULL;
1711 m_nOffset = NULL;
1712 m_nInput = ICLUT.m_nInput;
1713 m_nOutput = ICLUT.m_nOutput;
1714 m_nPrecision = ICLUT.m_nPrecision;
1715 m_nNumPoints = ICLUT.m_nNumPoints;
1716
1717 m_csInput = ICLUT.m_csInput;
1718 m_csOutput = ICLUT.m_csOutput;
1719
1720 memcpy(m_GridPoints, ICLUT.m_GridPoints, sizeof(m_GridPoints));
1721 memcpy(m_DimSize, ICLUT.m_DimSize, sizeof(m_DimSize));
1722 memcpy(m_GridAdr, ICLUT.m_GridAdr, sizeof(m_GridAdr));
1723 memcpy(&m_nReserved2, &ICLUT.m_nReserved2, sizeof(m_nReserved2));
1724
1725 int num = NumPoints()*m_nOutput;
1726 m_pData = new icFloatNumber[num];
1727 memcpy(m_pData, ICLUT.m_pData, num*sizeof(icFloatNumber));
1728
1729 UnitClip = ICLUT.UnitClip;
1730}
1731
1732
1733/**
1734 ****************************************************************************
1735 * Name: CIccCLUT::operator=
1736 *
1737 * Purpose: Copy Operator
1738 *
1739 * Args:
1740 * CLUTTag = The CIccCLUT object to be copied
1741 *****************************************************************************
1742 */
1744{
1745 if (&CLUTTag == this)
1746 return *this;
1747
1748 m_nInput = CLUTTag.m_nInput;
1749 m_nOutput = CLUTTag.m_nOutput;
1750 m_nPrecision = CLUTTag.m_nPrecision;
1751 m_nNumPoints = CLUTTag.m_nNumPoints;
1752
1753 m_csInput = CLUTTag.m_csInput;
1754 m_csOutput = CLUTTag.m_csOutput;
1755
1756 memcpy(m_GridPoints, CLUTTag.m_GridPoints, sizeof(m_GridPoints));
1757 memcpy(m_DimSize, CLUTTag.m_DimSize, sizeof(m_DimSize));
1758 memcpy(m_GridAdr, CLUTTag.m_GridAdr, sizeof(m_GridAdr));
1759 memcpy(m_nReserved2, &CLUTTag.m_nReserved2, sizeof(m_nReserved2));
1760
1761 int num;
1762 if (m_pData)
1763 delete [] m_pData;
1764 num = NumPoints()*m_nOutput;
1765 m_pData = new icFloatNumber[num];
1766 memcpy(m_pData, CLUTTag.m_pData, num*sizeof(icFloatNumber));
1767
1768 UnitClip = CLUTTag.UnitClip;
1769
1770 return *this;
1771}
1772
1773
1774
1775/**
1776 ****************************************************************************
1777 * Name: CIccCLUT::~CIccCLUT
1778 *
1779 * Purpose: Destructor
1780 *
1781 *****************************************************************************
1782 */
1784{
1785 if (m_pData)
1786 delete [] m_pData;
1787
1788 if (m_nOffset)
1789 delete [] m_nOffset;
1790
1791}
1792
1793/**
1794 ****************************************************************************
1795 * Name: CIccCLUT::Init
1796 *
1797 * Purpose: Initializes and sets the size of the CLUT
1798 *
1799 * Args:
1800 * nGridPoints = number of grid points in the CLUT
1801 *****************************************************************************
1802 */
1803bool CIccCLUT::Init(icUInt8Number nGridPoints, icUInt32Number nMaxSize, icUInt8Number nBytesPerPoint)
1804{
1805 memset(&m_GridPoints, 0, sizeof(m_GridPoints));
1806 // m_GridPoints[] is a fixed length of 16
1807 if (m_nInput > 16)
1808 return false;
1809 memset(m_GridPoints, nGridPoints, m_nInput);
1810 return Init(&m_GridPoints[0], nMaxSize, nBytesPerPoint);
1811}
1812
1813/**
1814 ****************************************************************************
1815 * Name: CIccCLUT::Init
1816 *
1817 * Purpose: Initializes and sets the size of the CLUT
1818 *
1819 * Args:
1820 * pGridPoints = number of grid points in the CLUT
1821 *****************************************************************************
1822 */
1823bool CIccCLUT::Init(const icUInt8Number *pGridPoints, icUInt32Number nMaxSize, icUInt8Number nBytesPerPoint)
1824{
1825 if (nMaxSize && !nBytesPerPoint)
1826 return false;
1827
1828 icUInt64Number nNumPoints;
1829 memset(m_nReserved2, 0, sizeof(m_nReserved2));
1830 if (pGridPoints!=&m_GridPoints[0]) {
1831 // m_GridPoints[] is fixed size of 16
1832 if (m_nInput > 16)
1833 return false;
1834 memcpy(m_GridPoints, pGridPoints, m_nInput);
1835 if (m_nInput<16)
1836 memset(m_GridPoints+m_nInput, 0, 16-m_nInput);
1837 }
1838
1839 // There should be at least 2 grid points for each input dimension for interpolation to work
1840 for (int i = 0; i < m_nInput; i++) {
1841 if (pGridPoints[i] < 2)
1842 return false;
1843 }
1844
1845 if (m_pData) {
1846 delete [] m_pData;
1847 m_pData = NULL;
1848 }
1849
1850 int i=m_nInput-1;
1851
1852 // m_DimSize[] is a fixed size of 16
1853 if (i >= 16)
1854 return false;
1855
1856 m_DimSize[i] = m_nOutput;
1857 nNumPoints = m_GridPoints[i];
1858 for (i--; i>=0; i--) {
1859 m_DimSize[i] = m_DimSize[i+1] * m_GridPoints[i+1];
1860 nNumPoints *= m_GridPoints[i];
1861 if (nMaxSize && nNumPoints * m_nOutput * nBytesPerPoint > nMaxSize)
1862 return false;
1863 }
1864 m_nNumPoints = (icUInt32Number)nNumPoints;
1865
1866 icUInt32Number nSize = NumPoints() * m_nOutput;
1867
1868 if (!nSize)
1869 return false;
1870
1871 m_pData = new icFloatNumber[nSize];
1872
1873 return (m_pData != NULL);
1874}
1875
1876
1877/**
1878 ****************************************************************************
1879 * Name: CIccCLUT::ReadData
1880 *
1881 * Purpose: Reads the CLUT data points into the data buffer
1882 *
1883 * Args:
1884 * size = # of bytes in the tag,
1885 * pIO = IO object to read data from,
1886 * nPrecision = data precision (8bit encoded as 1 or 16bit encoded as 2)
1887 *
1888 * Return:
1889 * true = data read succesfully,
1890 * false = read data failed
1891 *****************************************************************************
1892 */
1894{
1895 icUInt32Number nNum=NumPoints() * m_nOutput;
1896
1897 if (nNum * nPrecision > size)
1898 return false;
1899
1900 if (m_pData == NULL)
1901 return false;
1902
1903 if (nPrecision==1) {
1904 if (pIO->ReadUInt8Float(m_pData, nNum)!=(icInt32Number)nNum)
1905 return false;
1906 }
1907 else if (nPrecision==2) {
1908 if (pIO->ReadUInt16Float(m_pData, nNum)!=(icInt32Number)nNum)
1909 return false;
1910 }
1911 else
1912 return false;
1913
1914 return true;
1915}
1916
1917
1918/**
1919 ****************************************************************************
1920 * Name: CIccCLUT::WriteData
1921 *
1922 * Purpose: Writes the CLUT data points from the data buffer
1923 *
1924 * Args:
1925 * pIO = IO object to write data to,
1926 * nPrecision = data precision (8bit encoded as 1 or 16bit encoded as 2)
1927 *
1928 * Return:
1929 * true = data written succesfully,
1930 * false = write operation failed
1931 *****************************************************************************
1932 */
1934{
1935 icUInt32Number nNum=NumPoints() * m_nOutput;
1936
1937 if (nPrecision==1) {
1938 if (pIO->WriteUInt8Float(m_pData, nNum)!=(icInt32Number)nNum)
1939 return false;
1940 }
1941 else if (nPrecision==2) {
1942 if (pIO->WriteUInt16Float(m_pData, nNum)!=(icInt32Number)nNum)
1943 return false;
1944 }
1945 else
1946 return false;
1947
1948 return true;
1949}
1950
1951
1952/**
1953 ****************************************************************************
1954 * Name: CIccCLUT::Read
1955 *
1956 * Purpose: Read in the tag contents into a data block
1957 *
1958 * Args:
1959 * size - # of bytes in tag,
1960 * pIO - IO object to read tag from
1961 *
1962 * Return:
1963 * true = successful, false = failure
1964 *****************************************************************************
1965 */
1967{
1968 if (size < 20)
1969 return false;
1970
1971 if (pIO->Read8(m_GridPoints, 16)!=16 ||
1972 !pIO->Read8(&m_nPrecision) ||
1973 pIO->Read8(&m_nReserved2[0], 3)!=3)
1974 return false;
1975
1976 if (!Init(m_GridPoints, size - 20, m_nPrecision))
1977 return false;
1978
1979 return ReadData(size-20, pIO, m_nPrecision);
1980}
1981
1982
1983/**
1984 ****************************************************************************
1985 * Name: CIccCLUT::Write
1986 *
1987 * Purpose: Write the tag to a file
1988 *
1989 * Args:
1990 * pIO - The IO object to write tag to.
1991 *
1992 * Return:
1993 * true = succesful, false = failure
1994 *****************************************************************************
1995 */
1997{
1998 if (pIO->Write8(m_GridPoints, 16)!=16 ||
1999 !pIO->Write8(&m_nPrecision) ||
2000 pIO->Write8(&m_nReserved2[0], 3)!=3)
2001 return false;
2002
2003 return WriteData(pIO, m_nPrecision);
2004}
2005
2006/**
2007 ****************************************************************************
2008 * Name: CIccCLUT::Iterate
2009 *
2010 * Purpose: Iterate through the CLUT to dump the data
2011 *
2012 * Args:
2013 * sDescription = string to concatenate data dump to,
2014 * nIndex = the channel number,
2015 * nPos = the current position in the CLUT
2016 *
2017 *****************************************************************************
2018 */
2019void CIccCLUT::Iterate(std::string &sDescription, icUInt8Number nIndex, icUInt32Number nPos, bool bUseLegacy)
2020{
2021 if (nIndex < m_nInput) {
2022 int i;
2023 for (i=0; i<m_GridPoints[nIndex]; i++) {
2024 m_GridAdr[nIndex] = i;
2025 Iterate(sDescription, nIndex+1, nPos, bUseLegacy);
2026 nPos += m_DimSize[nIndex];
2027 }
2028 }
2029 else {
2030 icChar *ptr = m_pOutText;
2031 icFloatNumber *pData = &m_pData[nPos];
2032 int i;
2033
2034 for (i=0; i<m_nInput; i++) {
2035 icColorValue(m_pVal, (icFloatNumber)m_GridAdr[i] / (m_GridPoints[i]-1) , m_csInput, i, bUseLegacy);
2036
2037 ptr += sprintf(ptr, " %s", m_pVal);
2038 }
2039 strcpy(ptr, " ");
2040 ptr += 2;
2041
2042 for (i=0; i<m_nOutput; i++) {
2043 icColorValue(m_pVal, pData[i], m_csOutput, i, bUseLegacy);
2044
2045 ptr += sprintf(ptr, " %s", m_pVal);
2046 }
2047 strcpy(ptr, "\n");
2048 sDescription += (const icChar*)m_pOutText;
2049
2050 }
2051}
2052
2053
2054/**
2055 ****************************************************************************
2056 * Name: CIccCLUT::Iterate
2057 *
2058 * Purpose: Iterate through the CLUT to get the data and execute PixelOp
2059 *
2060 * Args:
2061 * pExec = pointer to the IIccCLUTExec object that implements the
2062 * IIccCLUTExec::Apply() function
2063 *
2064 *****************************************************************************
2065 */
2067{
2068 memset(&m_fGridAdr[0], 0, sizeof(m_fGridAdr));
2069 if (m_nInput==3) {
2070 int i,j,k;
2071 icUInt32Number index=0;
2072 for (i=0; i<m_GridPoints[0]; i++) {
2073 for (j=0; j<m_GridPoints[1]; j++) {
2074 for (k=0; k<m_GridPoints[2]; k++) {
2075 m_fGridAdr[2] = (icFloatNumber)k/(icFloatNumber)(m_GridPoints[2]-1);
2076 m_fGridAdr[1] = (icFloatNumber)j/(icFloatNumber)(m_GridPoints[1]-1);
2077 m_fGridAdr[0] = (icFloatNumber)i/(icFloatNumber)(m_GridPoints[0]-1);
2078
2079 index = (m_DimSize[0]*i + m_DimSize[1]*j + m_DimSize[2]*k);
2080 pExec->PixelOp(m_fGridAdr, &m_pData[index]);
2081
2082 }
2083 }
2084 }
2085 }
2086 else if (m_nInput==4) {
2087 int i,j,k,l;
2088 icUInt32Number index=0;
2089 for (i=0; i<m_GridPoints[0]; i++) {
2090 for (j=0; j<m_GridPoints[1]; j++) {
2091 for (k=0; k<m_GridPoints[2]; k++) {
2092 for (l=0; l<m_GridPoints[3]; l++) {
2093 m_fGridAdr[3] = (icFloatNumber)l/(icFloatNumber)(m_GridPoints[3]-1);
2094 m_fGridAdr[2] = (icFloatNumber)k/(icFloatNumber)(m_GridPoints[2]-1);
2095 m_fGridAdr[1] = (icFloatNumber)j/(icFloatNumber)(m_GridPoints[1]-1);
2096 m_fGridAdr[0] = (icFloatNumber)i/(icFloatNumber)(m_GridPoints[0]-1);
2097
2098 index = (m_DimSize[0]*i + m_DimSize[1]*j +
2099 m_DimSize[2]*k + m_DimSize[3]*l);
2100 pExec->PixelOp(m_fGridAdr, &m_pData[index]);
2101
2102 }
2103 }
2104 }
2105 }
2106 }
2107 else
2108 SubIterate(pExec, 0, 0);
2109}
2110
2111
2112/**
2113 ****************************************************************************
2114 * Name: CIccCLUT::SubIterate
2115 *
2116 * Purpose: Iterate through the CLUT to get the data
2117 *
2118 * Args:
2119 * pExec = pointer to the IIccCLUTExec object that implements the
2120 * IIccCLUTExec::Apply() function,
2121 * nIndex = the channel number,
2122 * nPos = the current position in the CLUT
2123 *
2124 *****************************************************************************
2125 */
2127{
2128 if (nIndex < m_nInput) {
2129 int i;
2130 for (i=0; i<m_GridPoints[nIndex]; i++) {
2131 m_fGridAdr[nIndex] = (icFloatNumber)i/(icFloatNumber)(m_GridPoints[nIndex]-1);
2132 SubIterate(pExec, nIndex+1, nPos);
2133 nPos += m_DimSize[nIndex];
2134 }
2135 }
2136 else
2137 pExec->PixelOp(m_fGridAdr, &m_pData[nPos]);
2138}
2139
2140/**
2141 ****************************************************************************
2142 * Name: CIccCLUT::DumpLut
2143 *
2144 * Purpose: Dump data associated with the tag to a string.
2145 *
2146 * Args:
2147 * sDescription = string to concatenate tag dump to,
2148 * szName = name of the LUT to be printed,
2149 * csInput = color space signature of the input data,
2150 * csOutput = color space signature of the output data
2151 * nVerboseness = how verbose the output is (bigger = more verbose)
2152 *****************************************************************************
2153 */
2154void CIccCLUT::DumpLut(std::string &sDescription, const icChar *szName,
2156 int nVerboseness, bool bUseLegacy)
2157{
2158 icChar szOutText[200000], szColor[40];
2159 int i;
2160
2161 sprintf(szOutText, "BEGIN_LUT %s %d %d\n", szName, m_nInput, m_nOutput);
2162 sDescription += szOutText;
2163
2164 if (nVerboseness > 75) {
2165
2166 for (i=0; i<m_nInput; i++) {
2167 icColorIndexName(szColor, csInput, i, m_nInput, "In");
2168 sprintf(szOutText, " %s=%d", szColor, m_GridPoints[i]);
2169 sDescription += szOutText;
2170 }
2171
2172 sDescription += " ";
2173
2174 for (i=0; i<m_nOutput; i++) {
2175 icColorIndexName(szColor, csOutput, i, m_nOutput, "Out");
2176 sprintf(szOutText, " %s", szColor);
2177 sDescription += szOutText;
2178 }
2179
2180 sDescription += "\n";
2181
2182 if (nVerboseness > 75) {
2183 size_t len = 0;
2184 for (i=0; i<m_nInput; i++) {
2185 icColorValue(szColor, 1.0, csInput, i, bUseLegacy);
2186 len += strlen(szColor);
2187 }
2188 for (i=0; i<m_nOutput; i++) {
2189 icColorValue(szColor, 1.0, csOutput, i, bUseLegacy);
2190 len += strlen(szColor);
2191 }
2192 len += m_nInput + m_nOutput + 6;
2193
2194 sDescription.reserve(sDescription.size() + NumPoints()*len);
2195
2196 //Initialize iteration member variables
2197 m_csInput = csInput;
2198 m_csOutput = csOutput;
2199 m_pOutText = szOutText;
2200 m_pVal = szColor;
2201 memset(m_GridAdr, 0, 16);
2202
2203 Iterate(sDescription, 0, 0, bUseLegacy);
2204 }
2205 }
2206}
2207
2208
2209
2210/**
2211 ****************************************************************************
2212 * Name: CIccCLUT::Begin
2213 *
2214 * Purpose: Initializes the CLUT. Must be called before Apply().
2215 *
2216 *****************************************************************************
2217 */
2219{
2220 int i;
2221 for (i=0; i<m_nInput; i++) {
2222 m_MaxGridPoint[i] = m_GridPoints[i] - 1;
2223 }
2224 m_nNodes = (1<<m_nInput);
2225
2226 if (m_nOffset)
2227 delete [] m_nOffset;
2228
2229 m_nOffset = new icUInt32Number[m_nNodes];
2230
2231 if (m_nInput==1) {
2232 m_nOffset[0] = n000 = 0;
2233 m_nOffset[1] = n001 = m_DimSize[0];
2234 }
2235 else if (m_nInput==2) {
2236 m_nOffset[0] = n000 = 0;
2237 m_nOffset[1] = n001 = m_DimSize[0];
2238 m_nOffset[2] = n010 = m_DimSize[1];
2239 m_nOffset[3] = n011 = n001 + n010;
2240 }
2241 else if (m_nInput==3) {
2242 m_nOffset[0] = n000 = 0;
2243 m_nOffset[1] = n001 = m_DimSize[0];
2244 m_nOffset[2] = n010 = m_DimSize[1];
2245 m_nOffset[3] = n011 = n001 + n010;
2246 m_nOffset[4] = n100 = m_DimSize[2];
2247 m_nOffset[5] = n101 = n100 + n001;
2248 m_nOffset[6] = n110 = n100 + n010;
2249 m_nOffset[7] = n111 = n110 + n001;
2250 }
2251 else if (m_nInput == 4) {
2252 m_nOffset[ 0] = 0;
2253 m_nOffset[ 1] = n001 = m_DimSize[ 0];
2254 m_nOffset[ 2] = n010 = m_DimSize[ 1];
2255 m_nOffset[ 3] = m_nOffset[ 2] + m_nOffset[ 1];
2256 m_nOffset[ 4] = n100 = m_DimSize[ 2];
2257 m_nOffset[ 5] = m_nOffset[ 4] + m_nOffset[ 1];
2258 m_nOffset[ 6] = m_nOffset[ 4] + m_nOffset[ 2];
2259 m_nOffset[ 7] = m_nOffset[ 4] + m_nOffset[ 3];
2260 m_nOffset[ 8] = n1000 = m_DimSize[ 3];
2261 m_nOffset[ 9] = m_nOffset[ 8] + m_nOffset[ 1];
2262 m_nOffset[10] = m_nOffset[ 8] + m_nOffset[ 2];
2263 m_nOffset[11] = m_nOffset[ 8] + m_nOffset[ 3];
2264 m_nOffset[12] = m_nOffset[ 8] + m_nOffset[ 4];
2265 m_nOffset[13] = m_nOffset[ 8] + m_nOffset[ 5];
2266 m_nOffset[14] = m_nOffset[ 8] + m_nOffset[ 6];
2267 m_nOffset[15] = m_nOffset[ 8] + m_nOffset[ 7];
2268 }
2269 else if (m_nInput == 5) {
2270 m_nOffset[ 0] = 0;
2271 m_nOffset[ 1] = n001 = m_DimSize[ 0];
2272 m_nOffset[ 2] = n010 = m_DimSize[ 1];
2273 m_nOffset[ 3] = m_nOffset[ 2] + m_nOffset[ 1];
2274 m_nOffset[ 4] = n100 = m_DimSize[ 2];
2275 m_nOffset[ 5] = m_nOffset[ 4] + m_nOffset[ 1];
2276 m_nOffset[ 6] = m_nOffset[ 4] + m_nOffset[ 2];
2277 m_nOffset[ 7] = m_nOffset[ 4] + m_nOffset[ 3];
2278 m_nOffset[ 8] = n1000 = m_DimSize[ 3];
2279 m_nOffset[ 9] = m_nOffset[ 8] + m_nOffset[ 1];
2280 m_nOffset[10] = m_nOffset[ 8] + m_nOffset[ 2];
2281 m_nOffset[11] = m_nOffset[ 8] + m_nOffset[ 3];
2282 m_nOffset[12] = m_nOffset[ 8] + m_nOffset[ 4];
2283 m_nOffset[13] = m_nOffset[ 8] + m_nOffset[ 5];
2284 m_nOffset[14] = m_nOffset[ 8] + m_nOffset[ 6];
2285 m_nOffset[15] = m_nOffset[ 8] + m_nOffset[ 7];
2286 m_nOffset[16] = n10000 = m_DimSize[ 4];
2287 m_nOffset[17] = m_nOffset[16] + m_nOffset[ 1];
2288 m_nOffset[18] = m_nOffset[16] + m_nOffset[ 2];
2289 m_nOffset[19] = m_nOffset[16] + m_nOffset[ 3];
2290 m_nOffset[20] = m_nOffset[16] + m_nOffset[ 4];
2291 m_nOffset[21] = m_nOffset[16] + m_nOffset[ 5];
2292 m_nOffset[22] = m_nOffset[16] + m_nOffset[ 6];
2293 m_nOffset[23] = m_nOffset[16] + m_nOffset[ 7];
2294 m_nOffset[24] = m_nOffset[16] + m_nOffset[ 8];
2295 m_nOffset[25] = m_nOffset[16] + m_nOffset[ 9];
2296 m_nOffset[26] = m_nOffset[16] + m_nOffset[10];
2297 m_nOffset[27] = m_nOffset[16] + m_nOffset[11];
2298 m_nOffset[28] = m_nOffset[16] + m_nOffset[12];
2299 m_nOffset[29] = m_nOffset[16] + m_nOffset[13];
2300 m_nOffset[30] = m_nOffset[16] + m_nOffset[14];
2301 m_nOffset[31] = m_nOffset[16] + m_nOffset[15];
2302 }
2303 else if (m_nInput == 6) {
2304 m_nOffset[ 0] = 0;
2305 m_nOffset[ 1] = n001 = m_DimSize[ 0];
2306 m_nOffset[ 2] = n010 = m_DimSize[ 1];
2307 m_nOffset[ 3] = m_nOffset[ 2] + m_nOffset[ 1];
2308 m_nOffset[ 4] = n100 = m_DimSize[ 2];
2309 m_nOffset[ 5] = m_nOffset[ 4] + m_nOffset[ 1];
2310 m_nOffset[ 6] = m_nOffset[ 4] + m_nOffset[ 2];
2311 m_nOffset[ 7] = m_nOffset[ 4] + m_nOffset[ 3];
2312 m_nOffset[ 8] = n1000 = m_DimSize[ 3];
2313 m_nOffset[ 9] = m_nOffset[ 8] + m_nOffset[ 1];
2314 m_nOffset[10] = m_nOffset[ 8] + m_nOffset[ 2];
2315 m_nOffset[11] = m_nOffset[ 8] + m_nOffset[ 3];
2316 m_nOffset[12] = m_nOffset[ 8] + m_nOffset[ 4];
2317 m_nOffset[13] = m_nOffset[ 8] + m_nOffset[ 5];
2318 m_nOffset[14] = m_nOffset[ 8] + m_nOffset[ 6];
2319 m_nOffset[15] = m_nOffset[ 8] + m_nOffset[ 7];
2320 m_nOffset[16] = n10000 = m_DimSize[ 4];
2321 m_nOffset[17] = m_nOffset[16] + m_nOffset[ 1];
2322 m_nOffset[18] = m_nOffset[16] + m_nOffset[ 2];
2323 m_nOffset[19] = m_nOffset[16] + m_nOffset[ 3];
2324 m_nOffset[20] = m_nOffset[16] + m_nOffset[ 4];
2325 m_nOffset[21] = m_nOffset[16] + m_nOffset[ 5];
2326 m_nOffset[22] = m_nOffset[16] + m_nOffset[ 6];
2327 m_nOffset[23] = m_nOffset[16] + m_nOffset[ 7];
2328 m_nOffset[24] = m_nOffset[16] + m_nOffset[ 8];
2329 m_nOffset[25] = m_nOffset[16] + m_nOffset[ 9];
2330 m_nOffset[26] = m_nOffset[16] + m_nOffset[10];
2331 m_nOffset[27] = m_nOffset[16] + m_nOffset[11];
2332 m_nOffset[28] = m_nOffset[16] + m_nOffset[12];
2333 m_nOffset[29] = m_nOffset[16] + m_nOffset[13];
2334 m_nOffset[30] = m_nOffset[16] + m_nOffset[14];
2335 m_nOffset[31] = m_nOffset[16] + m_nOffset[15];
2336 m_nOffset[32] = n100000 = m_DimSize[5];
2337 m_nOffset[33] = m_nOffset[32] + m_nOffset[ 1];
2338 m_nOffset[34] = m_nOffset[32] + m_nOffset[ 2];
2339 m_nOffset[35] = m_nOffset[32] + m_nOffset[ 3];
2340 m_nOffset[36] = m_nOffset[32] + m_nOffset[ 4];
2341 m_nOffset[37] = m_nOffset[32] + m_nOffset[ 5];
2342 m_nOffset[38] = m_nOffset[32] + m_nOffset[ 6];
2343 m_nOffset[39] = m_nOffset[32] + m_nOffset[ 7];
2344 m_nOffset[40] = m_nOffset[32] + m_nOffset[ 8];
2345 m_nOffset[41] = m_nOffset[32] + m_nOffset[ 9];
2346 m_nOffset[42] = m_nOffset[32] + m_nOffset[10];
2347 m_nOffset[43] = m_nOffset[32] + m_nOffset[11];
2348 m_nOffset[44] = m_nOffset[32] + m_nOffset[12];
2349 m_nOffset[45] = m_nOffset[32] + m_nOffset[13];
2350 m_nOffset[46] = m_nOffset[32] + m_nOffset[14];
2351 m_nOffset[47] = m_nOffset[32] + m_nOffset[15];
2352 m_nOffset[48] = m_nOffset[32] + m_nOffset[16];
2353 m_nOffset[49] = m_nOffset[32] + m_nOffset[17];
2354 m_nOffset[50] = m_nOffset[32] + m_nOffset[18];
2355 m_nOffset[51] = m_nOffset[32] + m_nOffset[19];
2356 m_nOffset[52] = m_nOffset[32] + m_nOffset[20];
2357 m_nOffset[53] = m_nOffset[32] + m_nOffset[21];
2358 m_nOffset[54] = m_nOffset[32] + m_nOffset[22];
2359 m_nOffset[55] = m_nOffset[32] + m_nOffset[23];
2360 m_nOffset[56] = m_nOffset[32] + m_nOffset[24];
2361 m_nOffset[57] = m_nOffset[32] + m_nOffset[25];
2362 m_nOffset[58] = m_nOffset[32] + m_nOffset[26];
2363 m_nOffset[59] = m_nOffset[32] + m_nOffset[27];
2364 m_nOffset[60] = m_nOffset[32] + m_nOffset[28];
2365 m_nOffset[61] = m_nOffset[32] + m_nOffset[29];
2366 m_nOffset[62] = m_nOffset[32] + m_nOffset[30];
2367 m_nOffset[63] = m_nOffset[32] + m_nOffset[31];
2368 }
2369 else {
2370
2371 m_nOffset[0] = 0;
2372 int count, nFlag;
2373 icUInt32Number nPower[2];
2374 nPower[0] = 0;
2375 nPower[1] = 1;
2376
2377 for (count=0; count<m_nInput; count++) {
2378 m_nPower[count] = (1<<(m_nInput-1-count));
2379 }
2380
2381 count = 0;
2382 nFlag = 1;
2383 for (icUInt32Number j=1; j<m_nNodes; j++) {
2384 if (j == nPower[1]) {
2385 m_nOffset[j] = m_DimSize[count];
2386 nPower[0] = (1<<count);
2387 count++;
2388 nPower[1] = (1<<count);
2389 nFlag = 1;
2390 }
2391 else {
2392 m_nOffset[j] = m_nOffset[nPower[0]] + m_nOffset[nFlag];
2393 nFlag++;
2394 }
2395 }
2396 }
2397}
2398
2399
2401{
2402 CIccApplyCLUT* rv = new CIccApplyCLUT();
2403
2404 if (!rv)
2405 return NULL;
2406
2407 if (!rv->Init(m_nInput, m_nNodes)) {
2408 delete rv;
2409 return NULL;
2410 }
2411
2412 return rv;
2413}
2414
2415/**
2416******************************************************************************
2417* Name: CIccCLUT::Interp1d
2418*
2419* Purpose: One dimensional interpolation function
2420*
2421* Args:
2422* Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2423*******************************************************************************
2424*/
2425void CIccCLUT::Interp1d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2426{
2427 icUInt8Number mx = m_MaxGridPoint[0];
2428
2429 icFloatNumber x = UnitClip(srcPixel[0]) * mx;
2430
2432
2433 icFloatNumber u = x - ix;
2434
2435 if (ix==mx) {
2436 ix--;
2437 u = 1.0;
2438 }
2439
2440 icFloatNumber nu = (icFloatNumber)(1.0 - u);
2441
2442 int i;
2443 icFloatNumber *p = &m_pData[ix*n001];
2444
2445 //Normalize grid units
2446 icFloatNumber dF0, dF1, pv;
2447
2448 dF0 = nu;
2449 dF1 = u;
2450
2451 for (i=0; i<m_nOutput; i++, p++) {
2452 pv = p[n000]*dF0 + p[n001]*dF1;
2453
2454 destPixel[i] = pv;
2455 }
2456}
2457
2458
2459/**
2460******************************************************************************
2461* Name: CIccCLUT::Interp2d
2462*
2463* Purpose: Two dimensional interpolation function
2464*
2465* Args:
2466* Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2467*******************************************************************************
2468*/
2469void CIccCLUT::Interp2d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2470{
2471 icUInt8Number mx = m_MaxGridPoint[0];
2472 icUInt8Number my = m_MaxGridPoint[1];
2473
2474 icFloatNumber x = UnitClip(srcPixel[0]) * mx;
2475 icFloatNumber y = UnitClip(srcPixel[1]) * my;
2476
2479
2480 icFloatNumber u = x - ix;
2481 icFloatNumber t = y - iy;
2482
2483 if (ix==mx) {
2484 ix--;
2485 u = 1.0f;
2486 }
2487 if (iy==my) {
2488 iy--;
2489 t = 1.0f;
2490 }
2491
2492 icFloatNumber nt = 1.0f - t;
2493 icFloatNumber nu = 1.0f - u;
2494
2495 int i;
2496 icFloatNumber *p = &m_pData[ix*n001 + iy*n010];
2497
2498 //Normalize grid units
2499 icFloatNumber dF0, dF1, dF2, dF3, pv;
2500
2501 dF0 = nt* nu;
2502 dF1 = nt* u;
2503 dF2 = t* nu;
2504 dF3 = t* u;
2505
2506 for (i=0; i<m_nOutput; i++, p++) {
2507 pv = p[n000]*dF0 + p[n001]*dF1 + p[n010]*dF2 + p[n011]*dF3;
2508
2509 destPixel[i] = pv;
2510 }
2511}
2512
2513
2514/**
2515 ******************************************************************************
2516 * Name: CIccCLUT::Interp3dTetra
2517 *
2518 * Purpose: Tetrahedral interpolation function
2519 *
2520 * Args:
2521 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2522 *******************************************************************************
2523 */
2524void CIccCLUT::Interp3dTetra(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2525{
2526 icUInt8Number mx = m_MaxGridPoint[0];
2527 icUInt8Number my = m_MaxGridPoint[1];
2528 icUInt8Number mz = m_MaxGridPoint[2];
2529
2530 icFloatNumber x = UnitClip(srcPixel[0]) * mx;
2531 icFloatNumber y = UnitClip(srcPixel[1]) * my;
2532 icFloatNumber z = UnitClip(srcPixel[2]) * mz;
2533
2537
2538 icFloatNumber v = x - ix;
2539 icFloatNumber u = y - iy;
2540 icFloatNumber t = z - iz;
2541
2542 if (ix==mx) {
2543 ix--;
2544 v = 1.0f;
2545 }
2546 if (iy==my) {
2547 iy--;
2548 u = 1.0f;
2549 }
2550 if (iz==mz) {
2551 iz--;
2552 t = 1.0f;
2553 }
2554
2555 int i;
2556 icFloatNumber *p = &m_pData[ix*n001 + iy*n010 + iz*n100];
2557
2558 //Normalize grid units
2559
2560 for (i=0; i<m_nOutput; i++, p++) {
2561 if (t<u) {
2562 if (t>v) {
2563 destPixel[i] = (p[n000] + t*(p[n110]-p[n010]) +
2564 u*(p[n010]-p[n000]) +
2565 v*(p[n111]-p[n110]));
2566 }
2567 else if (u<v) {
2568 destPixel[i] = (p[n000] + t*(p[n111]-p[n011]) +
2569 u*(p[n011]-p[n001]) +
2570 v*(p[n001]-p[n000]));
2571 }
2572 else {
2573 destPixel[i] = (p[n000] + t*(p[n111]-p[n011]) +
2574 u*(p[n010]-p[n000]) +
2575 v*(p[n011]-p[n010]));
2576 }
2577 }
2578 else {
2579 if (t<v) {
2580 destPixel[i] = (p[n000] + t*(p[n101]-p[n001]) +
2581 u*(p[n111]-p[n101]) +
2582 v*(p[n001]-p[n000]));
2583 }
2584 else if (u<v) {
2585 destPixel[i] = (p[n000] + t*(p[n100]-p[n000]) +
2586 u*(p[n111]-p[n101]) +
2587 v*(p[n101]-p[n100]));
2588 }
2589 else {
2590 destPixel[i] = (p[n000] + t*(p[n100]-p[n000]) +
2591 u*(p[n110]-p[n100]) +
2592 v*(p[n111]-p[n110]));
2593 }
2594 }
2595 }
2596}
2597
2598
2599
2600/**
2601 ******************************************************************************
2602 * Name: CIccCLUT::Interp3d
2603 *
2604 * Purpose: Three dimensional interpolation function
2605 *
2606 * Args:
2607 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2608 *******************************************************************************
2609 */
2610void CIccCLUT::Interp3d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2611{
2612 icUInt8Number mx = m_MaxGridPoint[0];
2613 icUInt8Number my = m_MaxGridPoint[1];
2614 icUInt8Number mz = m_MaxGridPoint[2];
2615
2616 icFloatNumber x = UnitClip(srcPixel[0]) * mx;
2617 icFloatNumber y = UnitClip(srcPixel[1]) * my;
2618 icFloatNumber z = UnitClip(srcPixel[2]) * mz;
2619
2623
2624 icFloatNumber u = x - ix;
2625 icFloatNumber t = y - iy;
2626 icFloatNumber s = z - iz;
2627
2628 if (ix==mx) {
2629 ix--;
2630 u = 1.0f;
2631 }
2632 if (iy==my) {
2633 iy--;
2634 t = 1.0f;
2635 }
2636 if (iz==mz) {
2637 iz--;
2638 s = 1.0f;
2639 }
2640
2641 icFloatNumber ns = 1.0f - s;
2642 icFloatNumber nt = 1.0f - t;
2643 icFloatNumber nu = 1.0f - u;
2644
2645 int i;
2646 icFloatNumber *p = &m_pData[ix*n001 + iy*n010 + iz*n100];
2647
2648 //Normalize grid units
2649 icFloatNumber dF0, dF1, dF2, dF3, dF4, dF5, dF6, dF7, pv;
2650
2651 dF0 = ns* nt* nu;
2652 dF1 = ns* nt* u;
2653 dF2 = ns* t* nu;
2654 dF3 = ns* t* u;
2655 dF4 = s* nt* nu;
2656 dF5 = s* nt* u;
2657 dF6 = s* t* nu;
2658 dF7 = s* t* u;
2659
2660 for (i=0; i<m_nOutput; i++, p++) {
2661 pv = p[n000]*dF0 + p[n001]*dF1 + p[n010]*dF2 + p[n011]*dF3 +
2662 p[n100]*dF4 + p[n101]*dF5 + p[n110]*dF6 + p[n111]*dF7;
2663
2664 destPixel[i] = pv;
2665 }
2666}
2667
2668
2669
2670/**
2671 ******************************************************************************
2672 * Name: CIccCLUT::Interp4d
2673 *
2674 * Purpose: Four dimensional interpolation function
2675 *
2676 * Args:
2677 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2678 *******************************************************************************
2679 */
2680void CIccCLUT::Interp4d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2681{
2682 icUInt8Number mw = m_MaxGridPoint[0];
2683 icUInt8Number mx = m_MaxGridPoint[1];
2684 icUInt8Number my = m_MaxGridPoint[2];
2685 icUInt8Number mz = m_MaxGridPoint[3];
2686
2687 icFloatNumber w = UnitClip(srcPixel[0]) * mw;
2688 icFloatNumber x = UnitClip(srcPixel[1]) * mx;
2689 icFloatNumber y = UnitClip(srcPixel[2]) * my;
2690 icFloatNumber z = UnitClip(srcPixel[3]) * mz;
2691
2696
2697 icFloatNumber v = w - iw;
2698 icFloatNumber u = x - ix;
2699 icFloatNumber t = y - iy;
2700 icFloatNumber s = z - iz;
2701
2702 if (iw==mw) {
2703 iw--;
2704 v = 1.0f;
2705 }
2706 if (ix==mx) {
2707 ix--;
2708 u = 1.0f;
2709 }
2710 if (iy==my) {
2711 iy--;
2712 t = 1.0f;
2713 }
2714 if (iz==mz) {
2715 iz--;
2716 s = 1.0f;
2717 }
2718
2719 icFloatNumber ns = 1.0f - s;
2720 icFloatNumber nt = 1.0f - t;
2721 icFloatNumber nu = 1.0f - u;
2722 icFloatNumber nv = 1.0f - v;
2723
2724 int i, j;
2725 icFloatNumber *p = &m_pData[iw*n001 + ix*n010 + iy*n100 + iz*n1000];
2726
2727 //Normalize grid units
2728 icFloatNumber dF[16], pv;
2729
2730 dF[ 0] = ns* nt* nu* nv;
2731 dF[ 1] = ns* nt* nu* v;
2732 dF[ 2] = ns* nt* u* nv;
2733 dF[ 3] = ns* nt* u* v;
2734 dF[ 4] = ns* t* nu* nv;
2735 dF[ 5] = ns* t* nu* v;
2736 dF[ 6] = ns* t* u* nv;
2737 dF[ 7] = ns* t* u* v;
2738 dF[ 8] = s* nt* nu* nv;
2739 dF[ 9] = s* nt* nu* v;
2740 dF[10] = s* nt* u* nv;
2741 dF[11] = s* nt* u* v;
2742 dF[12] = s* t* nu* nv;
2743 dF[13] = s* t* nu* v;
2744 dF[14] = s* t* u* nv;
2745 dF[15] = s* t* u* v;
2746
2747 for (i=0; i<m_nOutput; i++, p++) {
2748 for (pv=0, j=0; j<16; j++)
2749 pv += p[m_nOffset[j]] * dF[j];
2750
2751 destPixel[i] = pv;
2752 }
2753}
2754
2755
2756/**
2757 ******************************************************************************
2758 * Name: CIccCLUT::Interp5d
2759 *
2760 * Purpose: Five dimensional interpolation function
2761 *
2762 * Args:
2763 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2764 *******************************************************************************
2765 */
2766void CIccCLUT::Interp5d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2767{
2768 icUInt8Number m0 = m_MaxGridPoint[0];
2769 icUInt8Number m1 = m_MaxGridPoint[1];
2770 icUInt8Number m2 = m_MaxGridPoint[2];
2771 icUInt8Number m3 = m_MaxGridPoint[3];
2772 icUInt8Number m4 = m_MaxGridPoint[4];
2773
2774 icFloatNumber g0 = UnitClip(srcPixel[0]) * m0;
2775 icFloatNumber g1 = UnitClip(srcPixel[1]) * m1;
2776 icFloatNumber g2 = UnitClip(srcPixel[2]) * m2;
2777 icFloatNumber g3 = UnitClip(srcPixel[3]) * m3;
2778 icFloatNumber g4 = UnitClip(srcPixel[4]) * m4;
2779
2785
2786 icFloatNumber s4 = g0 - ig0;
2787 icFloatNumber s3 = g1 - ig1;
2788 icFloatNumber s2 = g2 - ig2;
2789 icFloatNumber s1 = g3 - ig3;
2790 icFloatNumber s0 = g4 - ig4;
2791
2792 if (ig0==m0) {
2793 ig0--;
2794 s4 = 1.0f;
2795 }
2796 if (ig1==m1) {
2797 ig1--;
2798 s3 = 1.0f;
2799 }
2800 if (ig2==m2) {
2801 ig2--;
2802 s2 = 1.0f;
2803 }
2804 if (ig3==m3) {
2805 ig3--;
2806 s1 = 1.0f;
2807 }
2808 if (ig4==m4) {
2809 ig4--;
2810 s0 = 1.0f;
2811 }
2812
2813 icFloatNumber ns0 = 1.0f - s0;
2814 icFloatNumber ns1 = 1.0f - s1;
2815 icFloatNumber ns2 = 1.0f - s2;
2816 icFloatNumber ns3 = 1.0f - s3;
2817 icFloatNumber ns4 = 1.0f - s4;
2818
2819 int i, j;
2820 icFloatNumber *p = &m_pData[ig0*n001 + ig1*n010 + ig2*n100 + ig3*n1000 + ig4*n10000];
2821
2822 //Normalize grid units
2823 icFloatNumber dF[32], pv;
2824
2825 dF[ 0] = ns0 * ns1 * ns2 * ns3 * ns4;
2826 dF[ 1] = ns0 * ns1 * ns2 * ns3 * s4;
2827 dF[ 2] = ns0 * ns1 * ns2 * s3 * ns4;
2828 dF[ 3] = ns0 * ns1 * ns2 * s3 * s4;
2829 dF[ 4] = ns0 * ns1 * s2 * ns3 * ns4;
2830 dF[ 5] = ns0 * ns1 * s2 * ns3 * s4;
2831 dF[ 6] = ns0 * ns1 * s2 * s3 * ns4;
2832 dF[ 7] = ns0 * ns1 * s2 * s3 * s4;
2833 dF[ 8] = ns0 * s1 * ns2 * ns3 * ns4;
2834 dF[ 9] = ns0 * s1 * ns2 * ns3 * s4;
2835 dF[10] = ns0 * s1 * ns2 * s3 * ns4;
2836 dF[11] = ns0 * s1 * ns2 * s3 * s4;
2837 dF[12] = ns0 * s1 * s2 * ns3 * ns4;
2838 dF[13] = ns0 * s1 * s2 * ns3 * s4;
2839 dF[14] = ns0 * s1 * s2 * s3 * ns4;
2840 dF[15] = ns0 * s1 * s2 * s3 * s4;
2841 dF[16] = s0 * ns1 * ns2 * ns3 * ns4;
2842 dF[17] = s0 * ns1 * ns2 * ns3 * s4;
2843 dF[18] = s0 * ns1 * ns2 * s3 * ns4;
2844 dF[19] = s0 * ns1 * ns2 * s3 * s4;
2845 dF[20] = s0 * ns1 * s2 * ns3 * ns4;
2846 dF[21] = s0 * ns1 * s2 * ns3 * s4;
2847 dF[22] = s0 * ns1 * s2 * s3 * ns4;
2848 dF[23] = s0 * ns1 * s2 * s3 * s4;
2849 dF[24] = s0 * s1 * ns2 * ns3 * ns4;
2850 dF[25] = s0 * s1 * ns2 * ns3 * s4;
2851 dF[26] = s0 * s1 * ns2 * s3 * ns4;
2852 dF[27] = s0 * s1 * ns2 * s3 * s4;
2853 dF[28] = s0 * s1 * s2 * ns3 * ns4;
2854 dF[29] = s0 * s1 * s2 * ns3 * s4;
2855 dF[30] = s0 * s1 * s2 * s3 * ns4;
2856 dF[31] = s0 * s1 * s2 * s3 * s4;
2857
2858 for (i=0; i<m_nOutput; i++, p++) {
2859 for (pv=0.0, j=0; j<32; j++)
2860 pv += p[m_nOffset[j]] * dF[j];
2861
2862 destPixel[i] = pv;
2863 }
2864}
2865
2866
2867
2868/**
2869 ******************************************************************************
2870 * Name: CIccCLUT::Interp6d
2871 *
2872 * Purpose: Six dimensional interpolation function
2873 *
2874 * Args:
2875 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2876 *******************************************************************************
2877 */
2878void CIccCLUT::Interp6d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2879{
2880 icUInt8Number m0 = m_MaxGridPoint[0];
2881 icUInt8Number m1 = m_MaxGridPoint[1];
2882 icUInt8Number m2 = m_MaxGridPoint[2];
2883 icUInt8Number m3 = m_MaxGridPoint[3];
2884 icUInt8Number m4 = m_MaxGridPoint[4];
2885 icUInt8Number m5 = m_MaxGridPoint[5];
2886
2887 icFloatNumber g0 = UnitClip(srcPixel[0]) * m0;
2888 icFloatNumber g1 = UnitClip(srcPixel[1]) * m1;
2889 icFloatNumber g2 = UnitClip(srcPixel[2]) * m2;
2890 icFloatNumber g3 = UnitClip(srcPixel[3]) * m3;
2891 icFloatNumber g4 = UnitClip(srcPixel[4]) * m4;
2892 icFloatNumber g5 = UnitClip(srcPixel[5]) * m5;
2893
2900
2901 icFloatNumber s5 = g0 - ig0;
2902 icFloatNumber s4 = g1 - ig1;
2903 icFloatNumber s3 = g2 - ig2;
2904 icFloatNumber s2 = g3 - ig3;
2905 icFloatNumber s1 = g4 - ig4;
2906 icFloatNumber s0 = g5 - ig5;
2907
2908 if (ig0==m0) {
2909 ig0--;
2910 s5 = 1.0f;
2911 }
2912 if (ig1==m1) {
2913 ig1--;
2914 s4 = 1.0f;
2915 }
2916 if (ig2==m2) {
2917 ig2--;
2918 s3 = 1.0f;
2919 }
2920 if (ig3==m3) {
2921 ig3--;
2922 s2 = 1.0f;
2923 }
2924 if (ig4==m4) {
2925 ig4--;
2926 s1 = 1.0f;
2927 }
2928 if (ig5==m5) {
2929 ig5--;
2930 s0 = 1.0f;
2931 }
2932
2933 icFloatNumber ns0 = 1.0f - s0;
2934 icFloatNumber ns1 = 1.0f - s1;
2935 icFloatNumber ns2 = 1.0f - s2;
2936 icFloatNumber ns3 = 1.0f - s3;
2937 icFloatNumber ns4 = 1.0f - s4;
2938 icFloatNumber ns5 = 1.0f - s5;
2939
2940 int i, j;
2941 icFloatNumber *p = &m_pData[ig0*n001 + ig1*n010 + ig2*n100 + ig3*n1000 + ig4*n10000 + ig5*n100000];
2942
2943 //Normalize grid units
2944 icFloatNumber dF[64], pv;
2945
2946 dF[ 0] = ns0 * ns1 * ns2 * ns3 * ns4 * ns5;
2947 dF[ 1] = ns0 * ns1 * ns2 * ns3 * ns4 * s5;
2948 dF[ 2] = ns0 * ns1 * ns2 * ns3 * s4 * ns5;
2949 dF[ 3] = ns0 * ns1 * ns2 * ns3 * s4 * s5;
2950 dF[ 4] = ns0 * ns1 * ns2 * s3 * ns4 * ns5;
2951 dF[ 5] = ns0 * ns1 * ns2 * s3 * ns4 * s5;
2952 dF[ 6] = ns0 * ns1 * ns2 * s3 * s4 * ns5;
2953 dF[ 7] = ns0 * ns1 * ns2 * s3 * s4 * s5;
2954 dF[ 8] = ns0 * ns1 * s2 * ns3 * ns4 * ns5;
2955 dF[ 9] = ns0 * ns1 * s2 * ns3 * ns4 * s5;
2956 dF[10] = ns0 * ns1 * s2 * ns3 * s4 * ns5;
2957 dF[11] = ns0 * ns1 * s2 * ns3 * s4 * s5;
2958 dF[12] = ns0 * ns1 * s2 * s3 * ns4 * ns5;
2959 dF[13] = ns0 * ns1 * s2 * s3 * ns4 * s5;
2960 dF[14] = ns0 * ns1 * s2 * s3 * s4 * ns5;
2961 dF[15] = ns0 * ns1 * s2 * s3 * s4 * s5;
2962 dF[16] = ns0 * s1 * ns2 * ns3 * ns4 * ns5;
2963 dF[17] = ns0 * s1 * ns2 * ns3 * ns4 * s5;
2964 dF[18] = ns0 * s1 * ns2 * ns3 * s4 * ns5;
2965 dF[19] = ns0 * s1 * ns2 * ns3 * s4 * s5;
2966 dF[20] = ns0 * s1 * ns2 * s3 * ns4 * ns5;
2967 dF[21] = ns0 * s1 * ns2 * s3 * ns4 * s5;
2968 dF[22] = ns0 * s1 * ns2 * s3 * s4 * ns5;
2969 dF[23] = ns0 * s1 * ns2 * s3 * s4 * s5;
2970 dF[24] = ns0 * s1 * s2 * ns3 * ns4 * ns5;
2971 dF[25] = ns0 * s1 * s2 * ns3 * ns4 * s5;
2972 dF[26] = ns0 * s1 * s2 * ns3 * s4 * ns5;
2973 dF[27] = ns0 * s1 * s2 * ns3 * s4 * s5;
2974 dF[28] = ns0 * s1 * s2 * s3 * ns4 * ns5;
2975 dF[29] = ns0 * s1 * s2 * s3 * ns4 * s5;
2976 dF[30] = ns0 * s1 * s2 * s3 * s4 * ns5;
2977 dF[31] = ns0 * s1 * s2 * s3 * s4 * s5;
2978 dF[32] = s0 * ns1 * ns2 * ns3 * ns4 * ns5;
2979 dF[33] = s0 * ns1 * ns2 * ns3 * ns4 * s5;
2980 dF[34] = s0 * ns1 * ns2 * ns3 * s4 * ns5;
2981 dF[35] = s0 * ns1 * ns2 * ns3 * s4 * s5;
2982 dF[36] = s0 * ns1 * ns2 * s3 * ns4 * ns5;
2983 dF[37] = s0 * ns1 * ns2 * s3 * ns4 * s5;
2984 dF[38] = s0 * ns1 * ns2 * s3 * s4 * ns5;
2985 dF[39] = s0 * ns1 * ns2 * s3 * s4 * s5;
2986 dF[40] = s0 * ns1 * s2 * ns3 * ns4 * ns5;
2987 dF[41] = s0 * ns1 * s2 * ns3 * ns4 * s5;
2988 dF[42] = s0 * ns1 * s2 * ns3 * s4 * ns5;
2989 dF[43] = s0 * ns1 * s2 * ns3 * s4 * s5;
2990 dF[44] = s0 * ns1 * s2 * s3 * ns4 * ns5;
2991 dF[45] = s0 * ns1 * s2 * s3 * ns4 * s5;
2992 dF[46] = s0 * ns1 * s2 * s3 * s4 * ns5;
2993 dF[47] = s0 * ns1 * s2 * s3 * s4 * s5;
2994 dF[48] = s0 * s1 * ns2 * ns3 * ns4 * ns5;
2995 dF[49] = s0 * s1 * ns2 * ns3 * ns4 * s5;
2996 dF[50] = s0 * s1 * ns2 * ns3 * s4 * ns5;
2997 dF[51] = s0 * s1 * ns2 * ns3 * s4 * s5;
2998 dF[52] = s0 * s1 * ns2 * s3 * ns4 * ns5;
2999 dF[53] = s0 * s1 * ns2 * s3 * ns4 * s5;
3000 dF[54] = s0 * s1 * ns2 * s3 * s4 * ns5;
3001 dF[55] = s0 * s1 * ns2 * s3 * s4 * s5;
3002 dF[56] = s0 * s1 * s2 * ns3 * ns4 * ns5;
3003 dF[57] = s0 * s1 * s2 * ns3 * ns4 * s5;
3004 dF[58] = s0 * s1 * s2 * ns3 * s4 * ns5;
3005 dF[59] = s0 * s1 * s2 * ns3 * s4 * s5;
3006 dF[60] = s0 * s1 * s2 * s3 * ns4 * ns5;
3007 dF[61] = s0 * s1 * s2 * s3 * ns4 * s5;
3008 dF[62] = s0 * s1 * s2 * s3 * s4 * ns5;
3009 dF[63] = s0 * s1 * s2 * s3 * s4 * s5;
3010
3011 for (i=0; i<m_nOutput; i++, p++) {
3012 for (pv=0, j=0; j<64; j++)
3013 pv += p[m_nOffset[j]] * dF[j];
3014
3015 destPixel[i] = pv;
3016 }
3017}
3018
3019
3020/**
3021 ******************************************************************************
3022 * Name: CIccCLUT::InterpND
3023 *
3024 * Purpose: Generic N-dimensional interpolation function
3025 *
3026 * Args:
3027 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
3028 *******************************************************************************
3029 */
3030void CIccCLUT::InterpND(icFloatNumber *destPixel, const icFloatNumber *srcPixel, CIccApplyCLUT *pApply) const
3031{
3032 icUInt32Number i,j, index = 0;
3033 icFloatNumber* df = pApply->m_df;
3034 icFloatNumber* g = pApply->m_g;
3035 icFloatNumber* s = pApply->m_s;
3036 icUInt32Number* ig = pApply->m_ig;
3037
3038 for (i=0; i<m_nInput; i++) {
3039 g[i] = UnitClip(srcPixel[i]) * m_MaxGridPoint[i];
3040 ig[i] = (icUInt32Number)g[i];
3041 s[m_nInput-1-i] = g[i] - ig[i];
3042 if (ig[i]==m_MaxGridPoint[i]) {
3043 ig[i]--;
3044 s[m_nInput-1-i] = 1.0;
3045 }
3046 index += ig[i]*m_DimSize[i];
3047 }
3048
3049 icFloatNumber *p = &m_pData[index];
3050 icFloatNumber temp[2];
3051 icFloatNumber pv;
3052 int nFlag = 0;
3053
3054 for (i=0; i<m_nNodes; i++) {
3055 df[i] = 1.0f;
3056 }
3057
3058
3059 for (i=0; i<m_nInput; i++) {
3060 temp[0] = 1.0f - s[i];
3061 temp[1] = s[i];
3062 index = m_nPower[i];
3063 for (j=0; j<m_nNodes; j++) {
3064 df[j] *= temp[nFlag];
3065 if ((j+1)%index == 0)
3066 nFlag = !nFlag;
3067 }
3068 nFlag = 0;
3069 }
3070
3071 for (i=0; i<m_nOutput; i++, p++) {
3072 for (pv=0, j=0; j<m_nNodes; j++)
3073 pv += p[m_nOffset[j]] * df[j];
3074
3075 destPixel[i] = pv;
3076 }
3077
3078}
3079
3080
3081/**
3082******************************************************************************
3083* Name: CIccCLUT::Validate
3084*
3085* Purpose: Check tag data validity.
3086*
3087* Args:
3088* sig = signature of tag being validated,
3089* sReport = String to add report information to
3090*
3091* Return:
3092* icValidateStatusOK if valid, or other error status.
3093******************************************************************************
3094*/
3095icValidateStatus CIccCLUT::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
3096{
3099
3100 CIccInfo Info;
3101 std::string sSigPathName = Info.GetSigPathName(sigPath);
3102 if (m_nReserved2[0]!=0 || m_nReserved2[1]!=0 || m_nReserved2[2]!=0) {
3103 sReport += icMsgValidateNonCompliant;
3104 sReport += sSigPathName;
3105 sReport += " - Reserved Value must be zero.\n";
3106
3108 }
3109
3111 char temp[256];
3112 for (int i=0; i<m_nInput; i++) {
3113 if (m_GridPoints[i]<2) {
3114 sReport += icMsgValidateCriticalError;
3115 sReport += sSigPathName;
3116 sprintf(temp, " - CLUT: At least 2 grid points should be present in dimension %u.\n",i );
3117 sReport += temp;
3119 }
3120 }
3121 }
3122
3123 return rv;
3124}
3125
3126
3127/**
3128 ****************************************************************************
3129 * Name: CIccMBB::CIccMBB
3130 *
3131 * Purpose: Constructor
3132 *
3133 *****************************************************************************
3134 */
3136{
3137 m_nInput = 0;
3138 m_nOutput = 0;
3139
3140 m_CurvesA = NULL;
3141 m_CLUT = NULL;
3142 m_Matrix = NULL;
3143 m_CurvesM = NULL;
3144 m_CurvesB = NULL;
3145
3146 m_csInput = icSigUnknownData;
3147 m_csOutput = icSigUnknownData;
3148
3149 m_bInputMatrix = true;
3150 m_bUseMCurvesAsBCurves = false;
3151}
3152
3153
3154/**
3155 ****************************************************************************
3156 * Name: CIccMBB::CIccMBB
3157 *
3158 * Purpose: Copy Constructor
3159 *
3160 * Args:
3161 * IMBB = The CIccMBB object to be copied
3162 *****************************************************************************
3163 */
3165{
3166 icUInt8Number nCurves;
3167 int i;
3168
3169 m_bInputMatrix = IMBB.m_bInputMatrix;
3170 m_bUseMCurvesAsBCurves = IMBB.m_bUseMCurvesAsBCurves;
3171 m_nInput = IMBB.m_nInput;
3172 m_nOutput = IMBB.m_nOutput;
3173 m_csInput = IMBB.m_csInput;
3174 m_csOutput = IMBB.m_csOutput;
3175
3176 if (IMBB.m_CLUT) {
3177 m_CLUT = new CIccCLUT(*IMBB.m_CLUT);
3178 }
3179 else
3180 m_CLUT = NULL;
3181
3182 if (IMBB.m_CurvesA) {
3183 nCurves = !IsInputB() ? m_nInput : m_nOutput;
3184
3185 m_CurvesA = new LPIccCurve[nCurves];
3186 for (i=0; i<nCurves; i++)
3187 m_CurvesA[i] = (CIccTagCurve*)IMBB.m_CurvesA[i]->NewCopy();
3188 }
3189 else {
3190 m_CurvesA = NULL;
3191 }
3192
3193 if (IMBB.m_CurvesM) {
3194 nCurves = IsInputMatrix() ? m_nInput : m_nOutput;
3195
3196 m_CurvesM = new LPIccCurve[nCurves];
3197 for (i=0; i<nCurves; i++)
3198 m_CurvesM[i] = (CIccTagCurve*)IMBB.m_CurvesM[i]->NewCopy();
3199 }
3200 else {
3201 m_CurvesM = NULL;
3202 }
3203
3204 if (IMBB.m_CurvesB) {
3205 nCurves = IsInputB() ? m_nInput : m_nOutput;
3206
3207 m_CurvesB = new LPIccCurve[nCurves];
3208 for (i=0; i<nCurves; i++)
3209 m_CurvesB[i] = (CIccTagCurve*)IMBB.m_CurvesB[i]->NewCopy();
3210 }
3211 else {
3212 m_CurvesB = NULL;
3213 }
3214
3215 if (IMBB.m_Matrix) {
3216 m_Matrix = new CIccMatrix(*IMBB.m_Matrix);
3217 }
3218 else {
3219 m_Matrix = NULL;
3220 }
3221}
3222
3223
3224/**
3225 ****************************************************************************
3226 * Name: CIccMBB::operator=
3227 *
3228 * Purpose: Copy Operator
3229 *
3230 * Args:
3231 * IMBB = The CIccMBB object to be copied
3232 *****************************************************************************
3233 */
3235{
3236 if (&IMBB == this)
3237 return *this;
3238
3239 Cleanup();
3240
3241 icUInt8Number nCurves;
3242 int i;
3243
3244 m_bInputMatrix = IMBB.m_bInputMatrix;
3245 m_bUseMCurvesAsBCurves = IMBB.m_bUseMCurvesAsBCurves;
3246 m_nInput = IMBB.m_nInput;
3247 m_nOutput = IMBB.m_nOutput;
3248 m_csInput = IMBB.m_csInput;
3249 m_csOutput = IMBB.m_csOutput;
3250
3251 if (IMBB.m_CLUT) {
3252 m_CLUT = new CIccCLUT(*IMBB.m_CLUT);
3253 }
3254 else
3255 m_CLUT = NULL;
3256
3257 if (IMBB.m_CurvesA) {
3258 nCurves = !IsInputB() ? m_nInput : m_nOutput;
3259
3260 m_CurvesA = new LPIccCurve[nCurves];
3261 for (i=0; i<nCurves; i++)
3262 m_CurvesA[i] = (CIccTagCurve*)IMBB.m_CurvesA[i]->NewCopy();
3263 }
3264 else {
3265 m_CurvesA = NULL;
3266 }
3267
3268 if (IMBB.m_CurvesM) {
3269 nCurves = IsInputMatrix() ? m_nInput : m_nOutput;
3270
3271 m_CurvesM = new LPIccCurve[nCurves];
3272 for (i=0; i<nCurves; i++)
3273 m_CurvesM[i] = (CIccTagCurve*)IMBB.m_CurvesM[i]->NewCopy();
3274 }
3275 else {
3276 m_CurvesM = NULL;
3277 }
3278
3279 if (IMBB.m_CurvesB) {
3280 nCurves = IsInputB() ? m_nInput : m_nOutput;
3281
3282 m_CurvesB = new LPIccCurve[nCurves];
3283 for (i=0; i<nCurves; i++)
3284 m_CurvesB[i] = (CIccTagCurve*)IMBB.m_CurvesB[i]->NewCopy();
3285 }
3286 else {
3287 m_CurvesB = NULL;
3288 }
3289
3290 if (IMBB.m_Matrix) {
3291 m_Matrix = new CIccMatrix(*IMBB.m_Matrix);
3292 }
3293 else {
3294 m_Matrix = NULL;
3295 }
3296
3297 return *this;
3298}
3299
3300
3301/**
3302 ****************************************************************************
3303 * Name: CIccMBB::~CIccMBB
3304 *
3305 * Purpose: Destructor
3306 *
3307 *****************************************************************************
3308 */
3310{
3311 Cleanup();
3312}
3313
3314/**
3315 ****************************************************************************
3316 * Name: CIccMBB::Cleanup
3317 *
3318 * Purpose: Frees the memory allocated to the object
3319 *
3320 *****************************************************************************
3321 */
3323{
3324 int i;
3325
3326 if (IsInputMatrix()) {
3327 if (m_CurvesB) {
3328 for (i=0; i<m_nInput; i++)
3329 if (m_CurvesB[i])
3330 delete m_CurvesB[i];
3331
3332 delete [] m_CurvesB;
3333 m_CurvesB = NULL;
3334 }
3335
3336 if (m_CurvesM) {
3337 for (i=0; i<m_nInput; i++)
3338 if (m_CurvesM[i])
3339 delete m_CurvesM[i];
3340
3341 delete [] m_CurvesM;
3342 m_CurvesM = NULL;
3343 }
3344
3345
3346 if (m_CurvesA) {
3347 for (i=0; i<m_nOutput; i++)
3348 if (m_CurvesA[i])
3349 delete m_CurvesA[i];
3350
3351 delete [] m_CurvesA;
3352 m_CurvesA = NULL;
3353 }
3354
3355 }
3356 else {
3357 if (m_CurvesA) {
3358 for (i=0; i<m_nInput; i++)
3359 if (m_CurvesA[i])
3360 delete m_CurvesA[i];
3361
3362 delete [] m_CurvesA;
3363 m_CurvesA = NULL;
3364 }
3365
3366 if (m_CurvesM) {
3367 for (i=0; i<m_nOutput; i++)
3368 if (m_CurvesM[i])
3369 delete m_CurvesM[i];
3370
3371 delete [] m_CurvesM;
3372 m_CurvesM = NULL;
3373 }
3374
3375 if (m_CurvesB) {
3376 for (i=0; i<m_nOutput; i++)
3377 if (m_CurvesB[i])
3378 delete m_CurvesB[i];
3379
3380 delete [] m_CurvesB;
3381 m_CurvesB = NULL;
3382 }
3383 }
3384
3385 if (m_Matrix) {
3386 delete m_Matrix;
3387 m_Matrix = NULL;
3388 }
3389
3390 if (m_CLUT) {
3391 delete m_CLUT;
3392 m_CLUT = NULL;
3393 }
3394}
3395
3396/**
3397 ****************************************************************************
3398 * Name: CIccMBB::Init
3399 *
3400 * Purpose: Cleans up any prior memory and Initializes the object.
3401 *
3402 * Args:
3403 * nInputChannels = number of input channels,
3404 * nOutputChannels = number of output channels
3405 *****************************************************************************
3406 */
3407void CIccMBB::Init(icUInt8Number nInputChannels, icUInt8Number nOutputChannels)
3408{
3409 Cleanup();
3410 m_nInput = nInputChannels;
3411 m_nOutput = nOutputChannels;
3412}
3413
3414/**
3415 ****************************************************************************
3416 * Name: CIccMBB::SetColorSpaces
3417 *
3418 * Purpose: Sets the input and output color spaces
3419 *
3420 * Args:
3421 * csInput = input color space signature,
3422 * csOutput = output color space signature
3423 *****************************************************************************
3424 */
3426{
3427 m_csInput = csInput;
3428 m_csOutput = csOutput;
3429}
3430
3431/**
3432 ****************************************************************************
3433 * Name: CIccMBB::Describe
3434 *
3435 * Purpose: Dump data associated with the tag to a string
3436 *
3437 * Args:
3438 * sDescription - string to concatenate tag dump to
3439 *****************************************************************************
3440 */
3441void CIccMBB::Describe(std::string &sDescription, int nVerboseness)
3442{
3443 int i;
3444 icChar buf[128], color[40];
3445
3446
3447 if (IsInputMatrix()) {
3448 if (m_CurvesB && !m_bUseMCurvesAsBCurves) {
3449 for (i=0; i<m_nInput; i++) {
3450 icColorIndexName(color, m_csInput, i, m_nInput, "");
3451 sprintf(buf, "B_Curve_%s", color);
3452 m_CurvesB[i]->DumpLut(sDescription, buf, m_csInput, i, nVerboseness);
3453 }
3454 }
3455
3456 if (m_Matrix)
3457 m_Matrix->DumpLut(sDescription, "Matrix", nVerboseness);
3458
3459 if (m_CurvesM) {
3460 for (i=0; i<m_nInput; i++) {
3461 icColorIndexName(color, m_csInput, i, m_nInput, "");
3462 if (!m_bUseMCurvesAsBCurves)
3463 sprintf(buf, "M_Curve_%s", color);
3464 else
3465 sprintf(buf, "B_Curve_%s", color);
3466 m_CurvesM[i]->DumpLut(sDescription, buf, m_csInput, i, nVerboseness);
3467 }
3468 }
3469
3470 if (m_CLUT)
3471 m_CLUT->DumpLut(sDescription, "CLUT", m_csInput, m_csOutput, nVerboseness, GetType()==icSigLut16Type);
3472
3473 if (m_CurvesA) {
3474 for (i=0; i<m_nOutput; i++) {
3475 icColorIndexName(color, m_csOutput, i, m_nOutput, "");
3476 sprintf(buf, "A_Curve_%s", color);
3477 m_CurvesA[i]->DumpLut(sDescription, buf, m_csOutput, i, nVerboseness);
3478 }
3479 }
3480 }
3481 else {
3482 if (m_CurvesA) {
3483 for (i=0; i<m_nInput; i++) {
3484 icColorIndexName(color, m_csInput, i, m_nInput, "");
3485 sprintf(buf, "A_Curve_%s", color);
3486 m_CurvesA[i]->DumpLut(sDescription, buf, m_csInput, i, nVerboseness);
3487 }
3488 }
3489
3490 if (m_CLUT)
3491 m_CLUT->DumpLut(sDescription, "CLUT", m_csInput, m_csOutput, nVerboseness);
3492
3493 if (m_CurvesM && this->GetType()!=icSigLut8Type) {
3494 for (i=0; i<m_nOutput; i++) {
3495 icColorIndexName(color, m_csOutput, i, m_nOutput, "");
3496 sprintf(buf, "M_Curve_%s", color);
3497 m_CurvesM[i]->DumpLut(sDescription, buf, m_csOutput, i, nVerboseness);
3498 }
3499 }
3500
3501 if (m_Matrix)
3502 m_Matrix->DumpLut(sDescription, "Matrix", nVerboseness);
3503
3504 if (m_CurvesB) {
3505 for (i=0; i<m_nOutput; i++) {
3506 icColorIndexName(color, m_csOutput, i, m_nOutput, "");
3507 sprintf(buf, "B_Curve_%s", color);
3508 m_CurvesB[i]->DumpLut(sDescription, buf, m_csOutput, i, nVerboseness);
3509 }
3510 }
3511 }
3512}
3513
3514
3515/**
3516******************************************************************************
3517* Name: CIccMBB::Validate
3518*
3519* Purpose: Check tag data validity.
3520*
3521* Args:
3522* sig = signature of tag being validated,
3523* sReport = String to add report information to
3524*
3525* Return:
3526* icValidateStatusOK if valid, or other error status.
3527******************************************************************************
3528*/
3529icValidateStatus CIccMBB::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/)
3530{
3531 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
3532
3533 CIccInfo Info;
3534 std::string sSigPathName = Info.GetSigPathName(sigPath);
3536
3537 if (!pProfile) {
3538 sReport += icMsgValidateWarning;
3539 sReport += sSigPathName;
3540 sReport += " - Tag validation incomplete: Pointer to profile unavailable.\n";
3542 return rv;
3543 }
3544 icUInt32Number nInput, nOutput;
3545
3546 //Check # of channels
3547 switch(sig) {
3548 case icSigAToB0Tag:
3549 case icSigAToB1Tag:
3550 case icSigAToB2Tag:
3551 case icSigAToB3Tag:
3552 {
3553 nInput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
3554 if (m_nInput!=nInput) {
3555 sReport += icMsgValidateCriticalError;
3556 sReport += sSigPathName;
3557 sReport += " - Incorrect number of input channels.\n";
3559 }
3560
3561 nOutput = icGetSpaceSamples(pProfile->m_Header.pcs);
3562 if (m_nOutput!=nOutput) {
3563 sReport += icMsgValidateCriticalError;
3564 sReport += sSigPathName;
3565 sReport += " - Incorrect number of output channels.\n";
3567 }
3568
3569 break;
3570 }
3571 case icSigBToA0Tag:
3572 case icSigBToA1Tag:
3573 case icSigBToA2Tag:
3574 case icSigBToA3Tag:
3575 {
3576 nInput = icGetSpaceSamples(pProfile->m_Header.pcs);
3577 if (m_nInput!=nInput) {
3578 sReport += icMsgValidateCriticalError;
3579 sReport += sSigPathName;
3580 sReport += " - Incorrect number of input channels.\n";
3582 }
3583
3584 nOutput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
3585 if (m_nOutput!=nOutput) {
3586 sReport += icMsgValidateCriticalError;
3587 sReport += sSigPathName;
3588 sReport += " - Incorrect number of output channels.\n";
3590 }
3591
3592 break;
3593 }
3594 case icSigHToS0Tag:
3595 case icSigHToS1Tag:
3596 case icSigHToS2Tag:
3597 case icSigHToS3Tag:
3598 {
3599 nInput = icGetSpaceSamples(pProfile->m_Header.pcs);
3600 if (m_nInput != nInput) {
3601 sReport += icMsgValidateCriticalError;
3602 sReport += sSigPathName;
3603 sReport += " - Incorrect number of input channels.\n";
3605 }
3606
3607 nOutput = icGetSpaceSamples(pProfile->m_Header.pcs);
3608 if (m_nOutput != nOutput) {
3609 sReport += icMsgValidateCriticalError;
3610 sReport += sSigPathName;
3611 sReport += " - Incorrect number of output channels.\n";
3613 }
3614
3615 break;
3616 }
3617 case icSigGamutTag:
3618 {
3619 nInput = 1;
3620 if (m_nInput!=nInput) {
3621 sReport += icMsgValidateCriticalError;
3622 sReport += sSigPathName;
3623 sReport += " - Incorrect number of input channels.\n";
3625 }
3626
3627 nOutput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
3628 if (m_nOutput!=nOutput) {
3629 sReport += icMsgValidateCriticalError;
3630 sReport += sSigPathName;
3631 sReport += " - Incorrect number of output channels.\n";
3633 }
3634
3635 break;
3636 }
3637 default:
3638 {
3639 nInput = m_nInput;
3640 nOutput = m_nOutput;
3641 }
3642 }
3643
3644 //CLUT check
3645 if (nInput!=nOutput) {
3646 if (!m_CLUT) {
3647 sReport += icMsgValidateCriticalError;
3648 sReport += sSigPathName;
3649 sReport += " - CLUT must be present.\n";
3651 }
3652 }
3653
3654 if (m_CLUT) {
3655 rv = icMaxStatus(rv, m_CLUT->Validate(sigPath, sReport, pProfile));
3656 }
3657
3658 return rv;
3659}
3660
3661/**
3662 ****************************************************************************
3663 * Name: CIccMBB::NewCurvesA
3664 *
3665 * Purpose: Allocates memory for a new set of A-curves
3666 *
3667 * Return: Pointer to the LPIccCurve object
3668 *****************************************************************************
3669 */
3671{
3672 if (m_CurvesA)
3673 return m_CurvesA;
3674
3675 icUInt8Number nCurves = !IsInputB() ? m_nInput : m_nOutput;
3676
3677 m_CurvesA = new LPIccCurve[nCurves];
3678 memset(m_CurvesA, 0, nCurves * sizeof(LPIccCurve));
3679
3680 return m_CurvesA;
3681}
3682
3683
3684/**
3685 ****************************************************************************
3686 * Name: CIccMBB::NewCurvesM
3687 *
3688 * Purpose: Allocates memory for a new set of M-curves
3689 *
3690 * Return: Pointer to the LPIccCurve object
3691 *****************************************************************************
3692 */
3694{
3695 if (m_CurvesM)
3696 return m_CurvesM;
3697
3698 icUInt8Number nCurves = IsInputMatrix() ? m_nInput : m_nOutput;
3699
3700 m_CurvesM = new LPIccCurve[nCurves];
3701 memset(m_CurvesM, 0, nCurves * sizeof(LPIccCurve));
3702
3703 return m_CurvesM;
3704}
3705
3706/**
3707 ****************************************************************************
3708 * Name: CIccMBB::NewCurvesB
3709 *
3710 * Purpose: Allocates memory for a new set of B-curves
3711 *
3712 * Return: Pointer to the LPIccCurve object
3713 *****************************************************************************
3714 */
3716{
3717 if (m_CurvesB)
3718 return m_CurvesB;
3719
3720 icUInt8Number nCurves = IsInputB() ? m_nInput : m_nOutput;
3721
3722 m_CurvesB = new LPIccCurve[nCurves];
3723 memset(m_CurvesB, 0, nCurves * sizeof(LPIccCurve));
3724
3725 return m_CurvesB;
3726}
3727
3728/**
3729 ****************************************************************************
3730 * Name: CIccMBB::NewMatrix
3731 *
3732 * Purpose: Allocates memory for a new matrix
3733 *
3734 * Return: Pointer to the CIccMatrix object
3735 *****************************************************************************
3736 */
3738{
3739 if (m_Matrix)
3740 return m_Matrix;
3741
3742 m_Matrix = new CIccMatrix;
3743
3744 return m_Matrix;
3745}
3746
3747/**
3748 ****************************************************************************
3749 * Name: CIccMBB::NewCLUT
3750 *
3751 * Purpose: Allocates memory for a new CLUT and initializes it
3752 *
3753 * Args:
3754 * pGridPoints = number of grid points in the CLUT
3755 *
3756 * Return: Pointer to the CIccCLUT object
3757 *****************************************************************************
3758 */
3760{
3761 if (m_CLUT)
3762 return m_CLUT;
3763
3764 m_CLUT = new CIccCLUT(m_nInput, m_nOutput, nPrecision);
3765
3766 m_CLUT->Init(pGridPoints);
3767
3768 return m_CLUT;
3769}
3770
3771/**
3772****************************************************************************
3773* Name: CIccMBB::SetCLUT
3774*
3775* Purpose: Assignes CLUT connection to an initialized new CLUT
3776*
3777* Args:
3778* clut = pointer to a previously allocated CLUT (Onwership is transfered to
3779* CIccMBB object).
3780*
3781* Return: Pointer to the CIccCLUT object or NULL if clut is incompatible with
3782* CIccMBB object. If the clut is incompatible it is deleted.
3783*****************************************************************************
3784*/
3786{
3787 if (clut->GetInputDim() != m_nInput || clut->GetOutputChannels() != m_nOutput) {
3788 delete clut;
3789 return NULL;
3790 }
3791
3792 if (m_CLUT) {
3793 delete m_CLUT;
3794 }
3795
3796 m_CLUT = clut;
3797 return clut;
3798}
3799
3800/**
3801 ****************************************************************************
3802 * Name: CIccMBB::NewCLUT
3803 *
3804 * Purpose: Allocates memory for a new CLUT and initializes it
3805 *
3806 * Args:
3807 * nGridPoints = number of grid points in the CLUT
3808 *
3809 * Return: Pointer to the CIccCLUT object
3810 *****************************************************************************
3811 */
3813{
3814 if (m_CLUT)
3815 return m_CLUT;
3816
3817 m_CLUT = new CIccCLUT(m_nInput, m_nOutput, nPrecision);
3818
3819 m_CLUT->Init(nGridPoints);
3820
3821 return m_CLUT;
3822}
3823
3824
3825/**
3826 ****************************************************************************
3827 * Name: CIccTagLutAtoB::CIccTagLutAtoB
3828 *
3829 * Purpose: Constructor
3830 *
3831 *****************************************************************************
3832 */
3834{
3835 m_bInputMatrix = false;
3836 m_nReservedWord = 0;
3837}
3838
3839
3840/**
3841 ****************************************************************************
3842 * Name: CIccTagLutAtoB::CIccTagLutAtoB
3843 *
3844 * Purpose: Copy Constructor
3845 *
3846 * Args:
3847 * ITLA2B = The CIccTagLutAtoB object to be copied
3848 *****************************************************************************
3849 */
3851{
3852 m_nReservedWord = 0;
3853}
3854
3855
3856/**
3857 ****************************************************************************
3858 * Name: CIccTagLutAtoB::operator=
3859 *
3860 * Purpose: Copy Operator
3861 *
3862 * Args:
3863 * ITLA2B = The CIccTagLutAtoB object to be copied
3864 *****************************************************************************
3865 */
3867{
3868 if (&ITLA2B == this)
3869 return *this;
3870
3871 CIccMBB::operator=(ITLA2B);
3872
3873 return *this;
3874}
3875
3876
3877/**
3878 ****************************************************************************
3879 * Name: CIccTagLutAtoB::~CIccTagLutAtoB
3880 *
3881 * Purpose: Destructor
3882 *
3883 *****************************************************************************
3884 */
3888
3889
3890/**
3891 ****************************************************************************
3892 * Name: CIccTagLutAtoB::Read
3893 *
3894 * Purpose: Read in the tag contents into a data block
3895 *
3896 * Args:
3897 * size - # of bytes in tag,
3898 * pIO - IO object to read tag from
3899 *
3900 * Return:
3901 * true = successful, false = failure
3902 *****************************************************************************
3903 */
3905{
3907 icUInt32Number Offset[5], nStart, nEnd, nPos;
3908 icUInt8Number nCurves, i;
3909
3910 if (size<8*sizeof(icUInt32Number) || !pIO) {
3911 return false;
3912 }
3913
3914 nStart = pIO->Tell();
3915 nEnd = nStart + size;
3916
3917 if (!pIO->Read32(&sig) ||
3918 !pIO->Read32(&m_nReserved) ||
3919 !pIO->Read8(&m_nInput) ||
3920 !pIO->Read8(&m_nOutput) ||
3921 !pIO->Read16(&m_nReservedWord) ||
3922 pIO->Read32(Offset, 5)!=5)
3923 return false;
3924
3925 if (sig!=GetType())
3926 return false;
3927
3928 //B Curves
3929 if (Offset[0]) {
3930 nCurves = IsInputB() ? m_nInput : m_nOutput;
3931 LPIccCurve *pCurves = NewCurvesB();
3932
3933 if (pIO->Seek(nStart + Offset[0], icSeekSet)<0)
3934 return false;
3935
3936 for (i=0; i<nCurves; i++) {
3937 nPos = pIO->Tell();
3938
3939 if (!pIO->Read32(&sig))
3940 return false;
3941
3942 if (pIO->Seek(nPos, icSeekSet)<0)
3943 return false;
3944
3945 if (sig!=icSigCurveType &&
3947 return false;
3948
3949 pCurves[i] = (CIccCurve*)CIccTag::Create(sig);
3950
3951 if (!pCurves[i]->Read(nEnd - pIO->Tell(), pIO))
3952 return false;
3953
3954 if (!pIO->Sync32(Offset[1]))
3955 return false;
3956 }
3957 }
3958
3959 //Matrix
3960 if (Offset[1]) {
3962
3963 if (Offset[1] + 12*sizeof(icS15Fixed16Number) >size)
3964 return false;
3965
3966 m_Matrix = new CIccMatrix();
3967
3968 if (pIO->Seek(nStart + Offset[1], icSeekSet)<0)
3969 return false;
3970
3971 for (i=0; i<12; i++) {
3972 if (pIO->Read32(&tmp, 1)!=1)
3973 return false;
3974 m_Matrix->m_e[i] = icFtoD(tmp);
3975 }
3976 }
3977
3978
3979 //M Curves
3980 if (Offset[2]) {
3981 nCurves = IsInputMatrix() ? m_nInput : m_nOutput;
3982 LPIccCurve *pCurves = NewCurvesM();
3983
3984 if (pIO->Seek(nStart + Offset[2], icSeekSet)<0)
3985 return false;
3986
3987 for (i=0; i<nCurves; i++) {
3988 nPos = pIO->Tell();
3989
3990 if (!pIO->Read32(&sig))
3991 return false;
3992
3993 if (pIO->Seek(nPos, icSeekSet)<0)
3994 return false;
3995
3996 if (sig!=icSigCurveType &&
3998 return false;
3999
4000 pCurves[i] = (CIccCurve*)CIccTag::Create(sig);
4001
4002 if (!pCurves[i]->Read(nEnd - pIO->Tell(), pIO))
4003 return false;
4004
4005 if (!pIO->Sync32(Offset[2]))
4006 return false;
4007 }
4008 }
4009
4010 //CLUT
4011 if (Offset[3]) {
4012 if (pIO->Seek(nStart + Offset[3], icSeekSet)<0)
4013 return false;
4014
4016
4017 if (!m_CLUT->Read(nEnd - pIO->Tell(), pIO))
4018 return false;
4019 }
4020
4021 //A Curves
4022 if (Offset[4]) {
4023 nCurves = !IsInputB() ? m_nInput : m_nOutput;
4024 LPIccCurve *pCurves = NewCurvesA();
4025
4026 if (pIO->Seek(nStart + Offset[4], icSeekSet)<0)
4027 return false;
4028
4029 for (i=0; i<nCurves; i++) {
4030 nPos = pIO->Tell();
4031
4032 if (!pIO->Read32(&sig))
4033 return false;
4034
4035 if (pIO->Seek(nPos, icSeekSet)<0)
4036 return false;
4037
4038 if (sig!=icSigCurveType &&
4040 return false;
4041
4042 pCurves[i] = (CIccCurve*)CIccTag::Create(sig);
4043
4044 if (!pCurves[i]->Read(nEnd - pIO->Tell(), pIO))
4045 return false;
4046
4047 if (!pIO->Sync32(Offset[4]))
4048 return false;
4049 }
4050 }
4051 return true;
4052}
4053
4054
4055
4056/**
4057 ****************************************************************************
4058 * Name: CIccTagLutAtoB::Write
4059 *
4060 * Purpose: Write the tag to a file
4061 *
4062 * Args:
4063 * pIO - The IO object to write tag to.
4064 *
4065 * Return:
4066 * true = succesful, false = failure
4067 *****************************************************************************
4068 */
4070{
4072 icUInt32Number Offset[5], nStart, nEnd, nOffsetPos;
4073 icUInt8Number nCurves, i;
4074
4075 nStart = pIO->Tell();
4076 memset(&Offset[0], 0, sizeof(Offset));
4077
4078 if (!pIO->Write32(&sig) ||
4079 !pIO->Write32(&m_nReserved) ||
4080 !pIO->Write8(&m_nInput) ||
4081 !pIO->Write8(&m_nOutput) ||
4082 !pIO->Write16(&m_nReservedWord))
4083 return false;
4084
4085 nOffsetPos = pIO->Tell();
4086 if (pIO->Write32(Offset, 5)!=5)
4087 return false;
4088
4089 //B Curves
4090 if (m_CurvesB) {
4091 Offset[0] = pIO->Tell() - nStart;
4092 nCurves = IsInputB() ? m_nInput : m_nOutput;
4093
4094 for (i=0; i<nCurves; i++) {
4095 if (!m_CurvesB[i])
4096 return false;
4097
4098 if (!m_CurvesB[i]->Write(pIO))
4099 return false;
4100
4101 if (!pIO->Align32())
4102 return false;
4103 }
4104 }
4105
4106 //Matrix
4107 if (m_Matrix) {
4109
4110 Offset[1] = pIO->Tell() - nStart;
4111
4112 for (i=0; i<12; i++) {
4113 tmp = icDtoF(m_Matrix->m_e[i]);
4114 if (pIO->Write32(&tmp, 1)!=1)
4115 return false;
4116 }
4117 }
4118
4119
4120 //M Curves
4121 if (m_CurvesM) {
4122 Offset[2] = pIO->Tell() - nStart;
4123 nCurves = IsInputMatrix() ? m_nInput : m_nOutput;
4124
4125 for (i=0; i<nCurves; i++) {
4126 if (!m_CurvesM[i])
4127 return false;
4128
4129 if (!m_CurvesM[i]->Write(pIO))
4130 return false;
4131
4132 if (!pIO->Align32())
4133 return false;
4134 }
4135 }
4136
4137 //CLUT
4138 if (m_CLUT) {
4139 Offset[3] = pIO->Tell() - nStart;
4140
4141 if (!m_CLUT->Write(pIO))
4142 return false;
4143
4144 if (!pIO->Align32())
4145 return false;
4146 }
4147
4148 //A Curves
4149 if (m_CurvesA) {
4150 Offset[4] = pIO->Tell() - nStart;
4151 nCurves = !IsInputB() ? m_nInput : m_nOutput;
4152
4153 for (i=0; i<nCurves; i++) {
4154 if (!m_CurvesA[i])
4155 return false;
4156
4157 if (!m_CurvesA[i]->Write(pIO))
4158 return false;
4159
4160 if (!pIO->Align32())
4161 return false;
4162 }
4163 }
4164
4165 nEnd = pIO->Tell();
4166
4167 if (!pIO->Seek(nOffsetPos, icSeekSet))
4168 return false;
4169
4170 if (pIO->Write32(&Offset[0], 5)!=5)
4171 return false;
4172
4173 return pIO->Seek(nEnd, icSeekSet)>=0;
4174}
4175
4176
4177/**
4178******************************************************************************
4179* Name: CIccTagLutAtoB::Validate
4180*
4181* Purpose: Check tag data validity.
4182*
4183* Args:
4184* sig = signature of tag being validated,
4185* sReport = String to add report information to
4186*
4187* Return:
4188* icValidateStatusOK if valid, or other error status.
4189******************************************************************************
4190*/
4191icValidateStatus CIccTagLutAtoB::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/)
4192{
4193 icValidateStatus rv = CIccMBB::Validate(sigPath, sReport, pProfile);
4194
4195 CIccInfo Info;
4196 std::string sSigPathName = Info.GetSigPathName(sigPath);
4198
4199 if (!pProfile) {
4200 return rv;
4201 }
4202
4203 switch(sig) {
4204 case icSigAToB0Tag:
4205 case icSigAToB1Tag:
4206 case icSigAToB2Tag:
4207 {
4208 icUInt32Number nInput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
4209
4210 icUInt32Number nOutput = icGetSpaceSamples(pProfile->m_Header.pcs);
4211
4212 icUInt8Number i;
4213 if (m_CurvesB) {
4214 for (i=0; i<nOutput; i++) {
4215 if (m_CurvesB[i]) {
4216 rv = icMaxStatus(rv, m_CurvesB[i]->Validate(sigPath+icGetSigPath(GetType()), sReport, pProfile));
4217 }
4218 else {
4219 sReport += icMsgValidateCriticalError;
4220 sReport += sSigPathName;
4221 sReport += " - Incorrect number of B-curves.\n";
4223 }
4224 }
4225 }
4226
4227 if (m_CurvesM) {
4228 for (i=0; i<nOutput; i++) {
4229 if (m_CurvesM[i]) {
4230 rv = icMaxStatus(rv, m_CurvesM[i]->Validate(sigPath+icGetSigPath(GetType()), sReport, pProfile));
4231 }
4232 else {
4233 sReport += icMsgValidateCriticalError;
4234 sReport += sSigPathName;
4235 sReport += " - Incorrect number of M-curves.\n";
4237 }
4238 }
4239 }
4240
4241 if (m_CurvesA) {
4242 if (!m_CLUT) {
4243 sReport += icMsgValidateNonCompliant;
4244 sReport += sSigPathName;
4245 sReport += " - CLUT must be present if using A-curves.\n";
4246
4248 }
4249
4250 for (i=0; i<nInput; i++) {
4251 if (m_CurvesA[i]) {
4252 rv = icMaxStatus(rv, m_CurvesA[i]->Validate(sigPath+icGetSigPath(GetType()), sReport, pProfile));
4253 }
4254 else {
4255 sReport += icMsgValidateCriticalError;
4256 sReport += sSigPathName;
4257 sReport += " - Incorrect number of A-curves.\n";
4259 }
4260 }
4261
4262 }
4263
4264 break;
4265 }
4266 default:
4267 {
4268 }
4269 }
4270
4271
4272 return rv;
4273}
4274
4275/**
4276 ****************************************************************************
4277 * Name: CIccTagLutBtoA::CIccTagLutBtoA
4278 *
4279 * Purpose: Constructor
4280 *
4281 *****************************************************************************
4282 */
4287
4288
4289/**
4290 ****************************************************************************
4291 * Name: CIccTagLutBtoA::CIccTagLutBtoA
4292 *
4293 * Purpose: Copy Constructor
4294 *
4295 * Args:
4296 * ITLB2A = The CIccTagLutBtoA object to be copied
4297 *****************************************************************************
4298 */
4302
4303
4304/**
4305 ****************************************************************************
4306 * Name: CIccTagLutBtoA::operator=
4307 *
4308 * Purpose: Copy Operator
4309 *
4310 * Args:
4311 * ITLB2A = The CIccTagLutBtoA object to be copied
4312 *****************************************************************************
4313 */
4315{
4316 if (&ITLB2A == this)
4317 return *this;
4318
4319 CIccMBB::operator=(ITLB2A);
4320
4321 return *this;
4322}
4323
4324
4325/**
4326******************************************************************************
4327* Name: CIccTagLutBtoA::Validate
4328*
4329* Purpose: Check tag data validity.
4330*
4331* Args:
4332* sig = signature of tag being validated,
4333* sReport = String to add report information to
4334*
4335* Return:
4336* icValidateStatusOK if valid, or other error status.
4337******************************************************************************
4338*/
4339icValidateStatus CIccTagLutBtoA::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/)
4340{
4341 icValidateStatus rv = CIccMBB::Validate(sigPath, sReport, pProfile);
4342
4343 CIccInfo Info;
4344 std::string sSigPathName = Info.GetSigPathName(sigPath);
4346
4347 if (!pProfile) {
4348 sReport += icMsgValidateWarning;
4349 sReport += sSigPathName;
4350 sReport += " - Tag validation incomplete: Pointer to profile unavailable.\n";
4352 return rv;
4353 }
4354
4355 switch(sig) {
4356 case icSigBToA0Tag:
4357 case icSigBToA1Tag:
4358 case icSigBToA2Tag:
4359 case icSigGamutTag:
4360 {
4361 icUInt32Number nInput = icGetSpaceSamples(pProfile->m_Header.pcs);
4362
4363 icUInt32Number nOutput;
4364 if (sig==icSigGamutTag) {
4365 nOutput = 1;
4366 }
4367 else {
4368 nOutput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
4369 }
4370
4371 if (m_nOutput!=nOutput) {
4372 sReport += icMsgValidateCriticalError;
4373 sReport += sSigPathName;
4374 sReport += " - Incorrect number of output channels.\n";
4376 }
4377
4378 icUInt8Number i;
4379 if (m_CurvesB) {
4380 for (i=0; i<nInput; i++) {
4381 if (m_CurvesB[i]) {
4382 rv = icMaxStatus(rv, m_CurvesB[i]->Validate(sigPath+icGetSigPath(GetType()), sReport, pProfile));
4383 }
4384 else {
4385 sReport += icMsgValidateCriticalError;
4386 sReport += sSigPathName;
4387 sReport += " - Incorrect number of B-curves.\n";
4389 }
4390 }
4391 }
4392
4393 if (m_CurvesM) {
4394 for (i=0; i<nInput; i++) {
4395 if (m_CurvesM[i]) {
4396 rv = icMaxStatus(rv, m_CurvesM[i]->Validate(sigPath+icGetSigPath(GetType()), sReport, pProfile));
4397 }
4398 else {
4399 sReport += icMsgValidateCriticalError;
4400 sReport += sSigPathName;
4401 sReport += " - Incorrect number of M-curves.\n";
4403 }
4404 }
4405 }
4406
4407 if (m_CurvesA) {
4408 if (!m_CLUT) {
4409 sReport += icMsgValidateNonCompliant;
4410 sReport += sSigPathName;
4411 sReport += " - CLUT must be present if using A-curves.\n";
4412
4414 }
4415
4416 for (i=0; i<nOutput; i++) {
4417 if (m_CurvesA[i]) {
4418 rv = icMaxStatus(rv, m_CurvesA[i]->Validate(sigPath+icGetSigPath(GetType()), sReport, pProfile));
4419 }
4420 else {
4421 sReport += icMsgValidateCriticalError;
4422 sReport += sSigPathName;
4423 sReport += " - Incorrect number of A-curves.\n";
4425 }
4426 }
4427
4428 }
4429
4430 break;
4431 }
4432 default:
4433 {
4434 }
4435 }
4436
4437
4438 return rv;
4439}
4440
4441
4442/**
4443 ****************************************************************************
4444 * Name: CIccTagLut8::CIccTagLut8
4445 *
4446 * Purpose: Constructor
4447 *
4448 *****************************************************************************
4449 */
4451{
4452 memset(m_XYZMatrix, 0, sizeof(m_XYZMatrix));
4453 m_XYZMatrix[0] = m_XYZMatrix[4] = m_XYZMatrix[8] = icDtoF(1.0);
4454 m_nReservedByte = 0;
4455}
4456
4457
4458/**
4459 ****************************************************************************
4460 * Name: CIccTagLut8::CIccTagLut8
4461 *
4462 * Purpose: Copy Constructor
4463 *
4464 * Args:
4465 * ITL = The CIccTagLut8 object to be copied
4466 *****************************************************************************
4467 */
4469{
4470 memcpy(&m_XYZMatrix, &ITL.m_XYZMatrix, sizeof(m_XYZMatrix));
4471 m_nReservedByte = 0;
4472}
4473
4474
4475/**
4476 ****************************************************************************
4477 * Name: CIccTagLut8::operator=
4478 *
4479 * Purpose: Copy Operator
4480 *
4481 * Args:
4482 * ITL = The CIccTagLut8 object to be copied
4483 *****************************************************************************
4484 */
4486{
4487 if (&ITL==this)
4488 return *this;
4489
4490 CIccMBB::operator=(ITL);
4491 memcpy(&m_XYZMatrix, &ITL.m_XYZMatrix, sizeof(m_XYZMatrix));
4492
4493 return *this;
4494}
4495
4496
4497/**
4498 ****************************************************************************
4499 * Name: CIccTagLut8::~CIccTagLut8
4500 *
4501 * Purpose: Destructor
4502 *
4503 *****************************************************************************
4504 */
4508
4509
4510/**
4511 ****************************************************************************
4512 * Name: CIccTagLut8::Read
4513 *
4514 * Purpose: Read in the tag contents into a data block
4515 *
4516 * Args:
4517 * size - # of bytes in tag,
4518 * pIO - IO object to read tag from
4519 *
4520 * Return:
4521 * true = successful, false = failure
4522 *****************************************************************************
4523 */
4525{
4527 icUInt32Number nStart, nEnd;
4528 icUInt8Number i, nGrid;
4529 LPIccCurve *pCurves;
4530 CIccTagCurve *pCurve;
4531
4532 if (size<13*sizeof(icUInt32Number) || !pIO) {
4533 return false;
4534 }
4535
4536 nStart = pIO->Tell();
4537 nEnd = nStart + size;
4538
4539 if (!pIO->Read32(&sig) ||
4540 !pIO->Read32(&m_nReserved) ||
4541 !pIO->Read8(&m_nInput) ||
4542 !pIO->Read8(&m_nOutput) ||
4543 !pIO->Read8(&nGrid) ||
4544 !pIO->Read8(&m_nReservedByte) ||
4545 pIO->Read32(m_XYZMatrix, 9) != 9)
4546 return false;
4547
4548 if (sig!=GetType())
4549 return false;
4550
4551 //B Curves
4552 pCurves = NewCurvesB();
4553
4554 for (i=0; i<m_nInput; i++) {
4555 if (256 > nEnd - pIO->Tell())
4556 return false;
4557
4558 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
4559
4560 if (!pCurve->SetSize(256))
4561 return false;
4562
4563 if (pIO->ReadUInt8Float(&(*pCurve)[0], 256) != 256)
4564 return false;
4565 }
4566
4567 //CLUT
4569 if (m_CLUT == NULL)
4570 return false;
4571
4572 if (!m_CLUT->Init(nGrid, nEnd - pIO->Tell(), 1))
4573 return false;
4574
4575 if (!m_CLUT->ReadData(nEnd - pIO->Tell(), pIO, 1))
4576 return false;
4577
4578 //A Curves
4579 pCurves = NewCurvesA();
4580 if (pCurves == NULL)
4581 return false;
4582
4583 for (i=0; i<m_nOutput; i++) {
4584 if (256 > nEnd - pIO->Tell())
4585 return false;
4586
4587 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
4588
4589 if (!pCurve->SetSize(256))
4590 return false;
4591
4592 if (pIO->ReadUInt8Float(&(*pCurve)[0], 256) != 256)
4593 return false;
4594 }
4595 return true;
4596}
4597
4598
4599/**
4600 ****************************************************************************
4601 * Name: CIccTagLut8::SetColorSpaces
4602 *
4603 * Purpose: Sets the input and output color spaces
4604 *
4605 * Args:
4606 * csInput = input color space signature,
4607 * csOutput = output color space signature
4608 *
4609 *****************************************************************************
4610 */
4612{
4613 if (csInput==icSigXYZData) {
4614 int i;
4615
4616 if (!m_CurvesM && IsInputMatrix()) { //Transfer ownership of curves
4618 m_CurvesB = NULL;
4619
4620 LPIccCurve *pCurves = NewCurvesB();
4621 CIccTagCurve *pCurve;
4622 for (i=0; i<m_nInput; i++) {
4623 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
4624 pCurve->SetSize(0);
4625 }
4626
4628 }
4629
4630 if (!m_Matrix) {
4631 CIccMatrix *pMatrix = NewMatrix();
4632 for (i=0; i<9; i++) {
4633 pMatrix->m_e[i] = icFtoD(m_XYZMatrix[i]);
4634 }
4635
4636 pMatrix->m_bUseConstants=false;
4637 }
4638 }
4639 else {
4640 m_XYZMatrix[0] = m_XYZMatrix[4] = m_XYZMatrix[8] = icDtoF(1.0);
4641 m_XYZMatrix[1] = m_XYZMatrix[2] = m_XYZMatrix[3] =
4642 m_XYZMatrix[5] = m_XYZMatrix[6] = m_XYZMatrix[7] = 0;
4643 }
4644
4645 CIccMBB::SetColorSpaces(csInput, csOutput);
4646}
4647
4648
4649/**
4650 ****************************************************************************
4651 * Name: CIccTagLut8::Write
4652 *
4653 * Purpose: Write the tag to a file
4654 *
4655 * Args:
4656 * pIO - The IO object to write tag to.
4657 *
4658 * Return:
4659 * true = succesful, false = failure
4660 *****************************************************************************
4661 */
4663{
4665 icUInt8Number i, nGrid;
4666 icS15Fixed16Number XYZMatrix[9];
4667 icUInt16Number nInputEntries, nOutputEntries;
4668 LPIccCurve *pCurves;
4669 CIccTagCurve *pCurve;
4671
4672 if (m_Matrix) {
4673 for (i=0; i<9; i++)
4674 XYZMatrix[i] = icDtoF(m_Matrix->m_e[i]);
4675 }
4676 else {
4677 memset(XYZMatrix, 0, 9*sizeof(icS15Fixed16Number));
4678 XYZMatrix[0] = XYZMatrix[4] = XYZMatrix[8] = icDtoF(1.0);
4679 }
4680
4682 pCurves = m_CurvesM;
4683 }
4684 else {
4685 pCurves = m_CurvesB;
4686 }
4687
4688 if (!pCurves || !m_CurvesA || !m_CLUT)
4689 return false;
4690
4691 nGrid = m_CLUT->GridPoints();
4692
4693 nInputEntries = (icUInt16Number)(((CIccTagCurve*)pCurves[0])->GetSize());
4694 nOutputEntries = (icUInt16Number)(((CIccTagCurve*)m_CurvesA[0])->GetSize());
4695
4696 if (!pIO->Write32(&sig) ||
4697 !pIO->Write32(&m_nReserved) ||
4698 !pIO->Write8(&m_nInput) ||
4699 !pIO->Write8(&m_nOutput) ||
4700 !pIO->Write8(&nGrid) ||
4701 !pIO->Write8(&m_nReservedByte) ||
4702 pIO->Write32(XYZMatrix, 9) != 9)
4703 return false;
4704
4705 //B Curves
4706 for (i=0; i<m_nInput; i++) {
4707 if (pCurves[i]->GetType()!=icSigCurveType)
4708 return false;
4709
4710 pCurve = (CIccTagCurve*)pCurves[i];
4711 if (!pCurve)
4712 return false;
4713
4714 if (pCurve->GetSize()!=256) {
4716
4717 for (j=0; j<256; j++) {
4718 v = pCurve->Apply((icFloat32Number)j / 255.0F);
4719 if (!pIO->WriteUInt8Float(&v, 1))
4720 return false;
4721 }
4722 }
4723 else {
4724 if (pIO->WriteUInt8Float(&(*pCurve)[0], 256)!=256)
4725 return false;
4726 }
4727 }
4728
4729 //CLUT
4730 if (!m_CLUT->WriteData(pIO, 1))
4731 return false;
4732
4733 //A Curves
4734 pCurves = m_CurvesA;
4735
4736 for (i=0; i<m_nOutput; i++) {
4737 if (pCurves[i]->GetType()!=icSigCurveType)
4738 return false;
4739
4740 pCurve = (CIccTagCurve*)pCurves[i];
4741
4742 if (!pCurve)
4743 return false;
4744
4745 if (pCurve->GetSize()!=256) {
4747
4748 for (j=0; j<256; j++) {
4749 v = pCurve->Apply((icFloat32Number)j / 255.0F);
4750 if (!pIO->WriteUInt8Float(&v, 1))
4751 return false;
4752 }
4753 }
4754 else {
4755 if (pIO->WriteUInt8Float(&(*pCurve)[0], 256)!=256)
4756 return false;
4757 }
4758 }
4759 return true;
4760}
4761
4762
4763/**
4764******************************************************************************
4765* Name: CIccTagLut8::Validate
4766*
4767* Purpose: Check tag data validity.
4768*
4769* Args:
4770* sig = signature of tag being validated,
4771* sReport = String to add report information to
4772*
4773* Return:
4774* icValidateStatusOK if valid, or other error status.
4775******************************************************************************
4776*/
4777icValidateStatus CIccTagLut8::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/)
4778{
4779 icValidateStatus rv = CIccMBB::Validate(sigPath, sReport, pProfile);
4780
4781 CIccInfo Info;
4782 std::string sSigPathName = Info.GetSigPathName(sigPath);
4784
4785 if (!pProfile) {
4786 return rv;
4787 }
4788
4789 switch(sig) {
4790 case icSigAToB0Tag:
4791 case icSigAToB1Tag:
4792 case icSigAToB2Tag:
4793 case icSigBToA0Tag:
4794 case icSigBToA1Tag:
4795 case icSigBToA2Tag:
4796 case icSigGamutTag:
4797 {
4798 icUInt32Number nInput, nOutput;
4800 nInput = icGetSpaceSamples(pProfile->m_Header.pcs);
4801 nOutput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
4802 }
4803 else {
4804 nInput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
4805 nOutput = icGetSpaceSamples(pProfile->m_Header.pcs);
4806 }
4807
4808 if (sig==icSigGamutTag) {
4809 nOutput = 1;
4810 }
4811
4812 icUInt8Number i;
4813 if (m_CurvesB) {
4814 for (i=0; i<nInput; i++) {
4815 if (m_CurvesB[i]) {
4816 rv = icMaxStatus(rv, m_CurvesB[i]->Validate(sigPath+icGetSigPath(GetType()), sReport, pProfile));
4817 if (m_CurvesB[i]->GetType()==icSigCurveType) {
4818 CIccTagCurve *pTagCurve = (CIccTagCurve*)m_CurvesB[i];
4819 if (pTagCurve->GetSize()==1) {
4820 sReport += icMsgValidateCriticalError;
4821 sReport += sSigPathName;
4822 sReport += " - lut8Tags do not support single entry gamma curves.\n";
4824 }
4825 }
4826 }
4827 else {
4828 sReport += icMsgValidateCriticalError;
4829 sReport += sSigPathName;
4830 sReport += " - Incorrect number of B-curves.\n";
4832 }
4833 }
4834 }
4835
4836 if (m_Matrix) {
4837 rv = icMaxStatus(rv, m_Matrix->Validate(sigPath + icGetSigPath(GetType()), sReport, pProfile));
4838 }
4839 else {
4840 int sum=0;
4841 for (int i=0; i<9; i++) {
4842 sum += m_XYZMatrix[i];
4843 }
4844 if (m_XYZMatrix[0]!=1.0 || m_XYZMatrix[4]!=1.0 || m_XYZMatrix[8]!=1.0 || sum!=3.0) {
4845 sReport += icMsgValidateWarning;
4846 sReport += sSigPathName;
4847 sReport += " - Matrix must be identity.\n";
4849 }
4850 }
4851
4852 if (m_CurvesA) {
4853
4854 for (i=0; i<nOutput; i++) {
4855 if (m_CurvesA[i]) {
4856 rv = icMaxStatus(rv, m_CurvesA[i]->Validate(sigPath+icGetSigPath(GetType()), sReport, pProfile));
4857 if (m_CurvesA[i]->GetType()==icSigCurveType) {
4858 CIccTagCurve *pTagCurve = (CIccTagCurve*)m_CurvesA[i];
4859 if (pTagCurve->GetSize()==1) {
4860 sReport += icMsgValidateCriticalError;
4861 sReport += sSigPathName;
4862 sReport += " - lut8Tags do not support single entry gamma curves.\n";
4864 }
4865 }
4866 }
4867 else {
4868 sReport += icMsgValidateCriticalError;
4869 sReport += sSigPathName;
4870 sReport += " - Incorrect number of A-curves.\n";
4872 }
4873 }
4874
4875 }
4876
4877 break;
4878 }
4879 default:
4880 {
4881 }
4882 }
4883
4884
4885 return rv;
4886}
4887
4888
4889/**
4890 ****************************************************************************
4891 * Name: CIccTagLut16::CIccTagLut16
4892 *
4893 * Purpose: Constructor
4894 *
4895 *****************************************************************************
4896 */
4898{
4899 memset(m_XYZMatrix, 0, sizeof(m_XYZMatrix));
4900 m_XYZMatrix[0] = m_XYZMatrix[4] = m_XYZMatrix[8] = icDtoF(1.0);
4901 m_nReservedByte = 0;
4902}
4903
4904
4905/**
4906 ****************************************************************************
4907 * Name: CIccTagLut16::CIccTagLut16
4908 *
4909 * Purpose: Copy Constructor
4910 *
4911 * Args:
4912 * ITL = The CIccTagUnknown object to be copied
4913 *****************************************************************************
4914 */
4916{
4917 memcpy(&m_XYZMatrix, &ITL.m_XYZMatrix, sizeof(m_XYZMatrix));
4918 m_nReservedByte = 0;
4919}
4920
4921
4922/**
4923 ****************************************************************************
4924 * Name: CIccTagLut16::operator=
4925 *
4926 * Purpose: Copy Operator
4927 *
4928 * Args:
4929 * ITL = The CIccTagLut16 object to be copied
4930 *****************************************************************************
4931 */
4933{
4934 if (&ITL==this)
4935 return *this;
4936
4937 CIccMBB::operator=(ITL);
4938 memcpy(&m_XYZMatrix, &ITL.m_XYZMatrix, sizeof(m_XYZMatrix));
4939
4940 return *this;
4941}
4942
4943
4944/**
4945 ****************************************************************************
4946 * Name: CIccTagLut16::~CIccTagLut16
4947 *
4948 * Purpose: Destructor
4949 *
4950 *****************************************************************************
4951 */
4955
4956
4957/**
4958 ****************************************************************************
4959 * Name: CIccTagLut16::Read
4960 *
4961 * Purpose: Read in the tag contents into a data block
4962 *
4963 * Args:
4964 * size - # of bytes in tag,
4965 * pIO - IO object to read tag from
4966 *
4967 * Return:
4968 * true = successful, false = failure
4969 *****************************************************************************
4970 */
4972{
4974 icUInt32Number nStart, nEnd;
4975 icUInt8Number i, nGrid;
4976 icUInt16Number nInputEntries, nOutputEntries;
4977 LPIccCurve *pCurves;
4978 CIccTagCurve *pCurve;
4979
4980 if (size<13*sizeof(icUInt32Number) || !pIO) {
4981 return false;
4982 }
4983
4984 nStart = pIO->Tell();
4985 nEnd = nStart + size;
4986
4987 if (!pIO->Read32(&sig) ||
4988 !pIO->Read32(&m_nReserved) ||
4989 !pIO->Read8(&m_nInput) ||
4990 !pIO->Read8(&m_nOutput) ||
4991 !pIO->Read8(&nGrid) ||
4992 !pIO->Read8(&m_nReservedByte) ||
4993 pIO->Read32(m_XYZMatrix, 9) != 9 ||
4994 !pIO->Read16(&nInputEntries) ||
4995 !pIO->Read16(&nOutputEntries))
4996 return false;
4997
4998 if (sig!=GetType())
4999 return false;
5000
5001
5002 //B Curves
5003 pCurves = NewCurvesB();
5004
5005 for (i=0; i<m_nInput; i++) {
5006 if (nInputEntries*sizeof(icUInt16Number) > nEnd - pIO->Tell())
5007 return false;
5008
5009 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
5010
5011 if (!pCurve->SetSize(nInputEntries))
5012 return false;
5013
5014 if (pIO->ReadUInt16Float(&(*pCurve)[0], nInputEntries) != nInputEntries)
5015 return false;
5016 }
5017
5018 //CLUT
5020
5021 if (!m_CLUT->Init(nGrid, nEnd - pIO->Tell(), 2))
5022 return false;
5023
5024 if (!m_CLUT->ReadData(nEnd - pIO->Tell(), pIO, 2))
5025 return false;
5026
5027 //A Curves
5028 pCurves = NewCurvesA();
5029
5030 for (i=0; i<m_nOutput; i++) {
5031 if (nOutputEntries*sizeof(icUInt16Number) > nEnd - pIO->Tell())
5032 return false;
5033
5034 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
5035
5036 if (!pCurve->SetSize(nOutputEntries))
5037 return false;
5038
5039 if (pIO->ReadUInt16Float(&(*pCurve)[0], nOutputEntries) != nOutputEntries)
5040 return false;
5041 }
5042 return true;
5043}
5044
5045
5046/**
5047 ****************************************************************************
5048 * Name: CIccTagLut16::SetColorSpaces
5049 *
5050 * Purpose: Sets the input and output color spaces
5051 *
5052 * Args:
5053 * csInput = input color space signature,
5054 * csOutput = output color space signature
5055 *
5056 *****************************************************************************
5057 */
5059{
5060 if (csInput==icSigXYZData) {
5061 int i;
5062
5063 if (!m_CurvesM && IsInputMatrix()) { //Transfer ownership of curves
5065 m_CurvesB = NULL;
5066
5067 LPIccCurve *pCurves = NewCurvesB();
5068 CIccTagCurve *pCurve;
5069 for (i=0; i<m_nInput; i++) {
5070 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
5071 pCurve->SetSize(0);
5072 }
5073
5075 }
5076
5077 if (!m_Matrix) {
5078 CIccMatrix *pMatrix = NewMatrix();
5079 for (i=0; i<9; i++) {
5080 pMatrix->m_e[i] = icFtoD(m_XYZMatrix[i]);
5081 }
5082
5083 pMatrix->m_bUseConstants=false;
5084 }
5085 }
5086 else {
5087 m_XYZMatrix[0] = m_XYZMatrix[4] = m_XYZMatrix[8] = icDtoF(1.0);
5088 m_XYZMatrix[1] = m_XYZMatrix[2] = m_XYZMatrix[3] =
5089 m_XYZMatrix[5] = m_XYZMatrix[6] = m_XYZMatrix[7] = 0;
5090 }
5091
5092 CIccMBB::SetColorSpaces(csInput, csOutput);
5093}
5094
5095
5096/**
5097 ****************************************************************************
5098 * Name: CIccTagLut16::Write
5099 *
5100 * Purpose: Write the tag to a file
5101 *
5102 * Args:
5103 * pIO - The IO object to write tag to.
5104 *
5105 * Return:
5106 * true = succesful, false = failure
5107 *****************************************************************************
5108 */
5110{
5112 icUInt8Number i, nGrid;
5113 icS15Fixed16Number XYZMatrix[9];
5114 icUInt16Number nInputEntries, nOutputEntries;
5115 LPIccCurve *pCurves;
5116 CIccTagCurve *pCurve;
5117
5118 if (m_Matrix) {
5119 for (i=0; i<9; i++) {
5120 XYZMatrix[i] = icDtoF(m_Matrix->m_e[i]);
5121 }
5122 }
5123 else {
5124 memset(XYZMatrix, 0, 9*sizeof(icS15Fixed16Number));
5125 XYZMatrix[0] = XYZMatrix[4] = XYZMatrix[8] = icDtoF(1.0);
5126 }
5127
5129 pCurves = m_CurvesM;
5130 }
5131 else {
5132 pCurves = m_CurvesB;
5133 }
5134
5135 if (!pCurves || !m_CurvesA || !m_CLUT)
5136 return false;
5137
5138 nGrid = m_CLUT->GridPoints();
5139
5140 nInputEntries = (icUInt16Number)(((CIccTagCurve*)pCurves[0])->GetSize());
5141 nOutputEntries = (icUInt16Number)(((CIccTagCurve*)m_CurvesA[0])->GetSize());
5142
5143 if (!pIO->Write32(&sig) ||
5144 !pIO->Write32(&m_nReserved) ||
5145 !pIO->Write8(&m_nInput) ||
5146 !pIO->Write8(&m_nOutput) ||
5147 !pIO->Write8(&nGrid) ||
5148 !pIO->Write8(&m_nReservedByte) ||
5149 pIO->Write32(XYZMatrix, 9) != 9 ||
5150 !pIO->Write16(&nInputEntries) ||
5151 !pIO->Write16(&nOutputEntries))
5152 return false;
5153
5154 //B Curves
5155 for (i=0; i<m_nInput; i++) {
5156 if (pCurves[i]->GetType()!=icSigCurveType)
5157 return false;
5158
5159 pCurve = (CIccTagCurve*)pCurves[i];
5160 if (!pCurve)
5161 return false;
5162
5163 if (pIO->WriteUInt16Float(&(*pCurve)[0], nInputEntries) != nInputEntries)
5164 return false;
5165 }
5166
5167 //CLUT
5168 if (!m_CLUT->WriteData(pIO, 2))
5169 return false;
5170
5171 //A Curves
5172 pCurves = m_CurvesA;
5173
5174 for (i=0; i<m_nOutput; i++) {
5175 if (pCurves[i]->GetType()!=icSigCurveType)
5176 return false;
5177
5178 pCurve = (CIccTagCurve*)pCurves[i];
5179
5180 if (pIO->WriteUInt16Float(&(*pCurve)[0], nOutputEntries) != nOutputEntries)
5181 return false;
5182 }
5183 return true;
5184}
5185
5186
5187/**
5188******************************************************************************
5189* Name: CIccTagLut16::Validate
5190*
5191* Purpose: Check tag data validity.
5192*
5193* Args:
5194* sig = signature of tag being validated,
5195* sReport = String to add report information to
5196*
5197* Return:
5198* icValidateStatusOK if valid, or other error status.
5199******************************************************************************
5200*/
5201icValidateStatus CIccTagLut16::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/)
5202{
5203 icValidateStatus rv = CIccMBB::Validate(sigPath, sReport, pProfile);
5204
5205 CIccInfo Info;
5206 std::string sSigPathName = Info.GetSigPathName(sigPath);
5208
5209 if (!pProfile) {
5211 return rv;
5212 }
5213
5214 switch(sig) {
5215 case icSigAToB0Tag:
5216 case icSigAToB1Tag:
5217 case icSigAToB2Tag:
5218 case icSigBToA0Tag:
5219 case icSigBToA1Tag:
5220 case icSigBToA2Tag:
5221 case icSigGamutTag:
5222 {
5223 icUInt32Number nInput, nOutput;
5225 nInput = icGetSpaceSamples(pProfile->m_Header.pcs);
5226 nOutput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
5227 }
5228 else {
5229 nInput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
5230 nOutput = icGetSpaceSamples(pProfile->m_Header.pcs);
5231 }
5232
5233 if (sig==icSigGamutTag) {
5234 nOutput = 1;
5235 }
5236
5237 icUInt8Number i;
5238 if (m_CurvesB) {
5239 for (i=0; i<nInput; i++) {
5240 if (m_CurvesB[i]) {
5241 rv = icMaxStatus(rv, m_CurvesB[i]->Validate(sigPath+icGetSigPath(GetType()), sReport, pProfile));
5242 if (m_CurvesB[i]->GetType()==icSigCurveType) {
5243 CIccTagCurve *pTagCurve = (CIccTagCurve*)m_CurvesB[i];
5244 if (pTagCurve->GetSize()==1) {
5245 sReport += icMsgValidateCriticalError;
5246 sReport += sSigPathName;
5247 sReport += " - lut16Tags do not support single entry gamma curves.\n";
5249 }
5250 }
5251 }
5252 else {
5253 sReport += icMsgValidateCriticalError;
5254 sReport += sSigPathName;
5255 sReport += " - Incorrect number of B-curves.\n";
5257 }
5258 }
5259 }
5260
5261 if (m_Matrix) {
5262 rv = icMaxStatus(rv, m_Matrix->Validate(sigPath + icGetSigPath(GetType()), sReport, pProfile));
5263 }
5264 else {
5265 int sum=0;
5266 for (int i=0; i<9; i++) {
5267 sum += m_XYZMatrix[i];
5268 }
5269 if (m_XYZMatrix[0]!=1.0 || m_XYZMatrix[4]!=1.0 || m_XYZMatrix[8]!=1.0 || sum!=3.0) {
5270 sReport += icMsgValidateWarning;
5271 sReport += sSigPathName;
5272 sReport += " - Matrix must be identity.\n";
5274 }
5275 }
5276
5277 if (m_CurvesA) {
5278
5279 for (i=0; i<nOutput; i++) {
5280 if (m_CurvesA[i]) {
5281 rv = icMaxStatus(rv, m_CurvesA[i]->Validate(sigPath+icGetSigPath(GetType()), sReport, pProfile));
5282 if (m_CurvesA[i]->GetType()==icSigCurveType) {
5283 CIccTagCurve *pTagCurve = (CIccTagCurve*)m_CurvesA[i];
5284 if (pTagCurve->GetSize()==1) {
5285 sReport += icMsgValidateCriticalError;
5286 sReport += sSigPathName;
5287 sReport += " - lut16Tags do not support single entry gamma curves.\n";
5289 }
5290 }
5291 }
5292 else {
5293 sReport += icMsgValidateCriticalError;
5294 sReport += sSigPathName;
5295 sReport += " - Incorrect number of A-curves.\n";
5297 }
5298 }
5299
5300 }
5301
5302 break;
5303 }
5304 default:
5305 {
5306 }
5307 }
5308
5309
5310 return rv;
5311}
5312
5313
5314/**
5315 ****************************************************************************
5316 * Name: CIccTagGamutBoundaryDescription::CIccTagGamutBoundaryDescription
5317 *
5318 * Purpose: Constructor
5319 *
5320 *****************************************************************************
5321 */
5323{
5326 m_nPCSChannels = 0;
5328 m_PCSValues = NULL;
5329 m_DeviceValues = NULL;
5330 m_Triangles = NULL;
5331
5332}
5333
5334/**
5335 ****************************************************************************
5336 * Name: CIccTagGamutBoundaryDescription::CIccTagGamutBoundaryDescription
5337 *
5338 * Purpose: Constructor
5339 *
5340 * Args:
5341 * nInputChannels = the number of PCS values, typically 3
5342 * numberOfVertices = the number of vertices in the gamut boundary
5343 * numberOfTriangles = the number of triangles that make up the gamut boundary
5344 * nOutputChannels = the number of device values, can be zero if none are included
5345 *
5346 *****************************************************************************
5347 */
5348
5349CIccTagGamutBoundaryDesc::CIccTagGamutBoundaryDesc(icUInt8Number nInputChannels,icInt32Number numberOfVertices, icInt32Number numberOfTriangles, icUInt8Number nOutputChannels)
5350{
5351
5352 m_NumberOfVertices = numberOfVertices;
5353 m_NumberOfTriangles = numberOfTriangles;
5354 m_nPCSChannels = nInputChannels;
5355 m_nDeviceChannels = nOutputChannels;
5356 m_PCSValues = new icFloatNumber[nInputChannels*m_NumberOfVertices];
5357 if (nOutputChannels > 0)
5358 {
5359 m_DeviceValues = new icFloatNumber[nOutputChannels*m_NumberOfVertices];
5360 }
5361 else
5362 {
5363 m_DeviceValues = NULL;
5364 }
5366
5367
5368}
5369
5370/**
5371 ****************************************************************************
5372 * Name: CIccTagGamutBoundaryDescription::CIccTagGamutBoundaryDescription
5373 *
5374 * Purpose: Constructor
5375 *
5376 * Args:
5377 * InGamutBoundaryTag = the CIccTagGamutBoundaryDescription object to copy
5378 *
5379 *****************************************************************************
5380 */
5382{
5383 m_NumberOfVertices = InGamutBoundaryTag.m_NumberOfVertices;
5384 m_NumberOfTriangles = InGamutBoundaryTag.m_NumberOfTriangles;
5385 m_nPCSChannels = InGamutBoundaryTag.m_nPCSChannels;
5386 m_nDeviceChannels = InGamutBoundaryTag.m_nDeviceChannels;
5387
5389
5390 if (m_nDeviceChannels > 0)
5391 {
5393 }
5394 else
5395 {
5396 m_DeviceValues = NULL;
5397 }
5399
5400 memcpy(m_PCSValues,InGamutBoundaryTag.m_PCSValues,m_nPCSChannels*m_NumberOfVertices*sizeof(icFloatNumber));
5401 if (m_DeviceValues)
5403 memcpy(m_Triangles,InGamutBoundaryTag.m_Triangles,m_NumberOfTriangles*sizeof(icGamutBoundaryTriangle));
5404}
5405
5406/**
5407 ****************************************************************************
5408 * Name: CIccTagGamutBoundaryDescription::operator=
5409 *
5410 * Purpose: Constructor
5411 *
5412 * Args:
5413 * InGamutBoundaryTag = the CIccTagGamutBoundaryDescription object to copy
5414 *
5415 ******/
5416
5418{
5419 if (&InGamutBoundaryTag == this)
5420 return *this;
5421
5422 m_NumberOfVertices = InGamutBoundaryTag.m_NumberOfVertices;
5423 m_NumberOfTriangles = InGamutBoundaryTag.m_NumberOfTriangles;
5424 m_nPCSChannels = InGamutBoundaryTag.m_nPCSChannels;
5425 m_nDeviceChannels = InGamutBoundaryTag.m_nDeviceChannels;
5426
5428
5429 if (m_nDeviceChannels > 0)
5430 {
5432 }
5433 else
5434 {
5435 m_DeviceValues = NULL;
5436 }
5438
5439 memcpy(m_PCSValues,InGamutBoundaryTag.m_PCSValues,m_nPCSChannels*m_NumberOfVertices*sizeof(icFloatNumber));
5440 if (m_DeviceValues)
5442 memcpy(m_Triangles,InGamutBoundaryTag.m_Triangles,m_NumberOfTriangles*sizeof(icGamutBoundaryTriangle));
5443
5444 return *this;
5445}
5446
5447/**
5448 ****************************************************************************
5449 * Name: CIccTagGamutBoundaryDescription::CIccTagGamutBoundaryDescription
5450 *
5451 * Purpose: Destructor
5452 *
5453 *****************************************************************************
5454 */
5456{
5457 if (m_PCSValues)
5458 delete [] m_PCSValues;
5459
5460 if (m_DeviceValues)
5461 delete [] m_DeviceValues;
5462
5463 if (m_Triangles)
5464 delete [] m_Triangles;
5465}
5466
5467/**
5468 ****************************************************************************
5469 * Name: CIccTagGamutBoundaryDescription::Read
5470 *
5471 * Purpose: Read in an gamut boundary tag type into a data block
5472 *
5473 * Args:
5474 * size - # of bytes in tag,
5475 * pIO - IO object to read tag from
5476 *
5477 * Return:
5478 * true = successful, false = failure
5479 *****************************************************************************
5480 */
5482{
5484
5485 if (sizeof(icTagTypeSignature) +
5486 sizeof(icUInt32Number)*3 +
5487 sizeof(icUInt16Number)*2 > size)
5488 return false;
5489
5490 if (!pIO) {
5491 return false;
5492 }
5493
5494 if (!pIO->Read32(&sig) ||
5495 !pIO->Read32(&m_nReserved))
5496 return false;
5497
5498 if (!pIO->Read16(&m_nPCSChannels) ||
5499 !pIO->Read16(&m_nDeviceChannels))
5500 return false;
5501
5502 if (!pIO->Read32(&m_NumberOfVertices) ||
5504 return false;
5505
5506 if (sizeof(icTagTypeSignature) +
5507 sizeof(icUInt32Number)*3 +
5508 sizeof(icUInt16Number)*2 +
5512 return false;
5513
5514 if (m_PCSValues)
5515 delete [] m_PCSValues;
5516 if (m_DeviceValues)
5517 delete [] m_DeviceValues;
5518 if (m_Triangles)
5519 delete [] m_Triangles;
5520
5522
5523 if (!m_PCSValues)
5524 return false;
5525
5526 if (m_nDeviceChannels > 0)
5527 {
5529
5530 if (!m_DeviceValues)
5531 return false;
5532 }
5533 else
5534 {
5535 m_DeviceValues = NULL;
5536 }
5538
5540
5541 if (pIO->Read32(m_Triangles, nNum32)!=nNum32)
5542 return false;
5543
5545
5546 if (pIO->ReadFloat32Float(m_PCSValues, nNum32)!=nNum32)
5547 return false;
5548
5549 if (m_nDeviceChannels > 0)
5550 {
5552
5553 if (pIO->ReadFloat32Float(m_DeviceValues, nNum32)!=nNum32)
5554 return false;
5555 }
5556
5557 return true;
5558}
5559
5560/**
5561 ****************************************************************************
5562 * Name: CIccTagGamutBoundaryDescription::Write
5563 *
5564 * Purpose: Write a gamut boundary type tag to a file
5565 *
5566 * Args:
5567 * pIO - The IO object to write tag to.
5568 *
5569 * Return:
5570 * true = succesful, false = failure
5571 *****************************************************************************
5572 */
5574{
5575
5577
5578 if (!pIO) {
5579 return false;
5580 }
5581
5582 icUInt32Number startPos = pIO->GetLength();
5583
5584 if (!pIO->Write32(&sig) ||
5585 !pIO->Write32(&m_nReserved))
5586 return false;
5587
5588
5589 if (!pIO->Write16(&m_nPCSChannels) ||
5590 !pIO->Write16(&m_nDeviceChannels))
5591 return false;
5592
5593 if (!pIO->Write32(&m_NumberOfVertices) ||
5595 return false;
5596
5598
5599 if (pIO->Write32(m_Triangles, nNum32)!=nNum32)
5600 return false;
5601
5602
5604
5605 if (pIO->WriteFloat32Float(m_PCSValues, nNum32)!=nNum32)
5606 return false;
5607
5608 if (m_nDeviceChannels > 0)
5609 {
5611
5612 if (pIO->WriteFloat32Float(m_DeviceValues, nNum32)!=nNum32)
5613 return false;
5614 }
5615
5616 return true;
5617
5618}
5619
5620
5621/**
5622 ****************************************************************************
5623 * Name: CIccTagGamutBoundaryDescription::Describe
5624 *
5625 * Purpose: Dump data associated with gamut boundary tag to a string
5626 *
5627 * Args:
5628 * sDescription - string to concatenate tag dump to
5629 *****************************************************************************
5630 */
5631void CIccTagGamutBoundaryDesc::Describe(std::string &sDescription, int nVerboseness)
5632{
5633 icChar buf[256];
5634
5635 sprintf(buf,"Number Of Vertices = %d, Number of Triangles = %d\n",m_NumberOfVertices,m_NumberOfTriangles);
5636 sDescription += buf;
5637
5638 sprintf(buf,"Number Of Inputs = %d, Number of Outputs = %d\n",m_nPCSChannels,m_nDeviceChannels);
5639 sDescription += buf;
5640
5641 if (nVerboseness > 75) {
5642 int c = 0;
5643 int d = 0;
5644 for (int i=0; i<m_NumberOfVertices; i++)
5645 {
5646 sprintf(buf,"V = %d:\t",i);
5647 sDescription += buf;
5648 for (int j=0; j<m_nPCSChannels; j++)
5649 {
5650 sprintf(buf,"%.4lf\t",m_PCSValues[c++]);
5651 sDescription += buf;
5652 }
5653 if (m_nDeviceChannels > 0)
5654 {
5655 sprintf(buf,":\t");
5656 sDescription += buf;
5657
5658 for (int j=0; j<m_nDeviceChannels; j++)
5659 {
5660 sprintf(buf,"%.4lf\t",m_DeviceValues[d++]);
5661 sDescription += buf;
5662 }
5663 }
5664 sprintf(buf,"\n");
5665 sDescription += buf;
5666 }
5667
5668 for (int i=0; i<m_NumberOfTriangles; i++)
5669 {
5670 sprintf(buf,"V1 = %u\tV2 = %u\tV3 = %u\n",m_Triangles[i].m_VertexNumbers[0],m_Triangles[i].m_VertexNumbers[1],m_Triangles[i].m_VertexNumbers[2]);
5671 sDescription += buf;
5672 }
5673 }
5674}
5675
5676/**
5677 ****************************************************************************
5678 * Name: CIccTagGamutBoundaryDescription::setVertex
5679 *
5680 * Purpose: Dump data associated with gamut boundary tag to a string
5681 *
5682 * Args:
5683 * vertexNumber = the number of the vertex to set
5684 * pcsCoords = the pcs coordinates of the vertex
5685 * deviceCoords = the device coordinates of the vertex
5686 *
5687 * Return:
5688 * true = succesful, false = failure
5689 *****************************************************************************
5690 */
5692{
5693 if ((vertexNumber < 0) || (vertexNumber >= m_NumberOfVertices))
5694 return false;
5695
5696 memcpy(&m_PCSValues[vertexNumber*m_nPCSChannels],pcsCoords,sizeof(icFloatNumber)*m_nPCSChannels);
5697 if ((m_DeviceValues) && (deviceCoords))
5698 memcpy(&m_DeviceValues[vertexNumber*m_nDeviceChannels],deviceCoords,sizeof(icFloatNumber)*m_nDeviceChannels);
5699
5700 return true;
5701}
5702
5703
5704/**
5705 ****************************************************************************
5706 * Name: CIccTagGamutBoundaryDescription::getVertexPCSCoord
5707 *
5708 * Purpose: Dump data associated with gamut boundary tag to a string
5709 *
5710 * Args:
5711 * vertexNumber = the number of the vertex to get
5712 *
5713 * Return:
5714 * NULL = failure, otherwise a pointer to the PCS coordinate
5715 *****************************************************************************
5716 */
5718{
5719 if ((vertexNumber < 0) || (vertexNumber >= m_NumberOfVertices))
5720 return NULL;
5721
5722 return &m_PCSValues[vertexNumber*m_nPCSChannels];
5723}
5724
5725/**
5726 ****************************************************************************
5727 * Name: CIccTagGamutBoundaryDescription::getVertexDeviceCoord
5728 *
5729 * Purpose: Dump data associated with gamut boundaty tag to a string
5730 *
5731 * Args:
5732 * vertexNumber = the number of the vertex to get
5733 *
5734 * Return:
5735 * NULL = failure, otherwise a pointer to the device coordinate
5736 *****************************************************************************
5737 */
5739{
5740 if ((vertexNumber < 0) || (vertexNumber >= m_NumberOfVertices))
5741 return NULL;
5742
5743 if (!m_DeviceValues)
5744 return NULL;
5745
5746 return &m_DeviceValues[vertexNumber*m_nDeviceChannels];
5747}
5748
5749/**
5750 ****************************************************************************
5751 * Name: CIccTagGamutBoundaryDescription::setTriangle
5752 *
5753 * Purpose: Dump data associated with gamut boundary tag to a string
5754 *
5755 * Args:
5756 * triangleNumber = the number of the triangle to set
5757 * triangle = the triangle to copy into the gamut boundary
5758 *
5759 * Return:
5760 * true = succesful, false = failure
5761 *****************************************************************************
5762 */
5764{
5765 if ((triangleNumber < 0) || (triangleNumber >= m_NumberOfTriangles))
5766 return false;
5767
5768 memcpy(&m_Triangles[triangleNumber],&triangle,sizeof(icGamutBoundaryTriangle));
5769
5770 return true;
5771}
5772
5773/**
5774 ****************************************************************************
5775 * Name: CIccTagGamutBoundaryDescription::getTriangle
5776 *
5777 * Purpose: Dump data associated with gamut boundary tag to a string
5778 *
5779 * Args:
5780 * triangleNumber = the number of the triangle to set
5781 * triangle = the triangle to copy from the gamut boundary
5782 *
5783 * Return:
5784 * true = succesful, false = failure
5785 *****************************************************************************
5786 */
5787
5789{
5790 if ((triangleNumber < 0) || (triangleNumber >= m_NumberOfTriangles))
5791 return false;
5792
5793 memcpy(&triangle,&m_Triangles[triangleNumber],sizeof(icGamutBoundaryTriangle));
5794 return true;
5795}
5796
5797
5798
5799/**
5800 ******************************************************************************
5801 * Name: CIccTagGamutBoundaryDescription::Validate
5802 *
5803 * Purpose: Check tag data validity.
5804 *
5805 * Args:
5806 * sig = signature of tag being validated,
5807 * sReport = String to add report information to
5808 *
5809 * Return:
5810 * icValidateStatusOK if valid, or other error status.
5811 ******************************************************************************
5812 */
5813icValidateStatus CIccTagGamutBoundaryDesc::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
5814{
5815 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
5816
5817 CIccInfo Info;
5818 std::string sSigPathName = Info.GetSigPathName(sigPath);
5819
5820 if ((m_NumberOfVertices == 0) || (m_NumberOfTriangles == 0) || (m_nPCSChannels < 3)) {
5821 sReport += icMsgValidateWarning;
5822 sReport += sSigPathName;
5823 sReport += " - Invalid tag.\n";
5824
5826 return rv;
5827 }
5828
5829 return rv;
5830}
5831
5832
5833
5834#ifdef USEREFICCMAXNAMESPACE
5835} //namespace refIccMAX
5836#endif
icArraySignature sig
float icFloatNumber
All floating point operations/variables in IccProfLib use the icFloatNumber data type.
Definition IccDefs.h:100
char icChar
Definition IccDefs.h:109
icValidateStatus
Definition IccDefs.h:118
@ icValidateOK
Definition IccDefs.h:119
@ icValidateWarning
Definition IccDefs.h:120
@ icValidateCriticalError
Definition IccDefs.h:122
@ icValidateNonCompliant
Definition IccDefs.h:121
@ icSeekSet
Definition IccIO.h:83
File: IccMpeBasic.h.
File: IccProfile.h.
File: IccTag.h.
const icChar * szName
static icFloatNumber ClutUnitClip(icFloatNumber v)
static bool IsUnity(const icFloatNumber &num)
const icFloatNumber VERYSMALLNUM
icTagCurveSizeInit
Definition IccTagLut.h:114
@ icInitZero
Definition IccTagLut.h:116
@ icInitIdentity
Definition IccTagLut.h:117
@ icInitNone
Definition IccTagLut.h:115
@ icElemInterpLinear
Definition IccTagMPE.h:94
icValidateStatus icMaxStatus(icValidateStatus s1, icValidateStatus s2)
Name: icMaxStatus.
Definition IccUtil.cpp:244
std::string icGetSigPath(icUInt32Number nSig)
Definition IccUtil.cpp:1191
const char * icMsgValidateWarning
Definition IccUtil.cpp:90
icUInt32Number icGetSpaceSamples(icColorSpaceSignature sig)
Definition IccUtil.cpp:1303
void * icRealloc(void *ptr, size_t size)
Name: icRealloc.
Definition IccUtil.cpp:111
icFloatNumber icFtoD(icS15Fixed16Number num)
Definition IccUtil.cpp:559
void icColorValue(icChar *szValue, icFloatNumber nValue, icColorSpaceSignature csSig, int nIndex, bool bUseLegacy)
Definition IccUtil.cpp:330
icS15Fixed16Number icDtoF(icFloatNumber num)
Definition IccUtil.cpp:545
const char * icMsgValidateNonCompliant
Definition IccUtil.cpp:91
void icColorIndexName(icChar *szName, icColorSpaceSignature csSig, int nIndex, int nColors, const icChar *szUnknown)
Definition IccUtil.cpp:295
const char * icMsgValidateCriticalError
Definition IccUtil.cpp:92
icSignature icGetFirstSigPathSig(std::string sigPath)
Definition IccUtil.cpp:1201
File: IccUtil.h.
icTagTypeSignature
unsigned int icUInt32Number
Class: CIccApplyCLUT.
Definition IccTagLut.h:302
CIccApplyCLUT()
Name: CIccApplyCLUT::CIccApplyCLUT.
icFloatNumber * m_df
Definition IccTagLut.h:313
virtual ~CIccApplyCLUT()
Name: CIccApplyNDLutXform::~CIccApplyNDLutXform.
icFloatNumber * m_g
Definition IccTagLut.h:313
bool Init(icUInt8Number nSrcChannels, icUInt32Number nNodes)
Name: CIccApplyCLUT::Init.
icFloatNumber * m_s
Definition IccTagLut.h:313
icUInt32Number * m_ig
Definition IccTagLut.h:314
Class: CIccCLUT.
Definition IccTagLut.h:326
void Interp4d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp4d.
icCLUTCLIPFUNC UnitClip
Definition IccTagLut.h:388
icUInt8Number GetInputDim() const
Definition IccTagLut.h:356
icUInt16Number GetOutputChannels() const
Definition IccTagLut.h:357
void Begin()
Name: CIccCLUT::Begin.
void Interp2d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp2d.
icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile=NULL) const
Name: CIccCLUT::Validate.
void Interp6d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp6d.
void Interp3d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp3d.
icUInt32Number m_DimSize[16]
Definition IccTagLut.h:399
void DumpLut(std::string &sDescription, const icChar *szName, icColorSpaceSignature csInput, icColorSpaceSignature csOutput, int nVerboseness, bool bUseLegacy=false)
Name: CIccCLUT::DumpLut.
icUInt8Number m_GridAdr[16]
Definition IccTagLut.h:403
icUInt8Number m_nInput
Definition IccTagLut.h:392
CIccCLUT & operator=(const CIccCLUT &CLUTClass)
Name: CIccCLUT::operator=.
CIccCLUT(icUInt8Number nInputChannels, icUInt16Number nOutputChannels, icUInt8Number nPrecision=2)
Name: CIccCLUT::CIccCLUT.
void Interp5d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp5d.
void Iterate(IIccCLUTExec *pExec)
Name: CIccCLUT::Iterate.
icUInt8Number m_nPrecision
Definition IccTagLut.h:394
bool WriteData(CIccIO *pIO, icUInt8Number nPrecision)
Name: CIccCLUT::WriteData.
icColorSpaceSignature m_csOutput
Definition IccTagLut.h:406
void SubIterate(IIccCLUTExec *pExec, icUInt8Number nIndex, icUInt32Number nPos)
Name: CIccCLUT::SubIterate.
icUInt16Number m_nOutput
Definition IccTagLut.h:393
icUInt32Number m_nNumPoints
Definition IccTagLut.h:397
bool ReadData(icUInt32Number size, CIccIO *pIO, icUInt8Number nPrecision)
Name: CIccCLUT::ReadData.
icUInt8Number GridPoints() const
Definition IccTagLut.h:349
virtual ~CIccCLUT()
Name: CIccCLUT::~CIccCLUT.
void Interp3dTetra(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp3dTetra.
icUInt8Number m_nReserved2[3]
Definition IccTagLut.h:390
bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccCLUT::Read.
bool Write(CIccIO *pIO)
Name: CIccCLUT::Write.
icColorSpaceSignature m_csInput
Definition IccTagLut.h:406
CIccApplyCLUT * GetNewApply()
void Interp1d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
Name: CIccCLUT::Interp1d.
void InterpND(icFloatNumber *destPixel, const icFloatNumber *srcPixel, CIccApplyCLUT *pApply) const
Name: CIccCLUT::InterpND.
bool Init(icUInt8Number nGridPoints, icUInt32Number nMaxSize=0, icUInt8Number nBytesPerPoint=4)
Name: CIccCLUT::Init.
icFloatNumber * m_pData
Definition IccTagLut.h:400
icUInt8Number m_GridPoints[16]
Definition IccTagLut.h:396
Class: CIccCurve.
Definition IccTagLut.h:91
virtual CIccTag * NewCopy() const
Function: NewCopy(sDescription) Each derived tag will implement it's own NewCopy() function.
Definition IccTagLut.h:94
icFloatNumber Find(icFloatNumber v)
Definition IccTagLut.h:103
virtual void Describe(std::string &sDescription, int nVerboseness=100)=0
Type: Class.
Definition IccIO.h:97
icInt32Number ReadFloat32Float(void *pBufFloat, icInt32Number nNum=1)
Definition IccIO.cpp:302
virtual icInt32Number Write8(void *pBuf8, icInt32Number nNum=1)
Definition IccIO.h:105
virtual icInt32Number GetLength()
Definition IccIO.h:130
icInt32Number Write16(void *pBuf16, icInt32Number nNum=1)
Definition IccIO.cpp:122
virtual icInt32Number Read8(void *pBuf8, icInt32Number nNum=1)
Definition IccIO.h:104
icInt32Number Read16(void *pBuf16, icInt32Number nNum=1)
Definition IccIO.cpp:114
virtual icInt32Number Tell()
Definition IccIO.h:133
bool Align32()
Write operation to make sure that filelength is evenly divisible by 4.
Definition IccIO.cpp:341
icInt32Number ReadUInt8Float(void *pBufFloat, icInt32Number nNum=1)
Definition IccIO.cpp:203
icInt32Number Write32(void *pBuf32, icInt32Number nNum=1)
Definition IccIO.cpp:152
virtual icInt32Number Seek(icInt32Number nOffset, icSeekVal pos)
Definition IccIO.h:132
icInt32Number WriteFloat32Float(void *pBufFloat, icInt32Number nNum=1)
Definition IccIO.cpp:321
icInt32Number WriteUInt8Float(void *pBuf16, icInt32Number nNum=1)
Definition IccIO.cpp:219
icInt32Number ReadUInt16Float(void *pBufFloat, icInt32Number nNum=1)
Definition IccIO.cpp:236
icInt32Number Read32(void *pBuf32, icInt32Number nNum=1)
Definition IccIO.cpp:143
bool Sync32(icUInt32Number nOffset=0)
Operation to make sure read position is evenly divisible by 4.
Definition IccIO.cpp:357
icInt32Number WriteUInt16Float(void *pBuf16, icInt32Number nNum=1)
Definition IccIO.cpp:252
Type: Class.
Definition IccUtil.h:303
std::string GetSigPathName(std::string sigPath)
Definition IccUtil.cpp:1614
Class: CIccMBB.
Definition IccTagLut.h:428
bool m_bInputMatrix
Definition IccTagLut.h:477
bool IsInputB()
Definition IccTagLut.h:445
LPIccCurve * m_CurvesB
Definition IccTagLut.h:490
LPIccCurve * NewCurvesB()
Name: CIccMBB::NewCurvesB.
CIccMatrix * NewMatrix()
Name: CIccMBB::NewMatrix.
virtual ~CIccMBB()
Name: CIccMBB::~CIccMBB.
virtual bool IsInputMatrix()
Definition IccTagLut.h:442
CIccCLUT * m_CLUT
Definition IccTagLut.h:487
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccMBB::Describe.
LPIccCurve * m_CurvesM
Definition IccTagLut.h:489
virtual void SetColorSpaces(icColorSpaceSignature csInput, icColorSpaceSignature csOutput)
Name: CIccMBB::SetColorSpaces.
CIccCLUT * SetCLUT(CIccCLUT *clut)
Name: CIccMBB::SetCLUT.
CIccMBB & operator=(const CIccMBB &IMBB)
Name: CIccMBB::operator=.
LPIccCurve * NewCurvesM()
Name: CIccMBB::NewCurvesM.
CIccMBB()
Name: CIccMBB::CIccMBB.
icUInt8Number m_nOutput
Definition IccTagLut.h:481
LPIccCurve * NewCurvesA()
Name: CIccMBB::NewCurvesA.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile=NULL)
Name: CIccMBB::Validate.
LPIccCurve * m_CurvesA
Definition IccTagLut.h:486
icUInt8Number m_nInput
Definition IccTagLut.h:480
icColorSpaceSignature m_csOutput
Definition IccTagLut.h:484
bool m_bUseMCurvesAsBCurves
Definition IccTagLut.h:478
void Cleanup()
Name: CIccMBB::Cleanup.
icColorSpaceSignature m_csInput
Definition IccTagLut.h:483
CIccCLUT * NewCLUT(icUInt8Number nGridPoints, icUInt8Number nPrecision=2)
Name: CIccMBB::NewCLUT.
CIccMatrix * m_Matrix
Definition IccTagLut.h:488
void Init(icUInt8Number nInputChannels, icUInt8Number nOutputChannels)
Name: CIccMBB::Init.
Class: CIccMatrix.
Definition IccTagLut.h:260
CIccMatrix(bool bUseConstants=true)
Name: CIccMatrix::CIccMatrix.
CIccMatrix & operator=(const CIccMatrix &MatrixClass)
Name: CIccMatrix::operator=.
virtual bool IsIdentity()
Name: CIccMatrix::IsIdentity.
icFloatNumber m_e[12]
Definition IccTagLut.h:269
icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile=NULL) const
Name: CIccMatrix::Validate.
void DumpLut(std::string &sDescription, const icChar *szName, int nVerboseness)
Name: CIccTagParametricCurve::DumpLut.
virtual void Apply(icFloatNumber *Pixel) const
Name: CIccMatrix::Apply.
bool m_bUseConstants
Definition IccTagLut.h:270
Class: CIccSegmentedCurve.
virtual bool Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
Name: CIccSegmentedCurve::Begin.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccSegmentedCurve::Read.
virtual CIccCurveSetCurve * NewCopy() const
Class: CIccTagCurve.
Definition IccTagLut.h:128
icUInt32Number m_nSize
Definition IccTagLut.h:159
virtual ~CIccTagCurve()
Name: CIccTagCurve::~CIccTagCurve.
icUInt16Number m_nMaxIndex
Definition IccTagLut.h:160
virtual bool IsIdentity()
Name: CIccTagCurve::IsIdentity.
icFloatNumber * m_Curve
Definition IccTagLut.h:158
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccTagCurve::Describe.
virtual void DumpLut(std::string &sDescription, const icChar *szName, icColorSpaceSignature csSig, int nIndex, int nVerboseness)
Name: CIccTagCurve::DumpLut.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccTagCurve::Read.
CIccTagCurve(int nSize=0)
Name: CIccTagCurve::CIccTagCurve.
bool SetGamma(icFloatNumber gamma)
Name: refIccMAX::CIccTagCurve::SetGamma.
CIccTagCurve & operator=(const CIccTagCurve &CurveTag)
Name: CIccTagCurve::operator=.
virtual icFloatNumber Apply(icFloatNumber v) const
Name: CIccTagCurve::Apply.
icUInt32Number GetSize() const
Definition IccTagLut.h:148
bool SetSize(icUInt32Number nSize, icTagCurveSizeInit nSizeOpt=icInitZero)
Name: CIccTagCurve::SetSize.
virtual bool Write(CIccIO *pIO)
Name: CIccTagCurve::Write.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile=NULL) const
Name: CIccTagCurve::Validate.
Class: CIccTagGamutBoundaryDesc.
Definition IccTagLut.h:612
icGamutBoundaryTriangle * m_Triangles
Definition IccTagLut.h:664
CIccTagGamutBoundaryDesc & operator=(const CIccTagGamutBoundaryDesc &InGamutBoundaryTag)
Name: CIccTagGamutBoundaryDescription::operator=.
virtual bool Write(CIccIO *pIO)
Name: CIccTagGamutBoundaryDescription::Write.
icInt32Number m_NumberOfTriangles
Definition IccTagLut.h:659
bool setVertex(icInt32Number vertexNumber, icFloatNumber *pcsCoords, icFloatNumber *deviceCoords=NULL)
Name: CIccTagGamutBoundaryDescription::setVertex.
icInt16Number m_nPCSChannels
Definition IccTagLut.h:660
icFloatNumber * m_DeviceValues
Definition IccTagLut.h:663
icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile) const
Name: CIccTagGamutBoundaryDescription::Validate.
icFloatNumber * m_PCSValues
Definition IccTagLut.h:662
icInt16Number m_nDeviceChannels
Definition IccTagLut.h:661
bool getTriangle(icInt32Number triangleNumber, icGamutBoundaryTriangle &triangle)
Name: CIccTagGamutBoundaryDescription::getTriangle.
bool setTriangle(icInt32Number triangleNumber, icGamutBoundaryTriangle &triangle)
Name: CIccTagGamutBoundaryDescription::setTriangle.
icInt32Number m_NumberOfVertices
Definition IccTagLut.h:658
CIccTagGamutBoundaryDesc()
Name: CIccTagGamutBoundaryDescription::CIccTagGamutBoundaryDescription.
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccTagGamutBoundaryDescription::Describe.
icFloatNumber * getVertexPCSCoord(icInt32Number vertexNumber)
Name: CIccTagGamutBoundaryDescription::getVertexPCSCoord.
virtual icTagTypeSignature GetType() const
Function: GetType()
Definition IccTagLut.h:621
icFloatNumber * getVertexDeviceCoord(icInt32Number vertexNumber)
Name: CIccTagGamutBoundaryDescription::getVertexDeviceCoord.
virtual ~CIccTagGamutBoundaryDesc()
Name: CIccTagGamutBoundaryDescription::CIccTagGamutBoundaryDescription.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccTagGamutBoundaryDescription::Read.
icUInt32Number m_nReserved
static CIccTag * Create(icTagTypeSignature sig)
Name: CIccTag::Create.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile=NULL) const
Function: Validate Each derived tag will implement it's own IsValid() function.
Class: CIccTagLut16.
Definition IccTagLut.h:578
icUInt8Number m_nReservedByte
Definition IccTagLut.h:596
icS15Fixed16Number m_XYZMatrix[9]
Definition IccTagLut.h:597
virtual icTagTypeSignature GetType() const
Function: GetType()
Definition IccTagLut.h:586
bool Write(CIccIO *pIO)
Name: CIccTagLut16::Write.
virtual ~CIccTagLut16()
Name: CIccTagLut16::~CIccTagLut16.
CIccTagLut16()
Name: CIccTagLut16::CIccTagLut16.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile=NULL)
Name: CIccTagLut16::Validate.
bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccTagLut16::Read.
CIccTagLut16 & operator=(const CIccTagLut16 &ITL)
Name: CIccTagLut16::operator=.
virtual void SetColorSpaces(icColorSpaceSignature csInput, icColorSpaceSignature csOutput)
Name: CIccTagLut16::SetColorSpaces.
Class: CIccTagLut8.
Definition IccTagLut.h:548
CIccTagLut8()
Name: CIccTagLut8::CIccTagLut8.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile=NULL)
Name: CIccTagLut8::Validate.
virtual icTagTypeSignature GetType() const
Function: GetType()
Definition IccTagLut.h:556
icUInt8Number m_nReservedByte
Definition IccTagLut.h:566
virtual ~CIccTagLut8()
Name: CIccTagLut8::~CIccTagLut8.
icS15Fixed16Number m_XYZMatrix[9]
Definition IccTagLut.h:567
bool Write(CIccIO *pIO)
Name: CIccTagLut8::Write.
CIccTagLut8 & operator=(const CIccTagLut8 &ITL)
Name: CIccTagLut8::operator=.
bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccTagLut8::Read.
virtual void SetColorSpaces(icColorSpaceSignature csInput, icColorSpaceSignature csOutput)
Name: CIccTagLut8::SetColorSpaces.
Class: CIccTagLutAtoB.
Definition IccTagLut.h:502
virtual icTagTypeSignature GetType() const
Function: GetType()
Definition IccTagLut.h:510
CIccTagLutAtoB()
Name: CIccTagLutAtoB::CIccTagLutAtoB.
bool Write(CIccIO *pIO)
Name: CIccTagLutAtoB::Write.
icUInt16Number m_nReservedWord
Definition IccTagLut.h:517
CIccTagLutAtoB & operator=(const CIccTagLutAtoB &ITLA2B)
Name: CIccTagLutAtoB::operator=.
virtual ~CIccTagLutAtoB()
Name: CIccTagLutAtoB::~CIccTagLutAtoB.
bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccTagLutAtoB::Read.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile=NULL)
Name: CIccTagLutAtoB::Validate.
Class: CIccTagLutBtoA.
Definition IccTagLut.h:528
CIccTagLutBtoA & operator=(const CIccTagLutBtoA &ITLB2A)
Name: CIccTagLutBtoA::operator=.
virtual icTagTypeSignature GetType() const
Function: GetType()
Definition IccTagLut.h:535
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile=NULL)
Name: CIccTagLutBtoA::Validate.
CIccTagLutBtoA()
Name: CIccTagLutBtoA::CIccTagLutBtoA.
Class: CIccTagParametricCurve.
Definition IccTagLut.h:171
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile=NULL) const
Name: CIccTagParametricCurve::Validate.
virtual icFloatNumber Apply(icFloatNumber v) const
Name: CIccTagParametricCurve::Apply.
icUInt16Number m_nFunctionType
Definition IccTagLut.h:204
virtual bool IsIdentity()
Name: CIccTagParametricCurve::IsIdentity.
icFloatNumber * m_dParam
Definition IccTagLut.h:208
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccTagParametricCurve::Read.
CIccTagParametricCurve()
Name: CIccTagParametricCurve::CIccTagParametricCurve.
virtual void DumpLut(std::string &sDescription, const icChar *szName, icColorSpaceSignature csSig, int nIndex, int nVerboseness)
Name: CIccTagParametricCurve::DumpLut.
virtual ~CIccTagParametricCurve()
Name: CIccTagParametricCurve::~CIccTagParametricCurve.
virtual bool Write(CIccIO *pIO)
Name: CIccTagParametricCurve::Write.
icUInt16Number m_nNumParam
Definition IccTagLut.h:205
CIccTagParametricCurve & operator=(const CIccTagParametricCurve &ParamCurveTag)
Name: CIccTagParametricCurve::operator=.
bool SetFunctionType(icUInt16Number nFunctionType)
Name: CIccTagParametricCurve::SetFunctionType.
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccTagParametricCurve::Describe.
Class: CIccTagSegmentedCurve.
Definition IccTagLut.h:221
virtual void DumpLut(std::string &sDescription, const icChar *szName, icColorSpaceSignature csSig, int nIndex, int nVerboseness)
Name: CIccTagSegmentedCurve::DumpLut.
virtual icValidateStatus Validate(std::string sigPath, std::string &sReport, const CIccProfile *pProfile=NULL) const
Name: CIccTagSegmentedCurve::Validate.
CIccTagSegmentedCurve & operator=(const CIccTagSegmentedCurve &CurveTag)
Name: CIccTagSegmentedCurve::CIccTagSegmentedCurve.
virtual void Begin()
Name: CIccTagSegmentedCurve::Begin.
void SetCurve(CIccSegmentedCurve *pCurve)
Name: CIccTagSegmentedCurve::SetCurve.
virtual void Describe(std::string &sDescription, int nVerboseness)
Name: CIccTagSegmentedCurve::Describe.
virtual ~CIccTagSegmentedCurve()
Name: CIccTagSegmentedCurve::~CIccTagSegmentedCurve.
virtual bool Read(icUInt32Number size, CIccIO *pIO)
Name: CIccTagSegmentedCurve::Read.
virtual bool Write(CIccIO *pIO)
Name: CIccTagSegmentedCurve::Write.
virtual bool IsIdentity()
Name: CIccTagSegmentedCurve::IsIdentity.
CIccTagSegmentedCurve()
Name: CIccTagSegmentedCurve::CIccTagSegmentedCurve.
CIccSegmentedCurve * m_pCurve
Definition IccTagLut.h:248
virtual icFloatNumber Apply(icFloatNumber v) const
Name: CIccTagSegmentedCurve::Apply.
Interface Class: IIccCLUTExec.
Definition IccTagLut.h:285
virtual void PixelOp(icFloatNumber *pGridAdr, icFloatNumber *pData)=0
unsigned char icUInt8Number
Number definitions.
float icFloat32Number
unsigned short icUInt16Number
long icInt32Number
short icInt16Number
icColorSpaceSignature
Color Space Signatures.
@ icSigXYZData
@ icSigMCH1Data
icUInt32Number icSignature
@ icSigParametricCurveType
@ icSigLut8Type
@ icSigLutBtoAType
@ icSigCurveType
@ icSigLut16Type
@ icSigLutAtoBType
icUInt32Number icUInt64Number[2]
#define icSigUnknownData
icInt32Number icS15Fixed16Number
Fixed numbers.
@ icSigGrayTRCTag
@ icSigBToA2Tag
@ icSigAToB3Tag
@ icSigHToS3Tag
@ icSigGreenTRCTag
@ icSigHToS2Tag
@ icSigAToB0Tag
@ icSigBToA1Tag
@ icSigAToB2Tag
@ icSigBToA0Tag
@ icSigRedTRCTag
@ icSigHToS1Tag
@ icSigBlueTRCTag
@ icSigHToS0Tag
@ icSigAToB1Tag
@ icSigBToA3Tag
@ icSigGamutTag
static icFloatNumber UnitClip(icFloatNumber v)