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-2010 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 #if defined(WIN32) || defined(WIN64)
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
85 #ifdef USESAMPLEICCNAMESPACE
86 namespace sampleICC {
87 #endif
88
89 /**
90 ****************************************************************************
91 * Name: CIccCurve::Find
92 *
93 * Purpose: Read in the tag contents into a data block
94 *
95 * Args:
96 * v = index to be searched,
97 * v0 = index less than/equal to v,
98 * p0 = the value at index v0,
99 * v1 = index greater than/equal to v,
100 * p1 = value at index v1
101 *
102 * Return: The value at the requested index
103 *
104 *****************************************************************************
105 */
Find(icFloatNumber v,icFloatNumber p0,icFloatNumber v0,icFloatNumber p1,icFloatNumber v1)106 icFloatNumber CIccCurve::Find(icFloatNumber v,
107 icFloatNumber p0, icFloatNumber v0,
108 icFloatNumber p1, icFloatNumber v1)
109 {
110 if (v<=v0)
111 return p0;
112 if (v>=v1)
113 return p1;
114
115 if (p1-p0 <= 0.00001) {
116 icFloatNumber d0 = fabs(v-v0);
117 icFloatNumber d1 = fabs(v1-v);
118
119 if (d0<d1)
120 return p0;
121 return p1;
122 }
123
124 icFloatNumber np = (icFloatNumber)((p0 + p1)/2.0);
125 icFloatNumber nv = Apply(np);
126
127 if (v<=nv) {
128 return Find(v, p0, v0, np, nv);
129 }
130 return Find(v, np, nv, p1, v1);
131 }
132
133
134 /**
135 ****************************************************************************
136 * Name: CIccTagCurve::CIccTagCurve
137 *
138 * Purpose: Constructor
139 *
140 *****************************************************************************
141 */
CIccTagCurve(int nSize)142 CIccTagCurve::CIccTagCurve(int nSize/*=0*/)
143 {
144 m_nSize = nSize;
145 if (m_nSize <0)
146 m_nSize = 0;
147 if (m_nSize>0)
148 m_Curve = (icFloatNumber*)calloc(nSize, sizeof(icFloatNumber));
149 else
150 m_Curve = NULL;
151 }
152
153
154 /**
155 ****************************************************************************
156 * Name: CIccTagCurve::CIccTagCurve
157 *
158 * Purpose: Copy Constructor
159 *
160 * Args:
161 * ITCurve = The CIccTagCurve object to be copied
162 *****************************************************************************
163 */
CIccTagCurve(const CIccTagCurve & ITCurve)164 CIccTagCurve::CIccTagCurve(const CIccTagCurve &ITCurve)
165 {
166 m_nSize = ITCurve.m_nSize;
167 m_nMaxIndex = ITCurve.m_nMaxIndex;
168
169 m_Curve = (icFloatNumber*)calloc(m_nSize, sizeof(icFloatNumber));
170 memcpy(m_Curve, ITCurve.m_Curve, m_nSize*sizeof(icFloatNumber));
171 }
172
173
174 /**
175 ****************************************************************************
176 * Name: CIccTagCurve::operator=
177 *
178 * Purpose: Copy Operator
179 *
180 * Args:
181 * CurveTag = The CIccTagCurve object to be copied
182 *****************************************************************************
183 */
operator =(const CIccTagCurve & CurveTag)184 CIccTagCurve &CIccTagCurve::operator=(const CIccTagCurve &CurveTag)
185 {
186 if (&CurveTag == this)
187 return *this;
188
189 m_nSize = CurveTag.m_nSize;
190 m_nMaxIndex = CurveTag.m_nMaxIndex;
191
192 if (m_Curve)
193 free(m_Curve);
194 m_Curve = (icFloatNumber*)calloc(m_nSize, sizeof(icFloatNumber));
195 memcpy(m_Curve, CurveTag.m_Curve, m_nSize*sizeof(icFloatNumber));
196
197 return *this;
198 }
199
200
201 /**
202 ****************************************************************************
203 * Name: CIccTagCurve::~CIccTagCurve
204 *
205 * Purpose: Destructor
206 *
207 *****************************************************************************
208 */
~CIccTagCurve()209 CIccTagCurve::~CIccTagCurve()
210 {
211 if (m_Curve)
212 free(m_Curve);
213 }
214
215
216 /**
217 ****************************************************************************
218 * Name: CIccTagCurve::Read
219 *
220 * Purpose: Read in the tag contents into a data block
221 *
222 * Args:
223 * size - # of bytes in tag,
224 * pIO - IO object to read tag from
225 *
226 * Return:
227 * true = successful, false = failure
228 *****************************************************************************
229 */
Read(icUInt32Number size,CIccIO * pIO)230 bool CIccTagCurve::Read(icUInt32Number size, CIccIO *pIO)
231 {
232 icTagTypeSignature sig;
233
234 if (sizeof(icTagTypeSignature) +
235 sizeof(icUInt32Number) +
236 sizeof(icUInt32Number) > 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 SetSize(nSize, icInitNone);
255
256 if (m_nSize) {
257 if (pIO->Read16Float(m_Curve, m_nSize)!=(icInt32Number)m_nSize)
258 return false;
259 }
260
261 return true;
262 }
263
264
265 /**
266 ****************************************************************************
267 * Name: CIccTagCurve::Write
268 *
269 * Purpose: Write the tag to a file
270 *
271 * Args:
272 * pIO - The IO object to write tag to.
273 *
274 * Return:
275 * true = succesful, false = failure
276 *****************************************************************************
277 */
Write(CIccIO * pIO)278 bool CIccTagCurve::Write(CIccIO *pIO)
279 {
280 icTagTypeSignature sig = GetType();
281
282 if (!pIO)
283 return false;
284
285 if (!pIO->Write32(&sig))
286 return false;
287
288 if (!pIO->Write32(&m_nReserved))
289 return false;
290
291 if (!pIO->Write32(&m_nSize))
292 return false;
293
294 if (m_nSize)
295 if (pIO->Write16Float(m_Curve, m_nSize)!=(icInt32Number)m_nSize)
296 return false;
297
298 pIO->Align32();
299
300 return true;
301 }
302
303
304 /**
305 ****************************************************************************
306 * Name: CIccTagCurve::Describe
307 *
308 * Purpose: Dump data associated with the tag to a string
309 *
310 * Args:
311 * sDescription - string to concatenate tag dump to
312 *****************************************************************************
313 */
Describe(std::string & sDescription)314 void CIccTagCurve::Describe(std::string &sDescription)
315 {
316 icChar buf[128], *ptr;
317
318 if (!m_nSize) {
319 sprintf(buf, "BEGIN_CURVE In_Out\r\n");
320 sDescription += buf;
321 sDescription += "Y = X\r\n";
322 }
323 else if (m_nSize==1) {
324 icFloatNumber dGamma = (icFloatNumber)(m_Curve[0] * 256.0);
325 sprintf(buf, "BEGIN_CURVE In_Out\r\n");
326 sDescription += buf;
327 sprintf(buf, "Y = X ^ %.4lf\r\n", dGamma);
328 sDescription += buf;
329 }
330 else {
331 int i;
332
333 sprintf(buf, "BEGIN_LUT In_Out 1 1\r\n");
334 sDescription += buf;
335 sDescription += "IN OUT\r\n";
336
337 for (i=0; i<(int)m_nSize; i++) {
338 ptr = buf;
339
340 icColorValue(buf, (icFloatNumber)i/(m_nSize-1), icSigMCH1Data, 1);
341 ptr += strlen(buf);
342
343 strcpy(ptr, " ");
344 ptr ++;
345
346 icColorValue(ptr, m_Curve[i], icSigMCH1Data, 1);
347
348 ptr += strlen(ptr);
349
350 strcpy(ptr, "\r\n");
351
352 sDescription += buf;
353 }
354 }
355 sDescription += "\r\n";
356 }
357
358
359 /**
360 ****************************************************************************
361 * Name: CIccTagCurve::DumpLut
362 *
363 * Purpose: Dump data associated with the tag to a string. Basically has
364 * the same function as Describe()
365 *
366 * Args:
367 * sDescription = string to concatenate tag dump to,
368 * szName = name of the curve to be printed,
369 * csSig = color space signature of the LUT data,
370 * nIndex = the channel number of color space
371 *****************************************************************************
372 */
DumpLut(std::string & sDescription,const icChar * szName,icColorSpaceSignature csSig,int nIndex)373 void CIccTagCurve::DumpLut(std::string &sDescription, const icChar *szName,
374 icColorSpaceSignature csSig, int nIndex)
375 {
376 icChar buf[128], *ptr;
377
378 if (!m_nSize) {
379 sprintf(buf, "BEGIN_CURVE %s\r\n", szName);
380 sDescription += buf;
381 sDescription += "Y = X\r\n";
382 }
383 else if (m_nSize==1) {
384 icFloatNumber dGamma = (icFloatNumber)(m_Curve[0] * 256.0);
385 sprintf(buf, "BEGIN_CURVE %s\r\n", szName);
386 sDescription += buf;
387 sprintf(buf, "Y = X ^ %.4lf\r\n", dGamma);
388 sDescription += buf;
389 }
390 else {
391 int i;
392
393 sprintf(buf, "BEGIN_LUT %s 1 1\r\n", szName);
394 sDescription += buf;
395 sDescription += "IN OUT\r\n";
396
397 sDescription.reserve(sDescription.size() + m_nSize * 20);
398
399 for (i=0; i<(int)m_nSize; i++) {
400 ptr = buf;
401
402 icColorValue(buf, (icFloatNumber)i/(m_nSize-1), csSig, nIndex);
403 ptr += strlen(buf);
404
405 strcpy(ptr, " ");
406 ptr ++;
407
408 icColorValue(ptr, m_Curve[i], csSig, nIndex);
409
410 ptr += strlen(ptr);
411
412 strcpy(ptr, "\r\n");
413
414 sDescription += buf;
415 }
416 }
417 sDescription += "\r\n";
418 }
419
420
421 /**
422 ****************************************************************************
423 * Name: CIccTagCurve::SetSize
424 *
425 * Purpose: Sets the size of the curve array.
426 *
427 * Args:
428 * nSize - number of entries in the curve,
429 * nSizeOpt - flag to zero newly formed values
430 *****************************************************************************
431 */
SetSize(icUInt32Number nSize,icTagCurveSizeInit nSizeOpt)432 void CIccTagCurve::SetSize(icUInt32Number nSize, icTagCurveSizeInit nSizeOpt/*=icInitZero*/)
433 {
434 if (nSize==m_nSize)
435 return;
436
437 if (!nSize && m_Curve) {
438 free(m_Curve);
439 m_Curve = NULL;
440 }
441 else {
442 if (!m_Curve)
443 m_Curve = (icFloatNumber*)malloc(nSize*sizeof(icFloatNumber));
444 else
445 m_Curve = (icFloatNumber*)realloc(m_Curve, nSize*sizeof(icFloatNumber));
446
447 switch (nSizeOpt) {
448 case icInitNone:
449 default:
450 break;
451
452 case icInitZero:
453 if (m_nSize < nSize) {
454 memset(&m_Curve[m_nSize], 0, (nSize-m_nSize)*sizeof(icFloatNumber));
455 }
456 break;
457
458 case icInitIdentity:
459 if (nSize>1) {
460 icUInt32Number i;
461 icFloatNumber last = (icFloatNumber)(nSize-1);
462
463 for (i=0; i<nSize; i++) {
464 m_Curve[i] = (icFloatNumber)i/last;
465 }
466 }
467 else if (nSize==1) {
468 //Encode a gamma 1.0 u8Fixed8Number converted to 16 bit as a 0.0 to 1.0 float
469 m_Curve[0] = (icFloatNumber)(0x0100) / (icFloatNumber)65535.0;
470 }
471 break;
472 }
473 }
474 m_nSize = nSize;
475 m_nMaxIndex = (icUInt16Number)(nSize - 1);
476 }
477
478 /**
479 ****************************************************************************
480 * Name: sampleICC::CIccTagCurve::SetGamma
481 *
482 * Purpose: Set the curve with a single gamma value.
483 *
484 * Args:
485 * gamma - gamma value to use
486 *****************************************************************************
487 */
SetGamma(icFloatNumber gamma)488 void CIccTagCurve::SetGamma(icFloatNumber gamma)
489 {
490 SetSize(1, icInitNone);
491
492 icInt16Number whole = (icInt16Number)gamma;
493 icFloatNumber frac = gamma - (icFloatNumber)whole;
494
495 m_Curve[0] = (icFloatNumber)((whole * 256) + (frac*256.0)) / (icFloatNumber)65535.0;
496 }
497
498 /**
499 ****************************************************************************
500 *
501 *****************************************************************************
502 */
503 const icFloatNumber VERYSMALLNUM = (icFloatNumber)0.0000001;
IsUnity(const icFloatNumber & num)504 static bool IsUnity(const icFloatNumber& num)
505 {
506 return (num>(1.0-VERYSMALLNUM) && num<(1.0+VERYSMALLNUM));
507 }
508
509 /**
510 ****************************************************************************
511 * Name: CIccTagCurve::IsIdentity
512 *
513 * Purpose: Checks if this is an identity curve.
514 *
515 * Return: true if the curve is an identity
516 *
517 *****************************************************************************
518 */
IsIdentity()519 bool CIccTagCurve::IsIdentity()
520 {
521 if (!m_nSize) {
522 return true;
523 }
524
525 if (m_nSize==1) {
526 return IsUnity(icFloatNumber(m_Curve[0]*65535.0/256.0));
527 }
528
529 icUInt32Number i;
530 for (i=0; i<m_nSize; i++) {
531 if (fabs(m_Curve[i]-((icFloatNumber)i/(icFloatNumber)m_nMaxIndex))>VERYSMALLNUM) {
532 return false;
533 }
534 }
535
536 return true;
537 }
538
539 /**
540 ****************************************************************************
541 * Name: CIccTagCurve::Apply
542 *
543 * Purpose: Applies the curve to the value passed.
544 *
545 * Args:
546 * v = value to be passed through the curve.
547 *
548 * Return: The value modified by the curve.
549 *
550 *****************************************************************************
551 */
Apply(icFloatNumber v)552 icFloatNumber CIccTagCurve::Apply(icFloatNumber v)
553 {
554 if(v<0.0) v = 0.0;
555 else if(v>1.0) v = 1.0;
556
557 icUInt32Number nIndex = (icUInt32Number)(v * m_nMaxIndex);
558
559 if (!m_nSize) {
560 return v;
561 }
562 if (m_nSize==1) {
563 //Convert 0.0 to 1.0 float to 16bit and then convert from u8Fixed8Number
564 icFloatNumber dGamma = (icFloatNumber)(m_Curve[0] * 65535.0 / 256.0);
565 return pow(v, dGamma);
566 }
567 if (nIndex == m_nMaxIndex) {
568 return m_Curve[nIndex];
569 }
570 else {
571 icFloatNumber nDif = v*m_nMaxIndex - nIndex;
572 icFloatNumber p0 = m_Curve[nIndex];
573
574 icFloatNumber rv = p0 + (m_Curve[nIndex+1]-p0)*nDif;
575 if (rv>1.0)
576 rv=1.0;
577
578 return rv;
579 }
580 }
581
582
583 /**
584 ******************************************************************************
585 * Name: CIccTagCurve::Validate
586 *
587 * Purpose: Check tag data validity.
588 *
589 * Args:
590 * sig = signature of tag being validated,
591 * sReport = String to add report information to
592 *
593 * Return:
594 * icValidateStatusOK if valid, or other error status.
595 ******************************************************************************
596 */
Validate(icTagSignature sig,std::string & sReport,const CIccProfile * pProfile) const597 icValidateStatus CIccTagCurve::Validate(icTagSignature sig, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
598 {
599 icValidateStatus rv = CIccTag::Validate(sig, sReport, pProfile);
600
601 CIccInfo Info;
602 std::string sSigName = Info.GetSigName(sig);
603
604 if (sig==icSigBlueTRCTag || sig==icSigRedTRCTag || sig==icSigGreenTRCTag || sig==icSigGrayTRCTag) {
605 if (m_nSize>1) {
606 if (m_Curve) {
607 if (m_Curve[0]>0.0 || m_Curve[m_nSize-1]<1.0) {
608 sReport += icValidateWarningMsg;
609 sReport += sSigName;
610 sReport += " - Curve cannot be accurately inverted.\r\n";
611 rv = icMaxStatus(rv, icValidateWarning);
612 }
613 }
614 }
615 }
616
617 return rv;
618 }
619
620
621 /**
622 ****************************************************************************
623 * Name: CIccTagParametricCurve::CIccTagParametricCurve
624 *
625 * Purpose: Constructor
626 *
627 *****************************************************************************
628 */
CIccTagParametricCurve()629 CIccTagParametricCurve::CIccTagParametricCurve()
630 {
631 m_nFunctionType = 0xffff;
632 m_nNumParam = 0;
633 m_dParam = NULL;
634 m_nReserved2 = 0;
635 }
636
637
638 /**
639 ****************************************************************************
640 * Name: CIccTagParametricCurve::CIccTagParametricCurve
641 *
642 * Purpose: Copy Constructor
643 *
644 * Args:
645 * ITPC = The CIccTagParametricCurve object to be copied
646 *****************************************************************************
647 */
CIccTagParametricCurve(const CIccTagParametricCurve & ITPC)648 CIccTagParametricCurve::CIccTagParametricCurve(const CIccTagParametricCurve &ITPC)
649 {
650 m_nFunctionType = ITPC.m_nFunctionType;
651 m_nNumParam = ITPC.m_nNumParam;
652
653 m_dParam = new icFloatNumber[m_nNumParam];
654 memcpy(m_dParam, ITPC.m_dParam, m_nNumParam*sizeof(icFloatNumber));
655 }
656
657
658 /**
659 ****************************************************************************
660 * Name: CIccTagParametricCurve::operator=
661 *
662 * Purpose: Copy Operator
663 *
664 * Args:
665 * ParamCurveTag = The CIccTagParametricCurve object to be copied
666 *****************************************************************************
667 */
operator =(const CIccTagParametricCurve & ParamCurveTag)668 CIccTagParametricCurve &CIccTagParametricCurve::operator=(const CIccTagParametricCurve &ParamCurveTag)
669 {
670 if (&ParamCurveTag == this)
671 return *this;
672
673 m_nFunctionType = ParamCurveTag.m_nFunctionType;
674 m_nNumParam = ParamCurveTag.m_nNumParam;
675
676 if (m_dParam)
677 delete [] m_dParam;
678 m_dParam = new icFloatNumber[m_nNumParam];
679 memcpy(m_dParam, ParamCurveTag.m_dParam, m_nNumParam*sizeof(icFloatNumber));
680
681 return *this;
682 }
683
684
685 /**
686 ****************************************************************************
687 * Name: CIccTagParametricCurve::~CIccTagParametricCurve
688 *
689 * Purpose: Destructor
690 *
691 *****************************************************************************
692 */
~CIccTagParametricCurve()693 CIccTagParametricCurve::~CIccTagParametricCurve()
694 {
695 if (m_dParam)
696 delete [] m_dParam;
697 }
698
699
700 /**
701 ****************************************************************************
702 * Name: CIccTagParametricCurve::Read
703 *
704 * Purpose: Read in the tag contents into a data block
705 *
706 * Args:
707 * size - # of bytes in tag,
708 * pIO - IO object to read tag from
709 *
710 * Return:
711 * true = successful, false = failure
712 *****************************************************************************
713 */
Read(icUInt32Number size,CIccIO * pIO)714 bool CIccTagParametricCurve::Read(icUInt32Number size, CIccIO *pIO)
715 {
716 icTagTypeSignature sig;
717 icUInt16Number nFunctionType;
718
719 icUInt32Number nHdrSize = sizeof(icTagTypeSignature) +
720 sizeof(icUInt32Number) +
721 2*sizeof(icUInt16Number);
722
723 if ( nHdrSize > size)
724 return false;
725
726 if (!pIO) {
727 return false;
728 }
729
730 if (!pIO->Read32(&sig) ||
731 !pIO->Read32(&m_nReserved) ||
732 !pIO->Read16(&nFunctionType) ||
733 !pIO->Read16(&m_nReserved2))
734 return false;
735
736 SetFunctionType(nFunctionType);
737
738 if (!m_nNumParam) {
739 m_nNumParam = (icUInt16Number)((size-nHdrSize) / sizeof(icS15Fixed16Number));
740 m_dParam = new icFloatNumber[m_nNumParam];
741 }
742
743 if (m_nNumParam) {
744 int i;
745 if (nHdrSize + m_nNumParam*sizeof(icS15Fixed16Number) > size)
746 return false;
747
748 for (i=0; i<m_nNumParam; i++) {
749 icS15Fixed16Number num;
750 if (!pIO->Read32(&num, 1))
751 return false;
752 m_dParam[i]=icFtoD(num);
753 }
754 }
755
756 return true;
757 }
758
759
760 /**
761 ****************************************************************************
762 * Name: CIccTagParametricCurve::Write
763 *
764 * Purpose: Write the tag to a file
765 *
766 * Args:
767 * pIO - The IO object to write tag to.
768 *
769 * Return:
770 * true = succesful, false = failure
771 *****************************************************************************
772 */
Write(CIccIO * pIO)773 bool CIccTagParametricCurve::Write(CIccIO *pIO)
774 {
775 icTagTypeSignature sig;
776
777 if (!pIO) {
778 return false;
779 }
780
781 sig = GetType();
782
783 if (!pIO->Write32(&sig) ||
784 !pIO->Write32(&m_nReserved) ||
785 !pIO->Write16(&m_nFunctionType) ||
786 !pIO->Write16(&m_nReserved2))
787 return false;
788
789 if (m_nNumParam) {
790 int i;
791 for (i=0; i<m_nNumParam; i++) {
792 icS15Fixed16Number num = icDtoF(m_dParam[i]);
793 if (!pIO->Write32(&num, 1))
794 return false;
795 }
796 }
797
798 if (!pIO->Align32())
799 return false;
800
801 return true;
802 }
803
804
805 /**
806 ****************************************************************************
807 * Name: CIccTagParametricCurve::Describe
808 *
809 * Purpose: Dump data associated with the tag to a string
810 *
811 * Args:
812 * sDescription - string to concatenate tag dump to
813 *****************************************************************************
814 */
Describe(std::string & sDescription)815 void CIccTagParametricCurve::Describe(std::string &sDescription)
816 {
817 icChar buf[128];
818
819 sprintf(buf, "FunctionType: %04Xh\r\n", m_nFunctionType);
820 sDescription += buf;
821
822 switch(m_nFunctionType) {
823 case 0x0000:
824 sprintf(buf, "Y = X ^ %.4lf\r\n", m_dParam[0]);
825 sDescription += buf;
826 return;
827
828 case 0x0001:
829 sprintf(buf, "Y = 0 when (X < %.4lf / %.4lf)\r\n",
830 -m_dParam[2], m_dParam[1]);
831 sDescription += buf;
832
833 sprintf(buf, "Y = (%.4lf * X + %.4lf) ^ %.4lf when (X >= %.4lf / %.4lf)\r\n",
834 m_dParam[1], m_dParam[2], m_dParam[0],
835 m_dParam[2], m_dParam[1]);
836 sDescription += buf;
837 return;
838
839 case 0x0002:
840 sprintf(buf, "Y = %.4lf when (X < %.4lf / %.4lf)\r\n", m_dParam[3],
841 -m_dParam[2], m_dParam[1]);
842 sDescription += buf;
843
844 sprintf(buf, "Y = (%.4lf * X + %.4lf) ^ %.4lf + %.4lf when (X >= %.4lf / %.4lf)\r\n",
845 m_dParam[1], m_dParam[2], m_dParam[0],
846 m_dParam[3],
847 -m_dParam[2], m_dParam[1]);
848 sDescription += buf;
849 return;
850
851 case 0x0003:
852 sprintf(buf, "Y = %lf * X when (X < %.4lf)\r\n",
853 m_dParam[3], m_dParam[4]);
854 sDescription += buf;
855
856 sprintf(buf, "Y = (%.4lf * X + %.4lf) ^ %.4lf when (X >= %.4lf)\r\n",
857 m_dParam[1], m_dParam[2], m_dParam[0],
858 m_dParam[4]);
859 sDescription += buf;
860 return;
861
862 case 0x0004:
863 sprintf(buf, "Y = %lf * X + %.4lf when (X < %.4lf)\r\n",
864 m_dParam[3], m_dParam[6], m_dParam[4]);
865 sDescription += buf;
866
867 sprintf(buf, "Y = (%.4lf * X + %.4lf) ^ %.4lf + %.4lf when (X >= %.4lf)\r\n",
868 m_dParam[1], m_dParam[2], m_dParam[0],
869 m_dParam[5], m_dParam[4]);
870 sDescription += buf;
871 return;
872
873 default:
874 int i;
875 sprintf(buf, "Unknown Function with %d parameters:\r\n", m_nNumParam);
876 sDescription += buf;
877
878 for (i=0; i<m_nNumParam; i++) {
879 sprintf(buf, "Param[%d] = %.4lf\r\n", i, m_dParam[i]);
880 sDescription += buf;
881 }
882 }
883 }
884
885 /**
886 ****************************************************************************
887 * Name: CIccTagParametricCurve::DumpLut
888 *
889 * Purpose: Dump data associated with the tag to a string. Basically has
890 * the same function as Describe()
891 *
892 * Args:
893 * sDescription = string to concatenate tag dump to,
894 * szName = name of the curve to be printed,
895 * csSig = color space signature of the curve data,
896 * nIndex = the channel number of color space
897 *****************************************************************************
898 */
DumpLut(std::string & sDescription,const icChar * szName,icColorSpaceSignature csSig,int nIndex)899 void CIccTagParametricCurve::DumpLut(std::string &sDescription, const icChar *szName,
900 icColorSpaceSignature csSig, int nIndex)
901 {
902 icChar buf[128];
903
904 sprintf(buf, "BEGIN_CURVE %s\r\n", szName);
905 sDescription += buf;
906 Describe(sDescription);
907 sDescription += "\r\n";
908 }
909
910
911 /**
912 ****************************************************************************
913 * Name: CIccTagParametricCurve::SetFunctionType
914 *
915 * Purpose: Sets the type of the function the Parametric curve represents
916 *
917 * Args:
918 * nFunctionType = the type of the function encoded as 0-4
919 *
920 * Return:
921 * always true!!
922 *****************************************************************************
923 */
SetFunctionType(icUInt16Number nFunctionType)924 bool CIccTagParametricCurve::SetFunctionType(icUInt16Number nFunctionType)
925 {
926 icUInt16Number nNumParam;
927
928 switch(nFunctionType) {
929 case 0x0000:
930 nNumParam = 1;
931 break;
932
933 case 0x0001:
934 nNumParam = 3;
935 break;
936
937 case 0x0002:
938 nNumParam = 4;
939 break;
940
941 case 0x0003:
942 nNumParam = 5;
943 break;
944
945 case 0x0004:
946 nNumParam = 7;
947 break;
948
949 default:
950 nNumParam = 0;
951 }
952
953 if (m_dParam)
954 delete m_dParam;
955 m_nNumParam = nNumParam;
956 m_nFunctionType = nFunctionType;
957
958 if (m_nNumParam)
959 m_dParam = new icFloatNumber[m_nNumParam];
960 else
961 m_dParam = NULL;
962
963 return true;
964 }
965
966
967 /**
968 ****************************************************************************
969 * Name: CIccTagParametricCurve::IsIdentity
970 *
971 * Purpose: Checks if this is an identity curve.
972 *
973 * Return: true if the curve is an identity
974 *
975 *****************************************************************************
976 */
IsIdentity()977 bool CIccTagParametricCurve::IsIdentity()
978 {
979 switch(m_nFunctionType) {
980 case 0x0000:
981 return IsUnity(m_dParam[0]);
982
983 case 0x0001:
984 case 0x0002:
985 case 0x0003:
986 case 0x0004:
987 return false;
988
989 default:
990 return true;
991 }
992 }
993
994 /**
995 ****************************************************************************
996 * Name: CIccTagParametricCurve::DoApply
997 *
998 * Purpose: Applies the curve to the value passed.
999 *
1000 * Args:
1001 * x = value to be passed through the curve.
1002 *
1003 * Return: The value modified by the curve.
1004 *
1005 *****************************************************************************
1006 */
DoApply(icFloatNumber X) const1007 icFloatNumber CIccTagParametricCurve::DoApply(icFloatNumber X) const
1008 {
1009 double a, b;
1010
1011 switch(m_nFunctionType) {
1012 case 0x0000:
1013 return pow(X, m_dParam[0]);
1014
1015 case 0x0001:
1016 a=m_dParam[1];
1017 b=m_dParam[2];
1018
1019 if (X >= -b/a) {
1020 return (icFloatNumber)pow((double)a*X + b, (double)m_dParam[0]);
1021 }
1022 else {
1023 return 0;
1024 }
1025
1026 case 0x0002:
1027 a=m_dParam[1];
1028 b=m_dParam[2];
1029
1030 if (X >= -b/a) {
1031 return (icFloatNumber)pow((double)a*X + b, (double)m_dParam[0]) + m_dParam[3];
1032 }
1033 else {
1034 return m_dParam[3];
1035 }
1036
1037 case 0x0003:
1038 if (X >= m_dParam[4]) {
1039 return (icFloatNumber)pow((double)m_dParam[1]*X + m_dParam[2], (double)m_dParam[0]);
1040 }
1041 else {
1042 return m_dParam[3]*X;
1043 }
1044
1045 case 0x0004:
1046 if (X >= m_dParam[4]) {
1047 return (icFloatNumber)pow((double)m_dParam[1]*X + m_dParam[2], (double)m_dParam[0]) + m_dParam[5];
1048 }
1049 else {
1050 return m_dParam[3]*X + m_dParam[6];
1051 }
1052
1053 default:
1054 return X;
1055 }
1056 }
1057
1058
1059 /**
1060 ******************************************************************************
1061 * Name: CIccTagParametricCurve::Validate
1062 *
1063 * Purpose: Check tag data validity.
1064 *
1065 * Args:
1066 * sig = signature of tag being validated,
1067 * sReport = String to add report information to
1068 *
1069 * Return:
1070 * icValidateStatusOK if valid, or other error status.
1071 ******************************************************************************
1072 */
Validate(icTagSignature sig,std::string & sReport,const CIccProfile * pProfile) const1073 icValidateStatus CIccTagParametricCurve::Validate(icTagSignature sig, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
1074 {
1075 icValidateStatus rv = CIccTag::Validate(sig, sReport, pProfile);
1076
1077 CIccInfo Info;
1078 std::string sSigName = Info.GetSigName(sig);
1079
1080 if (m_nReserved2!=0) {
1081 sReport += icValidateNonCompliantMsg;
1082 sReport += sSigName;
1083 sReport += " - Reserved Value must be zero.\r\n";
1084
1085 rv = icMaxStatus(rv, icValidateNonCompliant);
1086 }
1087
1088 switch(m_nFunctionType) {
1089 case 0x0000:
1090 if (m_nNumParam!=1) {
1091 sReport += icValidateCriticalErrorMsg;
1092 sReport += sSigName;
1093 sReport += " - Number of parameters inconsistent with function type.\r\n";
1094 rv = icMaxStatus(rv, icValidateCriticalError);
1095 }
1096 break;
1097
1098 case 0x0001:
1099 if (m_nNumParam!=3) {
1100 sReport += icValidateCriticalErrorMsg;
1101 sReport += sSigName;
1102 sReport += " - Number of parameters inconsistent with function type.\r\n";
1103 rv = icMaxStatus(rv, icValidateCriticalError);
1104 }
1105 break;
1106
1107 case 0x0002:
1108 if (m_nNumParam!=4) {
1109 sReport += icValidateCriticalErrorMsg;
1110 sReport += sSigName;
1111 sReport += " - Number of parameters inconsistent with function type.\r\n";
1112 rv = icMaxStatus(rv, icValidateCriticalError);
1113 }
1114 break;
1115
1116 case 0x0003:
1117 if (m_nNumParam!=5) {
1118 sReport += icValidateCriticalErrorMsg;
1119 sReport += sSigName;
1120 sReport += " - Number of parameters inconsistent with function type.\r\n";
1121 rv = icMaxStatus(rv, icValidateCriticalError);
1122 }
1123 break;
1124
1125 case 0x0004:
1126 if (m_nNumParam!=7) {
1127 sReport += icValidateCriticalErrorMsg;
1128 sReport += sSigName;
1129 sReport += " - Number of parameters inconsistent with function type.\r\n";
1130 rv = icMaxStatus(rv, icValidateCriticalError);
1131 }
1132 break;
1133
1134 default:
1135 sReport += icValidateCriticalErrorMsg;
1136 sReport += sSigName;
1137 sReport += " - Unknown function type.\r\n";
1138 rv = icMaxStatus(rv, icValidateCriticalError);
1139 }
1140
1141 if (sig==icSigBlueTRCTag || sig==icSigRedTRCTag || sig==icSigGreenTRCTag || sig==icSigGrayTRCTag) {
1142 icFloatNumber lval = DoApply(0.0);
1143 icFloatNumber uval = DoApply(1.0);
1144 if (lval>0.0 || uval<1.0) {
1145 sReport += icValidateWarningMsg;
1146 sReport += sSigName;
1147 sReport += " - Curve cannot be accurately inverted.\r\n";
1148 rv = icMaxStatus(rv, icValidateWarning);
1149 }
1150 }
1151
1152 return rv;
1153 }
1154
1155 /**
1156 ****************************************************************************
1157 * Name: CIccMatrix::CIccMatrix
1158 *
1159 * Purpose: Constructor
1160 *
1161 * Args:
1162 * bUseConstants = true if the matrix contains additional row for constants
1163 *****************************************************************************
1164 */
CIccMatrix(bool bUseConstants)1165 CIccMatrix::CIccMatrix(bool bUseConstants/*=true*/)
1166 {
1167 m_bUseConstants = bUseConstants;
1168 m_e[0] = m_e[4] = m_e[8] = 1.0;
1169 m_e[1] = m_e[2] = m_e[3] =
1170 m_e[5] = m_e[6] = m_e[7] = 0.0;
1171
1172 if (!m_bUseConstants) {
1173 m_e[9] = m_e[10] = m_e[11] = 0.0;
1174 }
1175 }
1176
1177
1178 /**
1179 ****************************************************************************
1180 * Name: CIccMatrix::CIccMatrix
1181 *
1182 * Purpose: Copy Constructor
1183 *
1184 * Args:
1185 * MatrixClass = The CIccMatrix object to be copied
1186 *****************************************************************************
1187 */
CIccMatrix(const CIccMatrix & MatrixClass)1188 CIccMatrix::CIccMatrix(const CIccMatrix &MatrixClass)
1189 {
1190 m_bUseConstants = MatrixClass.m_bUseConstants;
1191 memcpy(m_e, MatrixClass.m_e, sizeof(m_e));
1192 }
1193
1194
1195 /**
1196 ****************************************************************************
1197 * Name: CIccMatrix::operator=
1198 *
1199 * Purpose: Copy Operator
1200 *
1201 * Args:
1202 * MatrixClass = The CIccMatrix object to be copied
1203 *****************************************************************************
1204 */
operator =(const CIccMatrix & MatrixClass)1205 CIccMatrix &CIccMatrix::operator=(const CIccMatrix &MatrixClass)
1206 {
1207 if (&MatrixClass == this)
1208 return *this;
1209
1210 m_bUseConstants = MatrixClass.m_bUseConstants;
1211 memcpy(m_e, MatrixClass.m_e, sizeof(m_e));
1212
1213 return *this;
1214 }
1215
1216
1217 /**
1218 ****************************************************************************
1219 * Name: CIccTagParametricCurve::DumpLut
1220 *
1221 * Purpose: Dump the matrix data to a string.
1222 *
1223 * Args:
1224 * sDescription = string to concatenate tag dump to,
1225 * szName = name of the curve to be printed
1226 *****************************************************************************
1227 */
DumpLut(std::string & sDescription,const icChar * szName)1228 void CIccMatrix::DumpLut(std::string &sDescription, const icChar *szName)
1229 {
1230 icChar buf[128];
1231
1232 sprintf(buf, "BEGIN_MATRIX %s\r\n", szName);
1233 sDescription += buf;
1234
1235 if (!m_bUseConstants) {
1236 sprintf(buf, "%8.4lf %8.4lf %8.4lf\r\n",
1237 m_e[0], m_e[1], m_e[2]);
1238 sDescription += buf;
1239 sprintf(buf, "%8.4lf %8.4lf %8.4lf\r\n",
1240 m_e[3], m_e[4], m_e[5]);
1241 sDescription += buf;
1242 sprintf(buf, "%8.4lf %8.4lf %8.4lf\r\n",
1243 m_e[6], m_e[7], m_e[8]);
1244 sDescription += buf;
1245 }
1246 else {
1247 sprintf(buf, "%8.4lf %8.4lf %8.4lf + %8.4lf\r\n",
1248 m_e[0], m_e[1], m_e[2], m_e[9]);
1249 sDescription += buf;
1250 sprintf(buf, "%8.4lf %8.4lf %8.4lf + %8.4lf\r\n",
1251 m_e[3], m_e[4], m_e[5], m_e[10]);
1252 sDescription += buf;
1253 sprintf(buf, "%8.4lf %8.4lf %8.4lf + %8.4lf\r\n",
1254 m_e[6], m_e[7], m_e[8], m_e[11]);
1255 sDescription += buf;
1256 }
1257 sDescription += "\r\n";
1258 }
1259
1260 /**
1261 ****************************************************************************
1262 * Name: CIccMatrix::IsIdentity
1263 *
1264 * Purpose: Checks if the matrix is identity
1265 *
1266 * Return:
1267 * true if matrix is identity and uses no constants, else false
1268 *
1269 *****************************************************************************
1270 */
IsIdentity()1271 bool CIccMatrix::IsIdentity()
1272 {
1273 if (m_bUseConstants) {
1274 if (fabs(m_e[9])>0.0 || fabs(m_e[10])>0.0 || fabs(m_e[11])>0.0) {
1275 return false;
1276 }
1277 }
1278
1279 if (!IsUnity(m_e[0]) || !IsUnity(m_e[4]) || !IsUnity(m_e[8])) {
1280 return false;
1281 }
1282
1283 if (fabs(m_e[1])>0.0 || fabs(m_e[2])>0.0 || fabs(m_e[3])>0.0 ||
1284 fabs(m_e[5])>0.0 || fabs(m_e[6])>0.0 || fabs(m_e[7])>0.0)
1285 {
1286 return false;
1287 }
1288
1289 return true;
1290 }
1291
1292 /**
1293 ****************************************************************************
1294 * Name: CIccMatrix::Apply
1295 *
1296 * Purpose: Multiplies the pixel by the matrix.
1297 *
1298 * Args:
1299 * Pixel = Pixel to be multiplied by the matrix
1300 *
1301 *****************************************************************************
1302 */
Apply(icFloatNumber * Pixel) const1303 void CIccMatrix::Apply(icFloatNumber *Pixel) const
1304 {
1305 icFloatNumber a=Pixel[0];
1306 icFloatNumber b=Pixel[1];
1307 icFloatNumber c=Pixel[2];
1308
1309 icFloatNumber x = m_e[0]*a + m_e[1]*b + m_e[2]*c;
1310 icFloatNumber y = m_e[3]*a + m_e[4]*b + m_e[5]*c;
1311 icFloatNumber z = m_e[6]*a + m_e[7]*b + m_e[8]*c;
1312
1313 if (m_bUseConstants) {
1314 x += m_e[9];
1315 y += m_e[10];
1316 z += m_e[11];
1317 }
1318
1319 Pixel[0] = x;
1320 Pixel[1] = y;
1321 Pixel[2] = z;
1322 }
1323
1324
1325 /**
1326 ******************************************************************************
1327 * Name: CIccMatrix::Validate
1328 *
1329 * Purpose: Check tag data validity.
1330 *
1331 * Args:
1332 * sig = signature of tag being validated,
1333 * sReport = String to add report information to
1334 *
1335 * Return:
1336 * icValidateStatusOK if valid, or other error status.
1337 ******************************************************************************
1338 */
Validate(icTagTypeSignature sig,std::string & sReport,const CIccProfile * pProfile) const1339 icValidateStatus CIccMatrix::Validate(icTagTypeSignature sig, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
1340 {
1341 icValidateStatus rv = icValidateOK;
1342
1343 if (sig==icSigLut8Type || sig==icSigLut16Type) {
1344 if (pProfile->m_Header.pcs!=icSigXYZData) {
1345 CIccInfo Info;
1346 std::string sSigName = Info.GetSigName(sig);
1347 icFloatNumber sum=0.0;
1348 for (int i=0; i<9; i++) {
1349 sum += m_e[i];
1350 }
1351 if (m_e[0]!=1.0 || m_e[4]!=1.0 || m_e[9]!=1.0 || sum!=3.0) {
1352 sReport += icValidateNonCompliantMsg;
1353 sReport += sSigName;
1354 sReport += " - Matrix must be identity.\r\n";
1355 rv = icValidateNonCompliant;
1356 }
1357 }
1358 }
1359
1360 return rv;
1361 }
1362
1363
ClutUnitClip(icFloatNumber v)1364 static icFloatNumber ClutUnitClip(icFloatNumber v)
1365 {
1366 if (v<0)
1367 return 0;
1368 else if (v>1.0)
1369 return 1.0;
1370
1371 return v;
1372 }
1373
1374 /**
1375 ****************************************************************************
1376 * Name: CIccCLUT::CIccCLUT
1377 *
1378 * Purpose: Constructor
1379 *
1380 * Args:
1381 * nInputChannels = number of input channels,
1382 * nOutputChannels = number of output channels
1383 *
1384 *****************************************************************************
1385 */
CIccCLUT(icUInt8Number nInputChannels,icUInt16Number nOutputChannels,icUInt8Number nPrecision)1386 CIccCLUT::CIccCLUT(icUInt8Number nInputChannels, icUInt16Number nOutputChannels, icUInt8Number nPrecision/*=2*/)
1387 {
1388 m_nInput = nInputChannels;
1389 m_nOutput = nOutputChannels;
1390 m_nPrecision = nPrecision;
1391 m_pData = NULL;
1392 m_nOffset = NULL;
1393 m_g = NULL;
1394 m_ig = NULL;
1395 m_s = NULL;
1396 m_df = NULL;
1397 memset(&m_nReserved2, 0 , sizeof(m_nReserved2));
1398
1399 UnitClip = ClutUnitClip;
1400 }
1401
1402
1403 /**
1404 ****************************************************************************
1405 * Name: CIccCLUT::CIccCLUT
1406 *
1407 * Purpose: Copy Constructor
1408 *
1409 * Args:
1410 * ICLUT = The CIccCLUT object to be copied
1411 *****************************************************************************
1412 */
CIccCLUT(const CIccCLUT & ICLUT)1413 CIccCLUT::CIccCLUT(const CIccCLUT &ICLUT)
1414 {
1415 m_pData = NULL;
1416 m_nOffset = NULL;
1417 m_g = NULL;
1418 m_ig = NULL;
1419 m_s = NULL;
1420 m_df = NULL;
1421 m_nInput = ICLUT.m_nInput;
1422 m_nOutput = ICLUT.m_nOutput;
1423 m_nPrecision = ICLUT.m_nPrecision;
1424 m_nNumPoints = ICLUT.m_nNumPoints;
1425
1426 m_csInput = ICLUT.m_csInput;
1427 m_csOutput = ICLUT.m_csOutput;
1428
1429 memcpy(m_GridPoints, ICLUT.m_GridPoints, sizeof(m_GridPoints));
1430 memcpy(m_DimSize, ICLUT.m_DimSize, sizeof(m_DimSize));
1431 memcpy(m_GridAdr, ICLUT.m_GridAdr, sizeof(m_GridAdr));
1432 memcpy(&m_nReserved2, &ICLUT.m_nReserved2, sizeof(m_nReserved2));
1433
1434 int num = NumPoints()*m_nOutput;
1435 m_pData = new icFloatNumber[num];
1436 memcpy(m_pData, ICLUT.m_pData, num*sizeof(icFloatNumber));
1437
1438 UnitClip = ICLUT.UnitClip;
1439 }
1440
1441
1442 /**
1443 ****************************************************************************
1444 * Name: CIccCLUT::operator=
1445 *
1446 * Purpose: Copy Operator
1447 *
1448 * Args:
1449 * CLUTTag = The CIccCLUT object to be copied
1450 *****************************************************************************
1451 */
operator =(const CIccCLUT & CLUTTag)1452 CIccCLUT &CIccCLUT::operator=(const CIccCLUT &CLUTTag)
1453 {
1454 if (&CLUTTag == this)
1455 return *this;
1456
1457 m_nInput = CLUTTag.m_nInput;
1458 m_nOutput = CLUTTag.m_nOutput;
1459 m_nPrecision = CLUTTag.m_nPrecision;
1460 m_nNumPoints = CLUTTag.m_nNumPoints;
1461
1462 m_csInput = CLUTTag.m_csInput;
1463 m_csOutput = CLUTTag.m_csOutput;
1464
1465 memcpy(m_GridPoints, CLUTTag.m_GridPoints, sizeof(m_GridPoints));
1466 memcpy(m_DimSize, CLUTTag.m_DimSize, sizeof(m_DimSize));
1467 memcpy(m_GridAdr, CLUTTag.m_GridAdr, sizeof(m_GridAdr));
1468 memcpy(m_nReserved2, &CLUTTag.m_nReserved2, sizeof(m_nReserved2));
1469
1470 int num;
1471 if (m_pData)
1472 delete [] m_pData;
1473 num = NumPoints()*m_nOutput;
1474 m_pData = new icFloatNumber[num];
1475 memcpy(m_pData, CLUTTag.m_pData, num*sizeof(icFloatNumber));
1476
1477 UnitClip = CLUTTag.UnitClip;
1478
1479 return *this;
1480 }
1481
1482
1483
1484 /**
1485 ****************************************************************************
1486 * Name: CIccCLUT::~CIccCLUT
1487 *
1488 * Purpose: Destructor
1489 *
1490 *****************************************************************************
1491 */
~CIccCLUT()1492 CIccCLUT::~CIccCLUT()
1493 {
1494 if (m_pData)
1495 delete [] m_pData;
1496
1497 if (m_nOffset)
1498 delete [] m_nOffset;
1499
1500 if (m_g)
1501 delete [] m_g;
1502
1503 if (m_ig)
1504 delete [] m_ig;
1505
1506 if (m_s)
1507 delete [] m_s;
1508
1509 if (m_df)
1510 delete [] m_df;
1511 }
1512
1513 /**
1514 ****************************************************************************
1515 * Name: CIccCLUT::Init
1516 *
1517 * Purpose: Initializes and sets the size of the CLUT
1518 *
1519 * Args:
1520 * nGridPoints = number of grid points in the CLUT
1521 *****************************************************************************
1522 */
Init(icUInt8Number nGridPoints)1523 bool CIccCLUT::Init(icUInt8Number nGridPoints)
1524 {
1525 memset(&m_GridPoints, 0, sizeof(m_GridPoints));
1526 memset(m_GridPoints, nGridPoints, m_nInput);
1527 return Init(&m_GridPoints[0]);
1528 }
1529
1530 /**
1531 ****************************************************************************
1532 * Name: CIccCLUT::Init
1533 *
1534 * Purpose: Initializes and sets the size of the CLUT
1535 *
1536 * Args:
1537 * pGridPoints = number of grid points in the CLUT
1538 *****************************************************************************
1539 */
Init(icUInt8Number * pGridPoints)1540 bool CIccCLUT::Init(icUInt8Number *pGridPoints)
1541 {
1542 memset(m_nReserved2, 0, sizeof(m_nReserved2));
1543 if (pGridPoints!=&m_GridPoints[0]) {
1544 memcpy(m_GridPoints, pGridPoints, m_nInput);
1545 if (m_nInput<16)
1546 memset(m_GridPoints+m_nInput, 0, 16-m_nInput);
1547 }
1548
1549 if (m_pData) {
1550 delete [] m_pData;
1551 }
1552
1553 int i=m_nInput-1;
1554
1555 m_DimSize[i] = m_nOutput;
1556 m_nNumPoints = m_GridPoints[i];
1557 for (i--; i>=0; i--) {
1558 m_DimSize[i] = m_DimSize[i+1] * m_GridPoints[i+1];
1559 m_nNumPoints *= m_GridPoints[i];
1560 }
1561
1562 icUInt32Number nSize = NumPoints() * m_nOutput;
1563
1564 if (!nSize)
1565 return false;
1566
1567 m_pData = new icFloatNumber[nSize];
1568
1569 return (m_pData != NULL);
1570 }
1571
1572
1573 /**
1574 ****************************************************************************
1575 * Name: CIccCLUT::ReadData
1576 *
1577 * Purpose: Reads the CLUT data points into the data buffer
1578 *
1579 * Args:
1580 * size = # of bytes in the tag,
1581 * pIO = IO object to read data from,
1582 * nPrecision = data precision (8bit encoded as 1 or 16bit encoded as 2)
1583 *
1584 * Return:
1585 * true = data read succesfully,
1586 * false = read data failed
1587 *****************************************************************************
1588 */
ReadData(icUInt32Number size,CIccIO * pIO,icUInt8Number nPrecision)1589 bool CIccCLUT::ReadData(icUInt32Number size, CIccIO *pIO, icUInt8Number nPrecision)
1590 {
1591 icUInt32Number nNum=NumPoints() * m_nOutput;
1592
1593 if (nNum * nPrecision > size)
1594 return false;
1595
1596 if (nPrecision==1) {
1597 if (pIO->Read8Float(m_pData, nNum)!=(icInt32Number)nNum)
1598 return false;
1599 }
1600 else if (nPrecision==2) {
1601 if (pIO->Read16Float(m_pData, nNum)!=(icInt32Number)nNum)
1602 return false;
1603 }
1604 else
1605 return false;
1606
1607 return true;
1608 }
1609
1610
1611 /**
1612 ****************************************************************************
1613 * Name: CIccCLUT::WriteData
1614 *
1615 * Purpose: Writes the CLUT data points from the data buffer
1616 *
1617 * Args:
1618 * pIO = IO object to write data to,
1619 * nPrecision = data precision (8bit encoded as 1 or 16bit encoded as 2)
1620 *
1621 * Return:
1622 * true = data written succesfully,
1623 * false = write operation failed
1624 *****************************************************************************
1625 */
WriteData(CIccIO * pIO,icUInt8Number nPrecision)1626 bool CIccCLUT::WriteData(CIccIO *pIO, icUInt8Number nPrecision)
1627 {
1628 icUInt32Number nNum=NumPoints() * m_nOutput;
1629
1630 if (nPrecision==1) {
1631 if (pIO->Write8Float(m_pData, nNum)!=(icInt32Number)nNum)
1632 return false;
1633 }
1634 else if (nPrecision==2) {
1635 if (pIO->Write16Float(m_pData, nNum)!=(icInt32Number)nNum)
1636 return false;
1637 }
1638 else
1639 return false;
1640
1641 return true;
1642 }
1643
1644
1645 /**
1646 ****************************************************************************
1647 * Name: CIccCLUT::Read
1648 *
1649 * Purpose: Read in the tag contents into a data block
1650 *
1651 * Args:
1652 * size - # of bytes in tag,
1653 * pIO - IO object to read tag from
1654 *
1655 * Return:
1656 * true = successful, false = failure
1657 *****************************************************************************
1658 */
Read(icUInt32Number size,CIccIO * pIO)1659 bool CIccCLUT::Read(icUInt32Number size, CIccIO *pIO)
1660 {
1661 if (size < 20)
1662 return false;
1663
1664 if (pIO->Read8(m_GridPoints, 16)!=16 ||
1665 !pIO->Read8(&m_nPrecision) ||
1666 pIO->Read8(&m_nReserved2[0], 3)!=3)
1667 return false;
1668
1669 Init(m_GridPoints);
1670
1671 return ReadData(size-20, pIO, m_nPrecision);
1672 }
1673
1674
1675 /**
1676 ****************************************************************************
1677 * Name: CIccCLUT::Write
1678 *
1679 * Purpose: Write the tag to a file
1680 *
1681 * Args:
1682 * pIO - The IO object to write tag to.
1683 *
1684 * Return:
1685 * true = succesful, false = failure
1686 *****************************************************************************
1687 */
Write(CIccIO * pIO)1688 bool CIccCLUT::Write(CIccIO *pIO)
1689 {
1690 if (pIO->Write8(m_GridPoints, 16)!=16 ||
1691 !pIO->Write8(&m_nPrecision) ||
1692 pIO->Write8(&m_nReserved2[0], 3)!=3)
1693 return false;
1694
1695 return WriteData(pIO, m_nPrecision);
1696 }
1697
1698 /**
1699 ****************************************************************************
1700 * Name: CIccCLUT::Iterate
1701 *
1702 * Purpose: Iterate through the CLUT to dump the data
1703 *
1704 * Args:
1705 * sDescription = string to concatenate data dump to,
1706 * nIndex = the channel number,
1707 * nPos = the current position in the CLUT
1708 *
1709 *****************************************************************************
1710 */
Iterate(std::string & sDescription,icUInt8Number nIndex,icUInt32Number nPos,bool bUseLegacy)1711 void CIccCLUT::Iterate(std::string &sDescription, icUInt8Number nIndex, icUInt32Number nPos, bool bUseLegacy)
1712 {
1713 if (nIndex < m_nInput) {
1714 int i;
1715 for (i=0; i<m_GridPoints[nIndex]; i++) {
1716 m_GridAdr[nIndex] = i;
1717 Iterate(sDescription, nIndex+1, nPos, bUseLegacy);
1718 nPos += m_DimSize[nIndex];
1719 }
1720 }
1721 else {
1722 icChar *ptr = m_pOutText;
1723 icFloatNumber *pData = &m_pData[nPos];
1724 int i;
1725
1726 for (i=0; i<m_nInput; i++) {
1727 icColorValue(m_pVal, (icFloatNumber)m_GridAdr[i] / (m_GridPoints[i]-1) , m_csInput, i, bUseLegacy);
1728
1729 ptr += sprintf(ptr, " %s", m_pVal);
1730 }
1731 strcpy(ptr, " ");
1732 ptr += 2;
1733
1734 for (i=0; i<m_nOutput; i++) {
1735 icColorValue(m_pVal, pData[i], m_csOutput, i, bUseLegacy);
1736
1737 ptr += sprintf(ptr, " %s", m_pVal);
1738 }
1739 strcpy(ptr, "\r\n");
1740 sDescription += (const icChar*)m_pOutText;
1741
1742 }
1743 }
1744
1745
1746 /**
1747 ****************************************************************************
1748 * Name: CIccCLUT::Iterate
1749 *
1750 * Purpose: Iterate through the CLUT to get the data and execute PixelOp
1751 *
1752 * Args:
1753 * pExec = pointer to the IIccCLUTExec object that implements the
1754 * IIccCLUTExec::Apply() function
1755 *
1756 *****************************************************************************
1757 */
Iterate(IIccCLUTExec * pExec)1758 void CIccCLUT::Iterate(IIccCLUTExec* pExec)
1759 {
1760 memset(&m_fGridAdr[0], 0, sizeof(m_fGridAdr));
1761 if (m_nInput==3) {
1762 int i,j,k;
1763 icUInt32Number index=0;
1764 for (i=0; i<m_GridPoints[0]; i++) {
1765 for (j=0; j<m_GridPoints[1]; j++) {
1766 for (k=0; k<m_GridPoints[2]; k++) {
1767 m_fGridAdr[2] = (icFloatNumber)k/(icFloatNumber)(m_GridPoints[2]-1);
1768 m_fGridAdr[1] = (icFloatNumber)j/(icFloatNumber)(m_GridPoints[1]-1);
1769 m_fGridAdr[0] = (icFloatNumber)i/(icFloatNumber)(m_GridPoints[0]-1);
1770
1771 index = (m_DimSize[0]*i + m_DimSize[1]*j + m_DimSize[2]*k);
1772 pExec->PixelOp(m_fGridAdr, &m_pData[index]);
1773
1774 }
1775 }
1776 }
1777 }
1778 else if (m_nInput==4) {
1779 int i,j,k,l;
1780 icUInt32Number index=0;
1781 for (i=0; i<m_GridPoints[0]; i++) {
1782 for (j=0; j<m_GridPoints[1]; j++) {
1783 for (k=0; k<m_GridPoints[2]; k++) {
1784 for (l=0; l<m_GridPoints[3]; l++) {
1785 m_fGridAdr[3] = (icFloatNumber)l/(icFloatNumber)(m_GridPoints[3]-1);
1786 m_fGridAdr[2] = (icFloatNumber)k/(icFloatNumber)(m_GridPoints[2]-1);
1787 m_fGridAdr[1] = (icFloatNumber)j/(icFloatNumber)(m_GridPoints[1]-1);
1788 m_fGridAdr[0] = (icFloatNumber)i/(icFloatNumber)(m_GridPoints[0]-1);
1789
1790 index = (m_DimSize[0]*i + m_DimSize[1]*j +
1791 m_DimSize[2]*k + m_DimSize[3]*l);
1792 pExec->PixelOp(m_fGridAdr, &m_pData[index]);
1793
1794 }
1795 }
1796 }
1797 }
1798 }
1799 else
1800 SubIterate(pExec, 0, 0);
1801 }
1802
1803
1804 /**
1805 ****************************************************************************
1806 * Name: CIccCLUT::SubIterate
1807 *
1808 * Purpose: Iterate through the CLUT to get the data
1809 *
1810 * Args:
1811 * pExec = pointer to the IIccCLUTExec object that implements the
1812 * IIccCLUTExec::Apply() function,
1813 * nIndex = the channel number,
1814 * nPos = the current position in the CLUT
1815 *
1816 *****************************************************************************
1817 */
SubIterate(IIccCLUTExec * pExec,icUInt8Number nIndex,icUInt32Number nPos)1818 void CIccCLUT::SubIterate(IIccCLUTExec* pExec, icUInt8Number nIndex, icUInt32Number nPos)
1819 {
1820 if (nIndex < m_nInput) {
1821 int i;
1822 for (i=0; i<m_GridPoints[nIndex]; i++) {
1823 m_fGridAdr[nIndex] = (icFloatNumber)i/(icFloatNumber)(m_GridPoints[nIndex]-1);
1824 SubIterate(pExec, nIndex+1, nPos);
1825 nPos += m_DimSize[nIndex];
1826 }
1827 }
1828 else
1829 pExec->PixelOp(m_fGridAdr, &m_pData[nPos]);
1830 }
1831
1832 /**
1833 ****************************************************************************
1834 * Name: CIccCLUT::DumpLut
1835 *
1836 * Purpose: Dump data associated with the tag to a string.
1837 *
1838 * Args:
1839 * sDescription = string to concatenate tag dump to,
1840 * szName = name of the LUT to be printed,
1841 * csInput = color space signature of the input data,
1842 * csOutput = color space signature of the output data
1843 *****************************************************************************
1844 */
DumpLut(std::string & sDescription,const icChar * szName,icColorSpaceSignature csInput,icColorSpaceSignature csOutput,bool bUseLegacy)1845 void CIccCLUT::DumpLut(std::string &sDescription, const icChar *szName,
1846 icColorSpaceSignature csInput, icColorSpaceSignature csOutput,
1847 bool bUseLegacy)
1848 {
1849 icChar szOutText[2048], szColor[40];
1850 int i, len;
1851
1852 sprintf(szOutText, "BEGIN_LUT %s %d %d\r\n", szName, m_nInput, m_nOutput);
1853 sDescription += szOutText;
1854
1855 for (i=0; i<m_nInput; i++) {
1856 icColorIndexName(szColor, csInput, i, m_nInput, "In");
1857 sprintf(szOutText, " %s=%d", szColor, m_GridPoints[i]);
1858 sDescription += szOutText;
1859 }
1860
1861 sDescription += " ";
1862
1863 for (i=0; i<m_nOutput; i++) {
1864 icColorIndexName(szColor, csOutput, i, m_nOutput, "Out");
1865 sprintf(szOutText, " %s", szColor);
1866 sDescription += szOutText;
1867 }
1868
1869 sDescription += "\r\n";
1870
1871 len = 0;
1872 for (i=0; i<m_nInput; i++) {
1873 icColorValue(szColor, 1.0, csInput, i, bUseLegacy);
1874 len+= (int)strlen(szColor);
1875 }
1876 for (i=0; i<m_nOutput; i++) {
1877 icColorValue(szColor, 1.0, csOutput, i, bUseLegacy);
1878 len+= (int)strlen(szColor);
1879 }
1880 len += m_nInput + m_nOutput + 6;
1881
1882 sDescription.reserve(sDescription.size() + NumPoints()*len);
1883
1884 //Initialize iteration member variables
1885 m_csInput = csInput;
1886 m_csOutput = csOutput;
1887 m_pOutText = szOutText;
1888 m_pVal = szColor;
1889 memset(m_GridAdr, 0, 16);
1890
1891 Iterate(sDescription, 0, 0, bUseLegacy);
1892
1893 sDescription += "\r\n";
1894 }
1895
1896
1897
1898 /**
1899 ****************************************************************************
1900 * Name: CIccCLUT::Begin
1901 *
1902 * Purpose: Initializes the CLUT. Must be called before Apply().
1903 *
1904 *****************************************************************************
1905 */
Begin()1906 void CIccCLUT::Begin()
1907 {
1908 int i;
1909 for (i=0; i<m_nInput; i++) {
1910 m_MaxGridPoint[i] = m_GridPoints[i] - 1;
1911 }
1912 m_nNodes = (1<<m_nInput);
1913
1914 if (m_nOffset)
1915 delete [] m_nOffset;
1916
1917 m_nOffset = new icUInt32Number[m_nNodes];
1918
1919 if (m_nInput==3) {
1920 m_nOffset[0] = n000 = 0;
1921 m_nOffset[1] = n001 = m_DimSize[0];
1922 m_nOffset[2] = n010 = m_DimSize[1];
1923 m_nOffset[3] = n011 = n001 + n010;
1924 m_nOffset[4] = n100 = m_DimSize[2];
1925 m_nOffset[5] = n101 = n100 + n001;
1926 m_nOffset[6] = n110 = n100 + n010;
1927 m_nOffset[7] = n111 = n110 + n001;
1928 }
1929 else if (m_nInput == 4) {
1930 m_nOffset[ 0] = 0;
1931 m_nOffset[ 1] = n001 = m_DimSize[ 0];
1932 m_nOffset[ 2] = n010 = m_DimSize[ 1];
1933 m_nOffset[ 3] = m_nOffset[ 2] + m_nOffset[ 1];
1934 m_nOffset[ 4] = n100 = m_DimSize[ 2];
1935 m_nOffset[ 5] = m_nOffset[ 4] + m_nOffset[ 1];
1936 m_nOffset[ 6] = m_nOffset[ 4] + m_nOffset[ 2];
1937 m_nOffset[ 7] = m_nOffset[ 4] + m_nOffset[ 3];
1938 m_nOffset[ 8] = n1000 = m_DimSize[ 3];
1939 m_nOffset[ 9] = m_nOffset[ 8] + m_nOffset[ 1];
1940 m_nOffset[10] = m_nOffset[ 8] + m_nOffset[ 2];
1941 m_nOffset[11] = m_nOffset[ 8] + m_nOffset[ 3];
1942 m_nOffset[12] = m_nOffset[ 8] + m_nOffset[ 4];
1943 m_nOffset[13] = m_nOffset[ 8] + m_nOffset[ 5];
1944 m_nOffset[14] = m_nOffset[ 8] + m_nOffset[ 6];
1945 m_nOffset[15] = m_nOffset[ 8] + m_nOffset[ 7];
1946 }
1947 else if (m_nInput == 5) {
1948 m_nOffset[ 0] = 0;
1949 m_nOffset[ 1] = n001 = m_DimSize[ 0];
1950 m_nOffset[ 2] = n010 = m_DimSize[ 1];
1951 m_nOffset[ 3] = m_nOffset[ 2] + m_nOffset[ 1];
1952 m_nOffset[ 4] = n100 = m_DimSize[ 2];
1953 m_nOffset[ 5] = m_nOffset[ 4] + m_nOffset[ 1];
1954 m_nOffset[ 6] = m_nOffset[ 4] + m_nOffset[ 2];
1955 m_nOffset[ 7] = m_nOffset[ 4] + m_nOffset[ 3];
1956 m_nOffset[ 8] = n1000 = m_DimSize[ 3];
1957 m_nOffset[ 9] = m_nOffset[ 8] + m_nOffset[ 1];
1958 m_nOffset[10] = m_nOffset[ 8] + m_nOffset[ 2];
1959 m_nOffset[11] = m_nOffset[ 8] + m_nOffset[ 3];
1960 m_nOffset[12] = m_nOffset[ 8] + m_nOffset[ 4];
1961 m_nOffset[13] = m_nOffset[ 8] + m_nOffset[ 5];
1962 m_nOffset[14] = m_nOffset[ 8] + m_nOffset[ 6];
1963 m_nOffset[15] = m_nOffset[ 8] + m_nOffset[ 7];
1964 m_nOffset[16] = n10000 = m_DimSize[ 4];
1965 m_nOffset[17] = m_nOffset[16] + m_nOffset[ 1];
1966 m_nOffset[18] = m_nOffset[16] + m_nOffset[ 2];
1967 m_nOffset[19] = m_nOffset[16] + m_nOffset[ 3];
1968 m_nOffset[20] = m_nOffset[16] + m_nOffset[ 4];
1969 m_nOffset[21] = m_nOffset[16] + m_nOffset[ 5];
1970 m_nOffset[22] = m_nOffset[16] + m_nOffset[ 6];
1971 m_nOffset[23] = m_nOffset[16] + m_nOffset[ 7];
1972 m_nOffset[24] = m_nOffset[16] + m_nOffset[ 8];
1973 m_nOffset[25] = m_nOffset[16] + m_nOffset[ 9];
1974 m_nOffset[26] = m_nOffset[16] + m_nOffset[10];
1975 m_nOffset[27] = m_nOffset[16] + m_nOffset[11];
1976 m_nOffset[28] = m_nOffset[16] + m_nOffset[12];
1977 m_nOffset[29] = m_nOffset[16] + m_nOffset[13];
1978 m_nOffset[30] = m_nOffset[16] + m_nOffset[14];
1979 m_nOffset[31] = m_nOffset[16] + m_nOffset[15];
1980 }
1981 else if (m_nInput == 6) {
1982 m_nOffset[ 0] = 0;
1983 m_nOffset[ 1] = n001 = m_DimSize[ 0];
1984 m_nOffset[ 2] = n010 = m_DimSize[ 1];
1985 m_nOffset[ 3] = m_nOffset[ 2] + m_nOffset[ 1];
1986 m_nOffset[ 4] = n100 = m_DimSize[ 2];
1987 m_nOffset[ 5] = m_nOffset[ 4] + m_nOffset[ 1];
1988 m_nOffset[ 6] = m_nOffset[ 4] + m_nOffset[ 2];
1989 m_nOffset[ 7] = m_nOffset[ 4] + m_nOffset[ 3];
1990 m_nOffset[ 8] = n1000 = m_DimSize[ 3];
1991 m_nOffset[ 9] = m_nOffset[ 8] + m_nOffset[ 1];
1992 m_nOffset[10] = m_nOffset[ 8] + m_nOffset[ 2];
1993 m_nOffset[11] = m_nOffset[ 8] + m_nOffset[ 3];
1994 m_nOffset[12] = m_nOffset[ 8] + m_nOffset[ 4];
1995 m_nOffset[13] = m_nOffset[ 8] + m_nOffset[ 5];
1996 m_nOffset[14] = m_nOffset[ 8] + m_nOffset[ 6];
1997 m_nOffset[15] = m_nOffset[ 8] + m_nOffset[ 7];
1998 m_nOffset[16] = n10000 = m_DimSize[ 4];
1999 m_nOffset[17] = m_nOffset[16] + m_nOffset[ 1];
2000 m_nOffset[18] = m_nOffset[16] + m_nOffset[ 2];
2001 m_nOffset[19] = m_nOffset[16] + m_nOffset[ 3];
2002 m_nOffset[20] = m_nOffset[16] + m_nOffset[ 4];
2003 m_nOffset[21] = m_nOffset[16] + m_nOffset[ 5];
2004 m_nOffset[22] = m_nOffset[16] + m_nOffset[ 6];
2005 m_nOffset[23] = m_nOffset[16] + m_nOffset[ 7];
2006 m_nOffset[24] = m_nOffset[16] + m_nOffset[ 8];
2007 m_nOffset[25] = m_nOffset[16] + m_nOffset[ 9];
2008 m_nOffset[26] = m_nOffset[16] + m_nOffset[10];
2009 m_nOffset[27] = m_nOffset[16] + m_nOffset[11];
2010 m_nOffset[28] = m_nOffset[16] + m_nOffset[12];
2011 m_nOffset[29] = m_nOffset[16] + m_nOffset[13];
2012 m_nOffset[30] = m_nOffset[16] + m_nOffset[14];
2013 m_nOffset[31] = m_nOffset[16] + m_nOffset[15];
2014 m_nOffset[32] = n100000 = m_DimSize[5];
2015 m_nOffset[33] = m_nOffset[32] + m_nOffset[ 1];
2016 m_nOffset[34] = m_nOffset[32] + m_nOffset[ 2];
2017 m_nOffset[35] = m_nOffset[32] + m_nOffset[ 3];
2018 m_nOffset[36] = m_nOffset[32] + m_nOffset[ 4];
2019 m_nOffset[37] = m_nOffset[32] + m_nOffset[ 5];
2020 m_nOffset[38] = m_nOffset[32] + m_nOffset[ 6];
2021 m_nOffset[39] = m_nOffset[32] + m_nOffset[ 7];
2022 m_nOffset[40] = m_nOffset[32] + m_nOffset[ 8];
2023 m_nOffset[41] = m_nOffset[32] + m_nOffset[ 9];
2024 m_nOffset[42] = m_nOffset[32] + m_nOffset[10];
2025 m_nOffset[43] = m_nOffset[32] + m_nOffset[11];
2026 m_nOffset[44] = m_nOffset[32] + m_nOffset[12];
2027 m_nOffset[45] = m_nOffset[32] + m_nOffset[13];
2028 m_nOffset[46] = m_nOffset[32] + m_nOffset[14];
2029 m_nOffset[47] = m_nOffset[32] + m_nOffset[15];
2030 m_nOffset[48] = m_nOffset[32] + m_nOffset[16];
2031 m_nOffset[49] = m_nOffset[32] + m_nOffset[17];
2032 m_nOffset[50] = m_nOffset[32] + m_nOffset[18];
2033 m_nOffset[51] = m_nOffset[32] + m_nOffset[19];
2034 m_nOffset[52] = m_nOffset[32] + m_nOffset[20];
2035 m_nOffset[53] = m_nOffset[32] + m_nOffset[21];
2036 m_nOffset[54] = m_nOffset[32] + m_nOffset[22];
2037 m_nOffset[55] = m_nOffset[32] + m_nOffset[23];
2038 m_nOffset[56] = m_nOffset[32] + m_nOffset[24];
2039 m_nOffset[57] = m_nOffset[32] + m_nOffset[25];
2040 m_nOffset[58] = m_nOffset[32] + m_nOffset[26];
2041 m_nOffset[59] = m_nOffset[32] + m_nOffset[27];
2042 m_nOffset[60] = m_nOffset[32] + m_nOffset[28];
2043 m_nOffset[61] = m_nOffset[32] + m_nOffset[29];
2044 m_nOffset[62] = m_nOffset[32] + m_nOffset[30];
2045 m_nOffset[63] = m_nOffset[32] + m_nOffset[31];
2046 }
2047 else {
2048 //initialize ND interpolation variables
2049 m_g = new icFloatNumber[m_nInput];
2050 m_ig = new icUInt32Number[m_nInput];
2051 m_s = new icFloatNumber[m_nInput];
2052 m_df = new icFloatNumber[m_nNodes];
2053
2054 m_nOffset[0] = 0;
2055 int count, nFlag;
2056 icUInt32Number nPower[2];
2057 nPower[0] = 0;
2058 nPower[1] = 1;
2059
2060 for (count=0; count<m_nInput; count++) {
2061 m_nPower[count] = (1<<(m_nInput-1-count));
2062 }
2063
2064 count = 0;
2065 nFlag = 1;
2066 for (icUInt32Number j=1; j<m_nNodes; j++) {
2067 if (j == nPower[1]) {
2068 m_nOffset[j] = m_DimSize[count];
2069 nPower[0] = (1<<count);
2070 count++;
2071 nPower[1] = (1<<count);
2072 nFlag = 1;
2073 }
2074 else {
2075 m_nOffset[j] = m_nOffset[nPower[0]] + m_nOffset[nFlag];
2076 nFlag++;
2077 }
2078 }
2079 }
2080 }
2081
2082
2083
2084 /**
2085 ******************************************************************************
2086 * Name: CIccCLUT::Interp3dTetra
2087 *
2088 * Purpose: Tetrahedral interpolation function
2089 *
2090 * Args:
2091 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2092 *******************************************************************************
2093 */
Interp3dTetra(icFloatNumber * destPixel,const icFloatNumber * srcPixel) const2094 void CIccCLUT::Interp3dTetra(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2095 {
2096 icUInt8Number mx = m_MaxGridPoint[0];
2097 icUInt8Number my = m_MaxGridPoint[1];
2098 icUInt8Number mz = m_MaxGridPoint[2];
2099
2100 icFloatNumber x = UnitClip(srcPixel[0]) * mx;
2101 icFloatNumber y = UnitClip(srcPixel[1]) * my;
2102 icFloatNumber z = UnitClip(srcPixel[2]) * mz;
2103
2104 icUInt32Number ix = (icUInt32Number)x;
2105 icUInt32Number iy = (icUInt32Number)y;
2106 icUInt32Number iz = (icUInt32Number)z;
2107
2108 icFloatNumber v = x - ix;
2109 icFloatNumber u = y - iy;
2110 icFloatNumber t = z - iz;
2111
2112 if (ix==mx) {
2113 ix--;
2114 v = 1.0;
2115 }
2116 if (iy==my) {
2117 iy--;
2118 u = 1.0;
2119 }
2120 if (iz==mz) {
2121 iz--;
2122 t = 1.0;
2123 }
2124
2125 int i;
2126 icFloatNumber *p = &m_pData[ix*n001 + iy*n010 + iz*n100];
2127
2128 //Normalize grid units
2129
2130 for (i=0; i<m_nOutput; i++, p++) {
2131 if (t<u) {
2132 if (t>v) {
2133 destPixel[i] = (p[n000] + t*(p[n110]-p[n010]) +
2134 u*(p[n010]-p[n000]) +
2135 v*(p[n111]-p[n110]));
2136 }
2137 else if (u<v) {
2138 destPixel[i] = (p[n000] + t*(p[n111]-p[n011]) +
2139 u*(p[n011]-p[n001]) +
2140 v*(p[n001]-p[n000]));
2141 }
2142 else {
2143 destPixel[i] = (p[n000] + t*(p[n111]-p[n011]) +
2144 u*(p[n010]-p[n000]) +
2145 v*(p[n011]-p[n010]));
2146 }
2147 }
2148 else {
2149 if (t<v) {
2150 destPixel[i] = (p[n000] + t*(p[n101]-p[n001]) +
2151 u*(p[n111]-p[n101]) +
2152 v*(p[n001]-p[n000]));
2153 }
2154 else if (u<v) {
2155 destPixel[i] = (p[n000] + t*(p[n100]-p[n000]) +
2156 u*(p[n111]-p[n101]) +
2157 v*(p[n101]-p[n100]));
2158 }
2159 else {
2160 destPixel[i] = (p[n000] + t*(p[n100]-p[n000]) +
2161 u*(p[n110]-p[n100]) +
2162 v*(p[n111]-p[n110]));
2163 }
2164 }
2165 }
2166 }
2167
2168
2169
2170 /**
2171 ******************************************************************************
2172 * Name: CIccCLUT::Interp3d
2173 *
2174 * Purpose: Three dimensional interpolation function
2175 *
2176 * Args:
2177 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2178 *******************************************************************************
2179 */
Interp3d(icFloatNumber * destPixel,const icFloatNumber * srcPixel) const2180 void CIccCLUT::Interp3d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2181 {
2182 icUInt8Number mx = m_MaxGridPoint[0];
2183 icUInt8Number my = m_MaxGridPoint[1];
2184 icUInt8Number mz = m_MaxGridPoint[2];
2185
2186 icFloatNumber x = UnitClip(srcPixel[0]) * mx;
2187 icFloatNumber y = UnitClip(srcPixel[1]) * my;
2188 icFloatNumber z = UnitClip(srcPixel[2]) * mz;
2189
2190 icUInt32Number ix = (icUInt32Number)x;
2191 icUInt32Number iy = (icUInt32Number)y;
2192 icUInt32Number iz = (icUInt32Number)z;
2193
2194 icFloatNumber u = x - ix;
2195 icFloatNumber t = y - iy;
2196 icFloatNumber s = z - iz;
2197
2198 if (ix==mx) {
2199 ix--;
2200 u = 1.0;
2201 }
2202 if (iy==my) {
2203 iy--;
2204 t = 1.0;
2205 }
2206 if (iz==mz) {
2207 iz--;
2208 s = 1.0;
2209 }
2210
2211 icFloatNumber ns = (icFloatNumber)(1.0 - s);
2212 icFloatNumber nt = (icFloatNumber)(1.0 - t);
2213 icFloatNumber nu = (icFloatNumber)(1.0 - u);
2214
2215 int i;
2216 icFloatNumber *p = &m_pData[ix*n001 + iy*n010 + iz*n100];
2217
2218 //Normalize grid units
2219 icFloatNumber dF0, dF1, dF2, dF3, dF4, dF5, dF6, dF7, pv;
2220
2221 dF0 = ns* nt* nu;
2222 dF1 = ns* nt* u;
2223 dF2 = ns* t* nu;
2224 dF3 = ns* t* u;
2225 dF4 = s* nt* nu;
2226 dF5 = s* nt* u;
2227 dF6 = s* t* nu;
2228 dF7 = s* t* u;
2229
2230 for (i=0; i<m_nOutput; i++, p++) {
2231 pv = p[n000]*dF0 + p[n001]*dF1 + p[n010]*dF2 + p[n011]*dF3 +
2232 p[n100]*dF4 + p[n101]*dF5 + p[n110]*dF6 + p[n111]*dF7;
2233
2234 destPixel[i] = pv;
2235 }
2236 }
2237
2238
2239
2240 /**
2241 ******************************************************************************
2242 * Name: CIccCLUT::Interp4d
2243 *
2244 * Purpose: Four dimensional interpolation function
2245 *
2246 * Args:
2247 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2248 *******************************************************************************
2249 */
Interp4d(icFloatNumber * destPixel,const icFloatNumber * srcPixel) const2250 void CIccCLUT::Interp4d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2251 {
2252 icUInt8Number mw = m_MaxGridPoint[0];
2253 icUInt8Number mx = m_MaxGridPoint[1];
2254 icUInt8Number my = m_MaxGridPoint[2];
2255 icUInt8Number mz = m_MaxGridPoint[3];
2256
2257 icFloatNumber w = UnitClip(srcPixel[0]) * mw;
2258 icFloatNumber x = UnitClip(srcPixel[1]) * mx;
2259 icFloatNumber y = UnitClip(srcPixel[2]) * my;
2260 icFloatNumber z = UnitClip(srcPixel[3]) * mz;
2261
2262 icUInt32Number iw = (icUInt32Number)w;
2263 icUInt32Number ix = (icUInt32Number)x;
2264 icUInt32Number iy = (icUInt32Number)y;
2265 icUInt32Number iz = (icUInt32Number)z;
2266
2267 icFloatNumber v = w - iw;
2268 icFloatNumber u = x - ix;
2269 icFloatNumber t = y - iy;
2270 icFloatNumber s = z - iz;
2271
2272 if (iw==mw) {
2273 iw--;
2274 v = 1.0;
2275 }
2276 if (ix==mx) {
2277 ix--;
2278 u = 1.0;
2279 }
2280 if (iy==my) {
2281 iy--;
2282 t = 1.0;
2283 }
2284 if (iz==mz) {
2285 iz--;
2286 s = 1.0;
2287 }
2288
2289 icFloatNumber ns = (icFloatNumber)(1.0 - s);
2290 icFloatNumber nt = (icFloatNumber)(1.0 - t);
2291 icFloatNumber nu = (icFloatNumber)(1.0 - u);
2292 icFloatNumber nv = (icFloatNumber)(1.0 - v);
2293
2294 int i, j;
2295 icFloatNumber *p = &m_pData[iw*n001 + ix*n010 + iy*n100 + iz*n1000];
2296
2297 //Normalize grid units
2298 icFloatNumber dF[16], pv;
2299
2300 dF[ 0] = ns* nt* nu* nv;
2301 dF[ 1] = ns* nt* nu* v;
2302 dF[ 2] = ns* nt* u* nv;
2303 dF[ 3] = ns* nt* u* v;
2304 dF[ 4] = ns* t* nu* nv;
2305 dF[ 5] = ns* t* nu* v;
2306 dF[ 6] = ns* t* u* nv;
2307 dF[ 7] = ns* t* u* v;
2308 dF[ 8] = s* nt* nu* nv;
2309 dF[ 9] = s* nt* nu* v;
2310 dF[10] = s* nt* u* nv;
2311 dF[11] = s* nt* u* v;
2312 dF[12] = s* t* nu* nv;
2313 dF[13] = s* t* nu* v;
2314 dF[14] = s* t* u* nv;
2315 dF[15] = s* t* u* v;
2316
2317 for (i=0; i<m_nOutput; i++, p++) {
2318 for (pv=0, j=0; j<16; j++)
2319 pv += p[m_nOffset[j]] * dF[j];
2320
2321 destPixel[i] = pv;
2322 }
2323 }
2324
2325
2326
2327 /**
2328 ******************************************************************************
2329 * Name: CIccCLUT::Interp5d
2330 *
2331 * Purpose: Five dimensional interpolation function
2332 *
2333 * Args:
2334 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2335 *******************************************************************************
2336 */
Interp5d(icFloatNumber * destPixel,const icFloatNumber * srcPixel) const2337 void CIccCLUT::Interp5d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2338 {
2339 icUInt8Number m0 = m_MaxGridPoint[0];
2340 icUInt8Number m1 = m_MaxGridPoint[1];
2341 icUInt8Number m2 = m_MaxGridPoint[2];
2342 icUInt8Number m3 = m_MaxGridPoint[3];
2343 icUInt8Number m4 = m_MaxGridPoint[4];
2344
2345 icFloatNumber g0 = UnitClip(srcPixel[0]) * m0;
2346 icFloatNumber g1 = UnitClip(srcPixel[1]) * m1;
2347 icFloatNumber g2 = UnitClip(srcPixel[2]) * m2;
2348 icFloatNumber g3 = UnitClip(srcPixel[3]) * m3;
2349 icFloatNumber g4 = UnitClip(srcPixel[4]) * m4;
2350
2351 icUInt32Number ig0 = (icUInt32Number)g0;
2352 icUInt32Number ig1 = (icUInt32Number)g1;
2353 icUInt32Number ig2 = (icUInt32Number)g2;
2354 icUInt32Number ig3 = (icUInt32Number)g3;
2355 icUInt32Number ig4 = (icUInt32Number)g4;
2356
2357 icFloatNumber s4 = g0 - ig0;
2358 icFloatNumber s3 = g1 - ig1;
2359 icFloatNumber s2 = g2 - ig2;
2360 icFloatNumber s1 = g3 - ig3;
2361 icFloatNumber s0 = g4 - ig4;
2362
2363 if (ig0==m0) {
2364 ig0--;
2365 s4 = 1.0;
2366 }
2367 if (ig1==m1) {
2368 ig1--;
2369 s3 = 1.0;
2370 }
2371 if (ig2==m2) {
2372 ig2--;
2373 s2 = 1.0;
2374 }
2375 if (ig3==m3) {
2376 ig3--;
2377 s1 = 1.0;
2378 }
2379 if (ig4==m4) {
2380 ig4--;
2381 s0 = 1.0;
2382 }
2383
2384 icFloatNumber ns0 = (icFloatNumber)(1.0 - s0);
2385 icFloatNumber ns1 = (icFloatNumber)(1.0 - s1);
2386 icFloatNumber ns2 = (icFloatNumber)(1.0 - s2);
2387 icFloatNumber ns3 = (icFloatNumber)(1.0 - s3);
2388 icFloatNumber ns4 = (icFloatNumber)(1.0 - s4);
2389
2390 int i, j;
2391 icFloatNumber *p = &m_pData[ig0*n001 + ig1*n010 + ig2*n100 + ig3*n1000 + ig4*n10000];
2392
2393 //Normalize grid units
2394 icFloatNumber dF[32], pv;
2395
2396 dF[ 0] = ns0 * ns1 * ns2 * ns3 * ns4;
2397 dF[ 1] = ns0 * ns1 * ns2 * ns3 * s4;
2398 dF[ 2] = ns0 * ns1 * ns2 * s3 * ns4;
2399 dF[ 3] = ns0 * ns1 * ns2 * s3 * s4;
2400 dF[ 4] = ns0 * ns1 * s2 * ns3 * ns4;
2401 dF[ 5] = ns0 * ns1 * s2 * ns3 * s4;
2402 dF[ 6] = ns0 * ns1 * s2 * s3 * ns4;
2403 dF[ 7] = ns0 * ns1 * s2 * s3 * s4;
2404 dF[ 8] = ns0 * s1 * ns2 * ns3 * ns4;
2405 dF[ 9] = ns0 * s1 * ns2 * ns3 * s4;
2406 dF[10] = ns0 * s1 * ns2 * s3 * ns4;
2407 dF[11] = ns0 * s1 * ns2 * s3 * s4;
2408 dF[12] = ns0 * s1 * s2 * ns3 * ns4;
2409 dF[13] = ns0 * s1 * s2 * ns3 * s4;
2410 dF[14] = ns0 * s1 * s2 * s3 * ns4;
2411 dF[15] = ns0 * s1 * s2 * s3 * s4;
2412 dF[16] = s0 * ns1 * ns2 * ns3 * ns4;
2413 dF[17] = s0 * ns1 * ns2 * ns3 * s4;
2414 dF[18] = s0 * ns1 * ns2 * s3 * ns4;
2415 dF[19] = s0 * ns1 * ns2 * s3 * s4;
2416 dF[20] = s0 * ns1 * s2 * ns3 * ns4;
2417 dF[21] = s0 * ns1 * s2 * ns3 * s4;
2418 dF[22] = s0 * ns1 * s2 * s3 * ns4;
2419 dF[23] = s0 * ns1 * s2 * s3 * s4;
2420 dF[24] = s0 * s1 * ns2 * ns3 * ns4;
2421 dF[25] = s0 * s1 * ns2 * ns3 * s4;
2422 dF[26] = s0 * s1 * ns2 * s3 * ns4;
2423 dF[27] = s0 * s1 * ns2 * s3 * s4;
2424 dF[28] = s0 * s1 * s2 * ns3 * ns4;
2425 dF[29] = s0 * s1 * s2 * ns3 * s4;
2426 dF[30] = s0 * s1 * s2 * s3 * ns4;
2427 dF[31] = s0 * s1 * s2 * s3 * s4;
2428
2429 for (i=0; i<m_nOutput; i++, p++) {
2430 for (pv=0.0, j=0; j<32; j++)
2431 pv += p[m_nOffset[j]] * dF[j];
2432
2433 destPixel[i] = pv;
2434 }
2435 }
2436
2437
2438
2439 /**
2440 ******************************************************************************
2441 * Name: CIccCLUT::Interp6d
2442 *
2443 * Purpose: Six dimensional interpolation function
2444 *
2445 * Args:
2446 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2447 *******************************************************************************
2448 */
Interp6d(icFloatNumber * destPixel,const icFloatNumber * srcPixel) const2449 void CIccCLUT::Interp6d(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2450 {
2451 icUInt8Number m0 = m_MaxGridPoint[0];
2452 icUInt8Number m1 = m_MaxGridPoint[1];
2453 icUInt8Number m2 = m_MaxGridPoint[2];
2454 icUInt8Number m3 = m_MaxGridPoint[3];
2455 icUInt8Number m4 = m_MaxGridPoint[4];
2456 icUInt8Number m5 = m_MaxGridPoint[5];
2457
2458 icFloatNumber g0 = UnitClip(srcPixel[0]) * m0;
2459 icFloatNumber g1 = UnitClip(srcPixel[1]) * m1;
2460 icFloatNumber g2 = UnitClip(srcPixel[2]) * m2;
2461 icFloatNumber g3 = UnitClip(srcPixel[3]) * m3;
2462 icFloatNumber g4 = UnitClip(srcPixel[4]) * m4;
2463 icFloatNumber g5 = UnitClip(srcPixel[5]) * m5;
2464
2465 icUInt32Number ig0 = (icUInt32Number)g0;
2466 icUInt32Number ig1 = (icUInt32Number)g1;
2467 icUInt32Number ig2 = (icUInt32Number)g2;
2468 icUInt32Number ig3 = (icUInt32Number)g3;
2469 icUInt32Number ig4 = (icUInt32Number)g4;
2470 icUInt32Number ig5 = (icUInt32Number)g5;
2471
2472 icFloatNumber s5 = g0 - ig0;
2473 icFloatNumber s4 = g1 - ig1;
2474 icFloatNumber s3 = g2 - ig2;
2475 icFloatNumber s2 = g3 - ig3;
2476 icFloatNumber s1 = g4 - ig4;
2477 icFloatNumber s0 = g5 - ig5;
2478
2479 if (ig0==m0) {
2480 ig0--;
2481 s5 = 1.0;
2482 }
2483 if (ig1==m1) {
2484 ig1--;
2485 s4 = 1.0;
2486 }
2487 if (ig2==m2) {
2488 ig2--;
2489 s3 = 1.0;
2490 }
2491 if (ig3==m3) {
2492 ig3--;
2493 s2 = 1.0;
2494 }
2495 if (ig4==m4) {
2496 ig4--;
2497 s1 = 1.0;
2498 }
2499 if (ig5==m5) {
2500 ig5--;
2501 s0 = 1.0;
2502 }
2503
2504 icFloatNumber ns0 = (icFloatNumber)(1.0 - s0);
2505 icFloatNumber ns1 = (icFloatNumber)(1.0 - s1);
2506 icFloatNumber ns2 = (icFloatNumber)(1.0 - s2);
2507 icFloatNumber ns3 = (icFloatNumber)(1.0 - s3);
2508 icFloatNumber ns4 = (icFloatNumber)(1.0 - s4);
2509 icFloatNumber ns5 = (icFloatNumber)(1.0 - s5);
2510
2511 int i, j;
2512 icFloatNumber *p = &m_pData[ig0*n001 + ig1*n010 + ig2*n100 + ig3*n1000 + ig4*n10000 + ig5*n100000];
2513
2514 //Normalize grid units
2515 icFloatNumber dF[64], pv;
2516
2517 dF[ 0] = ns0 * ns1 * ns2 * ns3 * ns4 * ns5;
2518 dF[ 1] = ns0 * ns1 * ns2 * ns3 * ns4 * s5;
2519 dF[ 2] = ns0 * ns1 * ns2 * ns3 * s4 * ns5;
2520 dF[ 3] = ns0 * ns1 * ns2 * ns3 * s4 * s5;
2521 dF[ 4] = ns0 * ns1 * ns2 * s3 * ns4 * ns5;
2522 dF[ 5] = ns0 * ns1 * ns2 * s3 * ns4 * s5;
2523 dF[ 6] = ns0 * ns1 * ns2 * s3 * s4 * ns5;
2524 dF[ 7] = ns0 * ns1 * ns2 * s3 * s4 * s5;
2525 dF[ 8] = ns0 * ns1 * s2 * ns3 * ns4 * ns5;
2526 dF[ 9] = ns0 * ns1 * s2 * ns3 * ns4 * s5;
2527 dF[10] = ns0 * ns1 * s2 * ns3 * s4 * ns5;
2528 dF[11] = ns0 * ns1 * s2 * ns3 * s4 * s5;
2529 dF[12] = ns0 * ns1 * s2 * s3 * ns4 * ns5;
2530 dF[13] = ns0 * ns1 * s2 * s3 * ns4 * s5;
2531 dF[14] = ns0 * ns1 * s2 * s3 * s4 * ns5;
2532 dF[15] = ns0 * ns1 * s2 * s3 * s4 * s5;
2533 dF[16] = ns0 * s1 * ns2 * ns3 * ns4 * ns5;
2534 dF[17] = ns0 * s1 * ns2 * ns3 * ns4 * s5;
2535 dF[18] = ns0 * s1 * ns2 * ns3 * s4 * ns5;
2536 dF[19] = ns0 * s1 * ns2 * ns3 * s4 * s5;
2537 dF[20] = ns0 * s1 * ns2 * s3 * ns4 * ns5;
2538 dF[21] = ns0 * s1 * ns2 * s3 * ns4 * s5;
2539 dF[22] = ns0 * s1 * ns2 * s3 * s4 * ns5;
2540 dF[23] = ns0 * s1 * ns2 * s3 * s4 * s5;
2541 dF[24] = ns0 * s1 * s2 * ns3 * ns4 * ns5;
2542 dF[25] = ns0 * s1 * s2 * ns3 * ns4 * s5;
2543 dF[26] = ns0 * s1 * s2 * ns3 * s4 * ns5;
2544 dF[27] = ns0 * s1 * s2 * ns3 * s4 * s5;
2545 dF[28] = ns0 * s1 * s2 * s3 * ns4 * ns5;
2546 dF[29] = ns0 * s1 * s2 * s3 * ns4 * s5;
2547 dF[30] = ns0 * s1 * s2 * s3 * s4 * ns5;
2548 dF[31] = ns0 * s1 * s2 * s3 * s4 * s5;
2549 dF[32] = s0 * ns1 * ns2 * ns3 * ns4 * ns5;
2550 dF[33] = s0 * ns1 * ns2 * ns3 * ns4 * s5;
2551 dF[34] = s0 * ns1 * ns2 * ns3 * s4 * ns5;
2552 dF[35] = s0 * ns1 * ns2 * ns3 * s4 * s5;
2553 dF[36] = s0 * ns1 * ns2 * s3 * ns4 * ns5;
2554 dF[37] = s0 * ns1 * ns2 * s3 * ns4 * s5;
2555 dF[38] = s0 * ns1 * ns2 * s3 * s4 * ns5;
2556 dF[39] = s0 * ns1 * ns2 * s3 * s4 * s5;
2557 dF[40] = s0 * ns1 * s2 * ns3 * ns4 * ns5;
2558 dF[41] = s0 * ns1 * s2 * ns3 * ns4 * s5;
2559 dF[42] = s0 * ns1 * s2 * ns3 * s4 * ns5;
2560 dF[43] = s0 * ns1 * s2 * ns3 * s4 * s5;
2561 dF[44] = s0 * ns1 * s2 * s3 * ns4 * ns5;
2562 dF[45] = s0 * ns1 * s2 * s3 * ns4 * s5;
2563 dF[46] = s0 * ns1 * s2 * s3 * s4 * ns5;
2564 dF[47] = s0 * ns1 * s2 * s3 * s4 * s5;
2565 dF[48] = s0 * s1 * ns2 * ns3 * ns4 * ns5;
2566 dF[49] = s0 * s1 * ns2 * ns3 * ns4 * s5;
2567 dF[50] = s0 * s1 * ns2 * ns3 * s4 * ns5;
2568 dF[51] = s0 * s1 * ns2 * ns3 * s4 * s5;
2569 dF[52] = s0 * s1 * ns2 * s3 * ns4 * ns5;
2570 dF[53] = s0 * s1 * ns2 * s3 * ns4 * s5;
2571 dF[54] = s0 * s1 * ns2 * s3 * s4 * ns5;
2572 dF[55] = s0 * s1 * ns2 * s3 * s4 * s5;
2573 dF[56] = s0 * s1 * s2 * ns3 * ns4 * ns5;
2574 dF[57] = s0 * s1 * s2 * ns3 * ns4 * s5;
2575 dF[58] = s0 * s1 * s2 * ns3 * s4 * ns5;
2576 dF[59] = s0 * s1 * s2 * ns3 * s4 * s5;
2577 dF[60] = s0 * s1 * s2 * s3 * ns4 * ns5;
2578 dF[61] = s0 * s1 * s2 * s3 * ns4 * s5;
2579 dF[62] = s0 * s1 * s2 * s3 * s4 * ns5;
2580 dF[63] = s0 * s1 * s2 * s3 * s4 * s5;
2581
2582 for (i=0; i<m_nOutput; i++, p++) {
2583 for (pv=0, j=0; j<64; j++)
2584 pv += p[m_nOffset[j]] * dF[j];
2585
2586 destPixel[i] = pv;
2587 }
2588 }
2589
2590
2591 /**
2592 ******************************************************************************
2593 * Name: CIccCLUT::InterpND
2594 *
2595 * Purpose: Generic N-dimensional interpolation function
2596 *
2597 * Args:
2598 * Pixel = Pixel value to be found in the CLUT. Also used to store the result.
2599 *******************************************************************************
2600 */
InterpND(icFloatNumber * destPixel,const icFloatNumber * srcPixel) const2601 void CIccCLUT::InterpND(icFloatNumber *destPixel, const icFloatNumber *srcPixel) const
2602 {
2603 icUInt32Number i,j, index = 0;
2604
2605 for (i=0; i<m_nInput; i++) {
2606 m_g[i] = UnitClip(srcPixel[i]) * m_MaxGridPoint[i];
2607 m_ig[i] = (icUInt32Number)m_g[i];
2608 m_s[m_nInput-1-i] = m_g[i] - m_ig[i];
2609 if (m_ig[i]==m_MaxGridPoint[i]) {
2610 m_ig[i]--;
2611 m_s[m_nInput-1-i] = 1.0;
2612 }
2613 index += m_ig[i]*m_DimSize[i];
2614 }
2615
2616 icFloatNumber *p = &m_pData[index];
2617 icFloatNumber temp[2];
2618 icFloatNumber pv;
2619 int nFlag = 0;
2620
2621 for (i=0; i<m_nNodes; i++) {
2622 m_df[i] = 1.0;
2623 }
2624
2625
2626 for (i=0; i<m_nInput; i++) {
2627 temp[0] = (icFloatNumber)(1.0 - m_s[i]);
2628 temp[1] = (icFloatNumber)(m_s[i]);
2629 index = m_nPower[i];
2630 for (j=0; j<m_nNodes; j++) {
2631 m_df[j] *= temp[nFlag];
2632 if ((j+1)%index == 0)
2633 nFlag = !nFlag;
2634 }
2635 nFlag = 0;
2636 }
2637
2638 for (i=0; i<m_nOutput; i++, p++) {
2639 for (pv=0, j=0; j<m_nNodes; j++)
2640 pv += p[m_nOffset[j]] * m_df[j];
2641
2642 destPixel[i] = pv;
2643 }
2644
2645 }
2646
2647
2648 /**
2649 ******************************************************************************
2650 * Name: CIccCLUT::Validate
2651 *
2652 * Purpose: Check tag data validity.
2653 *
2654 * Args:
2655 * sig = signature of tag being validated,
2656 * sReport = String to add report information to
2657 *
2658 * Return:
2659 * icValidateStatusOK if valid, or other error status.
2660 ******************************************************************************
2661 */
Validate(icTagTypeSignature sig,std::string & sReport,const CIccProfile * pProfile) const2662 icValidateStatus CIccCLUT::Validate(icTagTypeSignature sig, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
2663 {
2664 icValidateStatus rv = icValidateOK;
2665
2666 CIccInfo Info;
2667 std::string sSigName = Info.GetSigName(sig);
2668 if (m_nReserved2[0]!=0 || m_nReserved2[1]!=0 || m_nReserved2[2]!=0) {
2669 sReport += icValidateNonCompliantMsg;
2670 sReport += sSigName;
2671 sReport += " - Reserved Value must be zero.\r\n";
2672
2673 rv = icValidateNonCompliant;
2674 }
2675
2676 if (sig==icSigLutAtoBType || sig==icSigLutBtoAType) {
2677 char temp[256];
2678 for (int i=0; i<m_nInput; i++) {
2679 if (m_GridPoints[i]<2) {
2680 sReport += icValidateCriticalErrorMsg;
2681 sReport += sSigName;
2682 sprintf(temp, " - CLUT: At least 2 grid points should be present in dimension %u.\r\n",i );
2683 sReport += temp;
2684 rv = icMaxStatus(rv, icValidateCriticalError);
2685 }
2686 }
2687 }
2688
2689 return rv;
2690 }
2691
2692
2693 /**
2694 ****************************************************************************
2695 * Name: CIccMBB::CIccMBB
2696 *
2697 * Purpose: Constructor
2698 *
2699 *****************************************************************************
2700 */
CIccMBB()2701 CIccMBB::CIccMBB()
2702 {
2703 m_nInput = 0;
2704 m_nOutput = 0;
2705
2706 m_CurvesA = NULL;
2707 m_CLUT = NULL;
2708 m_Matrix = NULL;
2709 m_CurvesM = NULL;
2710 m_CurvesB = NULL;
2711
2712 m_csInput = icSigUnknownData;
2713 m_csOutput = icSigUnknownData;
2714
2715 m_bInputMatrix = true;
2716 m_bUseMCurvesAsBCurves = false;
2717 }
2718
2719
2720 /**
2721 ****************************************************************************
2722 * Name: CIccMBB::CIccMBB
2723 *
2724 * Purpose: Copy Constructor
2725 *
2726 * Args:
2727 * IMBB = The CIccMBB object to be copied
2728 *****************************************************************************
2729 */
CIccMBB(const CIccMBB & IMBB)2730 CIccMBB::CIccMBB(const CIccMBB &IMBB)
2731 {
2732 icUInt8Number nCurves;
2733 int i;
2734
2735 m_bInputMatrix = IMBB.m_bInputMatrix;
2736 m_bUseMCurvesAsBCurves = IMBB.m_bUseMCurvesAsBCurves;
2737 m_nInput = IMBB.m_nInput;
2738 m_nOutput = IMBB.m_nOutput;
2739 m_csInput = IMBB.m_csInput;
2740 m_csOutput = IMBB.m_csOutput;
2741
2742 if (IMBB.m_CLUT) {
2743 m_CLUT = new CIccCLUT(*IMBB.m_CLUT);
2744 }
2745 else
2746 m_CLUT = NULL;
2747
2748 if (IMBB.m_CurvesA) {
2749 nCurves = !IsInputB() ? m_nInput : m_nOutput;
2750
2751 m_CurvesA = new LPIccCurve[nCurves];
2752 for (i=0; i<nCurves; i++)
2753 m_CurvesA[i] = (CIccTagCurve*)IMBB.m_CurvesA[i]->NewCopy();
2754 }
2755 else {
2756 m_CurvesA = NULL;
2757 }
2758
2759 if (IMBB.m_CurvesM) {
2760 nCurves = IsInputMatrix() ? m_nInput : m_nOutput;
2761
2762 m_CurvesM = new LPIccCurve[nCurves];
2763 for (i=0; i<nCurves; i++)
2764 m_CurvesM[i] = (CIccTagCurve*)IMBB.m_CurvesM[i]->NewCopy();
2765 }
2766 else {
2767 m_CurvesM = NULL;
2768 }
2769
2770 if (IMBB.m_CurvesB) {
2771 nCurves = IsInputB() ? m_nInput : m_nOutput;
2772
2773 m_CurvesB = new LPIccCurve[nCurves];
2774 for (i=0; i<nCurves; i++)
2775 m_CurvesB[i] = (CIccTagCurve*)IMBB.m_CurvesB[i]->NewCopy();
2776 }
2777 else {
2778 m_CurvesB = NULL;
2779 }
2780
2781 if (IMBB.m_Matrix) {
2782 m_Matrix = new CIccMatrix(*IMBB.m_Matrix);
2783 }
2784 else {
2785 m_Matrix = NULL;
2786 }
2787 }
2788
2789
2790 /**
2791 ****************************************************************************
2792 * Name: CIccMBB::operator=
2793 *
2794 * Purpose: Copy Operator
2795 *
2796 * Args:
2797 * IMBB = The CIccMBB object to be copied
2798 *****************************************************************************
2799 */
operator =(const CIccMBB & IMBB)2800 CIccMBB &CIccMBB::operator=(const CIccMBB &IMBB)
2801 {
2802 if (&IMBB == this)
2803 return *this;
2804
2805 Cleanup();
2806
2807 icUInt8Number nCurves;
2808 int i;
2809
2810 m_bInputMatrix = IMBB.m_bInputMatrix;
2811 m_bUseMCurvesAsBCurves = IMBB.m_bUseMCurvesAsBCurves;
2812 m_nInput = IMBB.m_nInput;
2813 m_nOutput = IMBB.m_nOutput;
2814 m_csInput = IMBB.m_csInput;
2815 m_csOutput = IMBB.m_csOutput;
2816
2817 if (IMBB.m_CLUT) {
2818 m_CLUT = new CIccCLUT(*IMBB.m_CLUT);
2819 }
2820 else
2821 m_CLUT = NULL;
2822
2823 if (IMBB.m_CurvesA) {
2824 nCurves = !IsInputB() ? m_nInput : m_nOutput;
2825
2826 m_CurvesA = new LPIccCurve[nCurves];
2827 for (i=0; i<nCurves; i++)
2828 m_CurvesA[i] = (CIccTagCurve*)IMBB.m_CurvesA[i]->NewCopy();
2829 }
2830 else {
2831 m_CurvesA = NULL;
2832 }
2833
2834 if (IMBB.m_CurvesM) {
2835 nCurves = IsInputMatrix() ? m_nInput : m_nOutput;
2836
2837 m_CurvesM = new LPIccCurve[nCurves];
2838 for (i=0; i<nCurves; i++)
2839 m_CurvesM[i] = (CIccTagCurve*)IMBB.m_CurvesM[i]->NewCopy();
2840 }
2841 else {
2842 m_CurvesM = NULL;
2843 }
2844
2845 if (IMBB.m_CurvesB) {
2846 nCurves = IsInputB() ? m_nInput : m_nOutput;
2847
2848 m_CurvesB = new LPIccCurve[nCurves];
2849 for (i=0; i<nCurves; i++)
2850 m_CurvesB[i] = (CIccTagCurve*)IMBB.m_CurvesB[i]->NewCopy();
2851 }
2852 else {
2853 m_CurvesB = NULL;
2854 }
2855
2856 if (IMBB.m_Matrix) {
2857 m_Matrix = new CIccMatrix(*IMBB.m_Matrix);
2858 }
2859 else {
2860 m_Matrix = NULL;
2861 }
2862
2863 return *this;
2864 }
2865
2866
2867 /**
2868 ****************************************************************************
2869 * Name: CIccMBB::~CIccMBB
2870 *
2871 * Purpose: Destructor
2872 *
2873 *****************************************************************************
2874 */
~CIccMBB()2875 CIccMBB::~CIccMBB()
2876 {
2877 Cleanup();
2878 }
2879
2880 /**
2881 ****************************************************************************
2882 * Name: CIccMBB::Cleanup
2883 *
2884 * Purpose: Frees the memory allocated to the object
2885 *
2886 *****************************************************************************
2887 */
Cleanup()2888 void CIccMBB::Cleanup()
2889 {
2890 int i;
2891
2892 if (IsInputMatrix()) {
2893 if (m_CurvesB) {
2894 for (i=0; i<m_nInput; i++)
2895 if (m_CurvesB[i])
2896 delete m_CurvesB[i];
2897
2898 delete [] m_CurvesB;
2899 m_CurvesB = NULL;
2900 }
2901
2902 if (m_CurvesM) {
2903 for (i=0; i<m_nInput; i++)
2904 if (m_CurvesM[i])
2905 delete m_CurvesM[i];
2906
2907 delete [] m_CurvesM;
2908 m_CurvesM = NULL;
2909 }
2910
2911
2912 if (m_CurvesA) {
2913 for (i=0; i<m_nOutput; i++)
2914 if (m_CurvesA[i])
2915 delete m_CurvesA[i];
2916
2917 delete [] m_CurvesA;
2918 m_CurvesA = NULL;
2919 }
2920
2921 }
2922 else {
2923 if (m_CurvesA) {
2924 for (i=0; i<m_nInput; i++)
2925 if (m_CurvesA[i])
2926 delete m_CurvesA[i];
2927
2928 delete [] m_CurvesA;
2929 m_CurvesA = NULL;
2930 }
2931
2932 if (m_CurvesM) {
2933 for (i=0; i<m_nOutput; i++)
2934 if (m_CurvesM[i])
2935 delete m_CurvesM[i];
2936
2937 delete [] m_CurvesM;
2938 m_CurvesM = NULL;
2939 }
2940
2941 if (m_CurvesB) {
2942 for (i=0; i<m_nOutput; i++)
2943 if (m_CurvesB[i])
2944 delete m_CurvesB[i];
2945
2946 delete [] m_CurvesB;
2947 m_CurvesB = NULL;
2948 }
2949 }
2950
2951 if (m_Matrix) {
2952 delete m_Matrix;
2953 m_Matrix = NULL;
2954 }
2955
2956 if (m_CLUT) {
2957 delete m_CLUT;
2958 m_CLUT = NULL;
2959 }
2960 }
2961
2962 /**
2963 ****************************************************************************
2964 * Name: CIccMBB::Init
2965 *
2966 * Purpose: Cleans up any prior memory and Initializes the object.
2967 *
2968 * Args:
2969 * nInputChannels = number of input channels,
2970 * nOutputChannels = number of output channels
2971 *****************************************************************************
2972 */
Init(icUInt8Number nInputChannels,icUInt8Number nOutputChannels)2973 void CIccMBB::Init(icUInt8Number nInputChannels, icUInt8Number nOutputChannels)
2974 {
2975 Cleanup();
2976 m_nInput = nInputChannels;
2977 m_nOutput = nOutputChannels;
2978 }
2979
2980 /**
2981 ****************************************************************************
2982 * Name: CIccMBB::SetColorSpaces
2983 *
2984 * Purpose: Sets the input and output color spaces
2985 *
2986 * Args:
2987 * csInput = input color space signature,
2988 * csOutput = output color space signature
2989 *****************************************************************************
2990 */
SetColorSpaces(icColorSpaceSignature csInput,icColorSpaceSignature csOutput)2991 void CIccMBB::SetColorSpaces(icColorSpaceSignature csInput, icColorSpaceSignature csOutput)
2992 {
2993 m_csInput = csInput;
2994 m_csOutput = csOutput;
2995 }
2996
2997 /**
2998 ****************************************************************************
2999 * Name: CIccMBB::Describe
3000 *
3001 * Purpose: Dump data associated with the tag to a string
3002 *
3003 * Args:
3004 * sDescription - string to concatenate tag dump to
3005 *****************************************************************************
3006 */
Describe(std::string & sDescription)3007 void CIccMBB::Describe(std::string &sDescription)
3008 {
3009 int i;
3010 icChar buf[128], color[40];
3011
3012
3013 if (IsInputMatrix()) {
3014 if (m_CurvesB && !m_bUseMCurvesAsBCurves) {
3015 for (i=0; i<m_nInput; i++) {
3016 icColorIndexName(color, m_csInput, i, m_nInput, "");
3017 sprintf(buf, "B_Curve_%s", color);
3018 m_CurvesB[i]->DumpLut(sDescription, buf, m_csInput, i);
3019 }
3020 }
3021
3022 if (m_Matrix)
3023 m_Matrix->DumpLut(sDescription, "Matrix");
3024
3025 if (m_CurvesM) {
3026 for (i=0; i<m_nInput; i++) {
3027 icColorIndexName(color, m_csInput, i, m_nInput, "");
3028 if (!m_bUseMCurvesAsBCurves)
3029 sprintf(buf, "M_Curve_%s", color);
3030 else
3031 sprintf(buf, "B_Curve_%s", color);
3032 m_CurvesM[i]->DumpLut(sDescription, buf, m_csInput, i);
3033 }
3034 }
3035
3036 if (m_CLUT)
3037 m_CLUT->DumpLut(sDescription, "CLUT", m_csInput, m_csOutput, GetType()==icSigLut16Type);
3038
3039 if (m_CurvesA) {
3040 for (i=0; i<m_nOutput; i++) {
3041 icColorIndexName(color, m_csOutput, i, m_nOutput, "");
3042 sprintf(buf, "A_Curve_%s", color);
3043 m_CurvesA[i]->DumpLut(sDescription, buf, m_csOutput, i);
3044 }
3045 }
3046 }
3047 else {
3048 if (m_CurvesA) {
3049 for (i=0; i<m_nInput; i++) {
3050 icColorIndexName(color, m_csInput, i, m_nInput, "");
3051 sprintf(buf, "A_Curve_%s", color);
3052 m_CurvesA[i]->DumpLut(sDescription, buf, m_csInput, i);
3053 }
3054 }
3055
3056 if (m_CLUT)
3057 m_CLUT->DumpLut(sDescription, "CLUT", m_csInput, m_csOutput);
3058
3059 if (m_CurvesM && this->GetType()!=icSigLut8Type) {
3060 for (i=0; i<m_nOutput; i++) {
3061 icColorIndexName(color, m_csOutput, i, m_nOutput, "");
3062 sprintf(buf, "M_Curve_%s", color);
3063 m_CurvesM[i]->DumpLut(sDescription, buf, m_csOutput, i);
3064 }
3065 }
3066
3067 if (m_Matrix)
3068 m_Matrix->DumpLut(sDescription, "Matrix");
3069
3070 if (m_CurvesB) {
3071 for (i=0; i<m_nOutput; i++) {
3072 icColorIndexName(color, m_csOutput, i, m_nOutput, "");
3073 sprintf(buf, "B_Curve_%s", color);
3074 m_CurvesB[i]->DumpLut(sDescription, buf, m_csOutput, i);
3075 }
3076 }
3077 }
3078 }
3079
3080
3081 /**
3082 ******************************************************************************
3083 * Name: CIccMBB::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 */
Validate(icTagSignature sig,std::string & sReport,const CIccProfile * pProfile) const3095 icValidateStatus CIccMBB::Validate(icTagSignature sig, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
3096 {
3097 icValidateStatus rv = CIccTag::Validate(sig, sReport, pProfile);
3098
3099 CIccInfo Info;
3100 std::string sSigName = Info.GetSigName(sig);
3101
3102 if (!pProfile) {
3103 sReport += icValidateWarningMsg;
3104 sReport += sSigName;
3105 sReport += " - Tag validation incomplete: Pointer to profile unavailable.\r\n";
3106 rv = icMaxStatus(rv, icValidateWarning);
3107 return rv;
3108 }
3109 icUInt32Number nInput, nOutput;
3110
3111 //Check # of channels
3112 switch(sig) {
3113 case icSigAToB0Tag:
3114 case icSigAToB1Tag:
3115 case icSigAToB2Tag:
3116 {
3117 nInput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
3118 if (m_nInput!=nInput) {
3119 sReport += icValidateCriticalErrorMsg;
3120 sReport += sSigName;
3121 sReport += " - Incorrect number of input channels.\r\n";
3122 rv = icMaxStatus(rv, icValidateCriticalError);
3123 }
3124
3125 nOutput = icGetSpaceSamples(pProfile->m_Header.pcs);
3126 if (m_nOutput!=nOutput) {
3127 sReport += icValidateCriticalErrorMsg;
3128 sReport += sSigName;
3129 sReport += " - Incorrect number of output channels.\r\n";
3130 rv = icMaxStatus(rv, icValidateCriticalError);
3131 }
3132
3133 break;
3134 }
3135 case icSigBToA0Tag:
3136 case icSigBToA1Tag:
3137 case icSigBToA2Tag:
3138 {
3139 nInput = icGetSpaceSamples(pProfile->m_Header.pcs);
3140 if (m_nInput!=nInput) {
3141 sReport += icValidateCriticalErrorMsg;
3142 sReport += sSigName;
3143 sReport += " - Incorrect number of input channels.\r\n";
3144 rv = icMaxStatus(rv, icValidateCriticalError);
3145 }
3146
3147 nOutput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
3148 if (m_nOutput!=nOutput) {
3149 sReport += icValidateCriticalErrorMsg;
3150 sReport += sSigName;
3151 sReport += " - Incorrect number of output channels.\r\n";
3152 rv = icMaxStatus(rv, icValidateCriticalError);
3153 }
3154
3155 break;
3156 }
3157 case icSigGamutTag:
3158 {
3159 nInput = 1;
3160 if (m_nInput!=nInput) {
3161 sReport += icValidateCriticalErrorMsg;
3162 sReport += sSigName;
3163 sReport += " - Incorrect number of input channels.\r\n";
3164 rv = icMaxStatus(rv, icValidateCriticalError);
3165 }
3166
3167 nOutput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
3168 if (m_nOutput!=nOutput) {
3169 sReport += icValidateCriticalErrorMsg;
3170 sReport += sSigName;
3171 sReport += " - Incorrect number of output channels.\r\n";
3172 rv = icMaxStatus(rv, icValidateCriticalError);
3173 }
3174
3175 break;
3176 }
3177 default:
3178 {
3179 nInput = m_nInput;
3180 nOutput = m_nOutput;
3181 }
3182 }
3183
3184 //CLUT check
3185 if (nInput!=nOutput) {
3186 if (!m_CLUT) {
3187 sReport += icValidateCriticalErrorMsg;
3188 sReport += sSigName;
3189 sReport += " - CLUT must be present.\r\n";
3190 rv = icMaxStatus(rv, icValidateCriticalError);
3191 }
3192 }
3193
3194 if (m_CLUT) {
3195 rv = icMaxStatus(rv, m_CLUT->Validate(GetType(), sReport, pProfile));
3196 }
3197
3198 return rv;
3199 }
3200
3201 /**
3202 ****************************************************************************
3203 * Name: CIccMBB::NewCurvesA
3204 *
3205 * Purpose: Allocates memory for a new set of A-curves
3206 *
3207 * Return: Pointer to the LPIccCurve object
3208 *****************************************************************************
3209 */
NewCurvesA()3210 LPIccCurve* CIccMBB::NewCurvesA()
3211 {
3212 if (m_CurvesA)
3213 return m_CurvesA;
3214
3215 icUInt8Number nCurves = !IsInputB() ? m_nInput : m_nOutput;
3216
3217 m_CurvesA = new LPIccCurve[nCurves];
3218 memset(m_CurvesA, 0, nCurves * sizeof(LPIccCurve));
3219
3220 return m_CurvesA;
3221 }
3222
3223
3224 /**
3225 ****************************************************************************
3226 * Name: CIccMBB::NewCurvesM
3227 *
3228 * Purpose: Allocates memory for a new set of M-curves
3229 *
3230 * Return: Pointer to the LPIccCurve object
3231 *****************************************************************************
3232 */
NewCurvesM()3233 LPIccCurve* CIccMBB::NewCurvesM()
3234 {
3235 if (m_CurvesM)
3236 return m_CurvesM;
3237
3238 icUInt8Number nCurves = IsInputMatrix() ? m_nInput : m_nOutput;
3239
3240 m_CurvesM = new LPIccCurve[nCurves];
3241 memset(m_CurvesM, 0, nCurves * sizeof(LPIccCurve));
3242
3243 return m_CurvesM;
3244 }
3245
3246 /**
3247 ****************************************************************************
3248 * Name: CIccMBB::NewCurvesB
3249 *
3250 * Purpose: Allocates memory for a new set of B-curves
3251 *
3252 * Return: Pointer to the LPIccCurve object
3253 *****************************************************************************
3254 */
NewCurvesB()3255 LPIccCurve* CIccMBB::NewCurvesB()
3256 {
3257 if (m_CurvesB)
3258 return m_CurvesB;
3259
3260 icUInt8Number nCurves = IsInputB() ? m_nInput : m_nOutput;
3261
3262 m_CurvesB = new LPIccCurve[nCurves];
3263 memset(m_CurvesB, 0, nCurves * sizeof(LPIccCurve));
3264
3265 return m_CurvesB;
3266 }
3267
3268 /**
3269 ****************************************************************************
3270 * Name: CIccMBB::NewMatrix
3271 *
3272 * Purpose: Allocates memory for a new matrix
3273 *
3274 * Return: Pointer to the CIccMatrix object
3275 *****************************************************************************
3276 */
NewMatrix()3277 CIccMatrix* CIccMBB::NewMatrix()
3278 {
3279 if (m_Matrix)
3280 return m_Matrix;
3281
3282 m_Matrix = new CIccMatrix;
3283
3284 return m_Matrix;
3285 }
3286
3287 /**
3288 ****************************************************************************
3289 * Name: CIccMBB::NewCLUT
3290 *
3291 * Purpose: Allocates memory for a new CLUT and initializes it
3292 *
3293 * Args:
3294 * pGridPoints = number of grid points in the CLUT
3295 *
3296 * Return: Pointer to the CIccCLUT object
3297 *****************************************************************************
3298 */
NewCLUT(icUInt8Number * pGridPoints,icUInt8Number nPrecision)3299 CIccCLUT* CIccMBB::NewCLUT(icUInt8Number *pGridPoints, icUInt8Number nPrecision/*=2*/)
3300 {
3301 if (m_CLUT)
3302 return m_CLUT;
3303
3304 m_CLUT = new CIccCLUT(m_nInput, m_nOutput, nPrecision);
3305
3306 m_CLUT->Init(pGridPoints);
3307
3308 return m_CLUT;
3309 }
3310
3311 /**
3312 ****************************************************************************
3313 * Name: CIccMBB::SetCLUT
3314 *
3315 * Purpose: Assignes CLUT connection to an initialized new CLUT
3316 *
3317 * Args:
3318 * clut = pointer to a previously allocated CLUT (Onwership is transfered to
3319 * CIccMBB object).
3320 *
3321 * Return: Pointer to the CIccCLUT object or NULL if clut is incompatible with
3322 * CIccMBB object. If the clut is incompatible it is deleted.
3323 *****************************************************************************
3324 */
SetCLUT(CIccCLUT * clut)3325 CIccCLUT *CIccMBB::SetCLUT(CIccCLUT *clut)
3326 {
3327 if (clut->GetInputDim() != m_nInput || clut->GetOutputChannels() != m_nOutput) {
3328 delete clut;
3329 return NULL;
3330 }
3331
3332 if (m_CLUT) {
3333 delete m_CLUT;
3334 }
3335
3336 m_CLUT = clut;
3337 return clut;
3338 }
3339
3340 /**
3341 ****************************************************************************
3342 * Name: CIccMBB::NewCLUT
3343 *
3344 * Purpose: Allocates memory for a new CLUT and initializes it
3345 *
3346 * Args:
3347 * nGridPoints = number of grid points in the CLUT
3348 *
3349 * Return: Pointer to the CIccCLUT object
3350 *****************************************************************************
3351 */
NewCLUT(icUInt8Number nGridPoints,icUInt8Number nPrecision)3352 CIccCLUT* CIccMBB::NewCLUT(icUInt8Number nGridPoints, icUInt8Number nPrecision/*=2*/)
3353 {
3354 if (m_CLUT)
3355 return m_CLUT;
3356
3357 m_CLUT = new CIccCLUT(m_nInput, m_nOutput, nPrecision);
3358
3359 m_CLUT->Init(nGridPoints);
3360
3361 return m_CLUT;
3362 }
3363
3364
3365 /**
3366 ****************************************************************************
3367 * Name: CIccTagLutAtoB::CIccTagLutAtoB
3368 *
3369 * Purpose: Constructor
3370 *
3371 *****************************************************************************
3372 */
CIccTagLutAtoB()3373 CIccTagLutAtoB::CIccTagLutAtoB()
3374 {
3375 m_bInputMatrix = false;
3376 m_nReservedWord = 0;
3377 }
3378
3379
3380 /**
3381 ****************************************************************************
3382 * Name: CIccTagLutAtoB::CIccTagLutAtoB
3383 *
3384 * Purpose: Copy Constructor
3385 *
3386 * Args:
3387 * ITLA2B = The CIccTagLutAtoB object to be copied
3388 *****************************************************************************
3389 */
CIccTagLutAtoB(const CIccTagLutAtoB & ITLA2B)3390 CIccTagLutAtoB::CIccTagLutAtoB(const CIccTagLutAtoB &ITLA2B) : CIccMBB(ITLA2B)
3391 {
3392 m_nReservedWord = 0;
3393 }
3394
3395
3396 /**
3397 ****************************************************************************
3398 * Name: CIccTagLutAtoB::operator=
3399 *
3400 * Purpose: Copy Operator
3401 *
3402 * Args:
3403 * ITLA2B = The CIccTagLutAtoB object to be copied
3404 *****************************************************************************
3405 */
operator =(const CIccTagLutAtoB & ITLA2B)3406 CIccTagLutAtoB &CIccTagLutAtoB::operator=(const CIccTagLutAtoB &ITLA2B)
3407 {
3408 if (&ITLA2B == this)
3409 return *this;
3410
3411 CIccMBB::operator=(ITLA2B);
3412
3413 return *this;
3414 }
3415
3416
3417 /**
3418 ****************************************************************************
3419 * Name: CIccTagLutAtoB::~CIccTagLutAtoB
3420 *
3421 * Purpose: Destructor
3422 *
3423 *****************************************************************************
3424 */
~CIccTagLutAtoB()3425 CIccTagLutAtoB::~CIccTagLutAtoB()
3426 {
3427 }
3428
3429
3430 /**
3431 ****************************************************************************
3432 * Name: CIccTagLutAtoB::Read
3433 *
3434 * Purpose: Read in the tag contents into a data block
3435 *
3436 * Args:
3437 * size - # of bytes in tag,
3438 * pIO - IO object to read tag from
3439 *
3440 * Return:
3441 * true = successful, false = failure
3442 *****************************************************************************
3443 */
Read(icUInt32Number size,CIccIO * pIO)3444 bool CIccTagLutAtoB::Read(icUInt32Number size, CIccIO *pIO)
3445 {
3446 icTagTypeSignature sig;
3447 icUInt32Number Offset[5], nStart, nEnd, nPos;
3448 icUInt8Number nCurves, i;
3449
3450 if (size<8*sizeof(icUInt32Number) || !pIO) {
3451 return false;
3452 }
3453
3454 nStart = pIO->Tell();
3455 nEnd = nStart + size;
3456
3457 if (!pIO->Read32(&sig) ||
3458 !pIO->Read32(&m_nReserved) ||
3459 !pIO->Read8(&m_nInput) ||
3460 !pIO->Read8(&m_nOutput) ||
3461 !pIO->Read16(&m_nReservedWord) ||
3462 pIO->Read32(Offset, 5)!=5)
3463 return false;
3464
3465 if (sig!=GetType())
3466 return false;
3467
3468 //B Curves
3469 if (Offset[0]) {
3470 nCurves = IsInputB() ? m_nInput : m_nOutput;
3471 LPIccCurve *pCurves = NewCurvesB();
3472
3473 if (pIO->Seek(nStart + Offset[0], icSeekSet)<0)
3474 return false;
3475
3476 for (i=0; i<nCurves; i++) {
3477 nPos = pIO->Tell();
3478
3479 if (!pIO->Read32(&sig))
3480 return false;
3481
3482 if (pIO->Seek(nPos, icSeekSet)<0)
3483 return false;
3484
3485 if (sig!=icSigCurveType &&
3486 sig!=icSigParametricCurveType)
3487 return false;
3488
3489 pCurves[i] = (CIccCurve*)CIccTag::Create(sig);
3490
3491 if (!pCurves[i]->Read(nEnd - pIO->Tell(), pIO))
3492 return false;
3493
3494 if (!pIO->Sync32(Offset[1]))
3495 return false;
3496 }
3497 }
3498
3499 //Matrix
3500 if (Offset[1]) {
3501 icS15Fixed16Number tmp;
3502
3503 if (Offset[1] + 12*sizeof(icS15Fixed16Number) >size)
3504 return false;
3505
3506 m_Matrix = new CIccMatrix();
3507
3508 if (pIO->Seek(nStart + Offset[1], icSeekSet)<0)
3509 return false;
3510
3511 for (i=0; i<12; i++) {
3512 if (pIO->Read32(&tmp, 1)!=1)
3513 return false;
3514 m_Matrix->m_e[i] = icFtoD(tmp);
3515 }
3516 }
3517
3518
3519 //M Curves
3520 if (Offset[2]) {
3521 nCurves = IsInputMatrix() ? m_nInput : m_nOutput;
3522 LPIccCurve *pCurves = NewCurvesM();
3523
3524 if (pIO->Seek(nStart + Offset[2], icSeekSet)<0)
3525 return false;
3526
3527 for (i=0; i<nCurves; i++) {
3528 nPos = pIO->Tell();
3529
3530 if (!pIO->Read32(&sig))
3531 return false;
3532
3533 if (pIO->Seek(nPos, icSeekSet)<0)
3534 return false;
3535
3536 if (sig!=icSigCurveType &&
3537 sig!=icSigParametricCurveType)
3538 return false;
3539
3540 pCurves[i] = (CIccCurve*)CIccTag::Create(sig);
3541
3542 if (!pCurves[i]->Read(nEnd - pIO->Tell(), pIO))
3543 return false;
3544
3545 if (!pIO->Sync32(Offset[2]))
3546 return false;
3547 }
3548 }
3549
3550 //CLUT
3551 if (Offset[3]) {
3552 if (pIO->Seek(nStart + Offset[3], icSeekSet)<0)
3553 return false;
3554
3555 m_CLUT = new CIccCLUT(m_nInput, m_nOutput);
3556
3557 if (!m_CLUT->Read(nEnd - pIO->Tell(), pIO))
3558 return false;
3559 }
3560
3561 //A Curves
3562 if (Offset[4]) {
3563 nCurves = !IsInputB() ? m_nInput : m_nOutput;
3564 LPIccCurve *pCurves = NewCurvesA();
3565
3566 if (pIO->Seek(nStart + Offset[4], icSeekSet)<0)
3567 return false;
3568
3569 for (i=0; i<nCurves; i++) {
3570 nPos = pIO->Tell();
3571
3572 if (!pIO->Read32(&sig))
3573 return false;
3574
3575 if (pIO->Seek(nPos, icSeekSet)<0)
3576 return false;
3577
3578 if (sig!=icSigCurveType &&
3579 sig!=icSigParametricCurveType)
3580 return false;
3581
3582 pCurves[i] = (CIccCurve*)CIccTag::Create(sig);
3583
3584 if (!pCurves[i]->Read(nEnd - pIO->Tell(), pIO))
3585 return false;
3586
3587 if (!pIO->Sync32(Offset[4]))
3588 return false;
3589 }
3590 }
3591 return true;
3592 }
3593
3594
3595
3596 /**
3597 ****************************************************************************
3598 * Name: CIccTagLutAtoB::Write
3599 *
3600 * Purpose: Write the tag to a file
3601 *
3602 * Args:
3603 * pIO - The IO object to write tag to.
3604 *
3605 * Return:
3606 * true = succesful, false = failure
3607 *****************************************************************************
3608 */
Write(CIccIO * pIO)3609 bool CIccTagLutAtoB::Write(CIccIO *pIO)
3610 {
3611 icTagTypeSignature sig = GetType();
3612 icUInt32Number Offset[5], nStart, nEnd, nOffsetPos;
3613 icUInt8Number nCurves, i;
3614
3615 nStart = pIO->Tell();
3616 memset(&Offset[0], 0, sizeof(Offset));
3617
3618 if (!pIO->Write32(&sig) ||
3619 !pIO->Write32(&m_nReserved) ||
3620 !pIO->Write8(&m_nInput) ||
3621 !pIO->Write8(&m_nOutput) ||
3622 !pIO->Write16(&m_nReservedWord))
3623 return false;
3624
3625 nOffsetPos = pIO->Tell();
3626 if (pIO->Write32(Offset, 5)!=5)
3627 return false;
3628
3629 //B Curves
3630 if (m_CurvesB) {
3631 Offset[0] = pIO->Tell() - nStart;
3632 nCurves = IsInputB() ? m_nInput : m_nOutput;
3633
3634 for (i=0; i<nCurves; i++) {
3635 if (!m_CurvesB[i])
3636 return false;
3637
3638 if (!m_CurvesB[i]->Write(pIO))
3639 return false;
3640
3641 if (!pIO->Align32())
3642 return false;
3643 }
3644 }
3645
3646 //Matrix
3647 if (m_Matrix) {
3648 icS15Fixed16Number tmp;
3649
3650 Offset[1] = pIO->Tell() - nStart;
3651
3652 for (i=0; i<12; i++) {
3653 tmp = icDtoF(m_Matrix->m_e[i]);
3654 if (pIO->Write32(&tmp, 1)!=1)
3655 return false;
3656 }
3657 }
3658
3659
3660 //M Curves
3661 if (m_CurvesM) {
3662 Offset[2] = pIO->Tell() - nStart;
3663 nCurves = IsInputMatrix() ? m_nInput : m_nOutput;
3664
3665 for (i=0; i<nCurves; i++) {
3666 if (!m_CurvesM[i])
3667 return false;
3668
3669 if (!m_CurvesM[i]->Write(pIO))
3670 return false;
3671
3672 if (!pIO->Align32())
3673 return false;
3674 }
3675 }
3676
3677 //CLUT
3678 if (m_CLUT) {
3679 Offset[3] = pIO->Tell() - nStart;
3680
3681 if (!m_CLUT->Write(pIO))
3682 return false;
3683
3684 if (!pIO->Align32())
3685 return false;
3686 }
3687
3688 //A Curves
3689 if (m_CurvesA) {
3690 Offset[4] = pIO->Tell() - nStart;
3691 nCurves = !IsInputB() ? m_nInput : m_nOutput;
3692
3693 for (i=0; i<nCurves; i++) {
3694 if (!m_CurvesA[i])
3695 return false;
3696
3697 if (!m_CurvesA[i]->Write(pIO))
3698 return false;
3699
3700 if (!pIO->Align32())
3701 return false;
3702 }
3703 }
3704
3705 nEnd = pIO->Tell();
3706
3707 if (!pIO->Seek(nOffsetPos, icSeekSet))
3708 return false;
3709
3710 if (pIO->Write32(&Offset[0], 5)!=5)
3711 return false;
3712
3713 return pIO->Seek(nEnd, icSeekSet)>=0;
3714 }
3715
3716
3717 /**
3718 ******************************************************************************
3719 * Name: CIccTagLutAtoB::Validate
3720 *
3721 * Purpose: Check tag data validity.
3722 *
3723 * Args:
3724 * sig = signature of tag being validated,
3725 * sReport = String to add report information to
3726 *
3727 * Return:
3728 * icValidateStatusOK if valid, or other error status.
3729 ******************************************************************************
3730 */
Validate(icTagSignature sig,std::string & sReport,const CIccProfile * pProfile) const3731 icValidateStatus CIccTagLutAtoB::Validate(icTagSignature sig, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
3732 {
3733 icValidateStatus rv = CIccMBB::Validate(sig, sReport, pProfile);
3734
3735 CIccInfo Info;
3736 std::string sSigName = Info.GetSigName(sig);
3737
3738 if (!pProfile) {
3739 return rv;
3740 }
3741
3742 switch(sig) {
3743 case icSigAToB0Tag:
3744 case icSigAToB1Tag:
3745 case icSigAToB2Tag:
3746 {
3747 icUInt32Number nInput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
3748
3749 icUInt32Number nOutput = icGetSpaceSamples(pProfile->m_Header.pcs);
3750
3751 icUInt8Number i;
3752 if (m_CurvesB) {
3753 for (i=0; i<nOutput; i++) {
3754 if (m_CurvesB[i]) {
3755 rv = icMaxStatus(rv, m_CurvesB[i]->Validate(sig, sReport, pProfile));
3756 }
3757 else {
3758 sReport += icValidateCriticalErrorMsg;
3759 sReport += sSigName;
3760 sReport += " - Incorrect number of B-curves.\r\n";
3761 rv = icMaxStatus(rv, icValidateCriticalError);
3762 }
3763 }
3764 }
3765
3766 if (m_CurvesM) {
3767 for (i=0; i<nOutput; i++) {
3768 if (m_CurvesM[i]) {
3769 rv = icMaxStatus(rv, m_CurvesM[i]->Validate(sig, sReport, pProfile));
3770 }
3771 else {
3772 sReport += icValidateCriticalErrorMsg;
3773 sReport += sSigName;
3774 sReport += " - Incorrect number of M-curves.\r\n";
3775 rv = icMaxStatus(rv, icValidateCriticalError);
3776 }
3777 }
3778 }
3779
3780 if (m_CurvesA) {
3781 if (!m_CLUT) {
3782 sReport += icValidateNonCompliantMsg;
3783 sReport += sSigName;
3784 sReport += " - CLUT must be present if using A-curves.\r\n";
3785
3786 rv = icMaxStatus(rv, icValidateNonCompliant);
3787 }
3788
3789 for (i=0; i<nInput; i++) {
3790 if (m_CurvesA[i]) {
3791 rv = icMaxStatus(rv, m_CurvesA[i]->Validate(sig, sReport, pProfile));
3792 }
3793 else {
3794 sReport += icValidateCriticalErrorMsg;
3795 sReport += sSigName;
3796 sReport += " - Incorrect number of A-curves.\r\n";
3797 rv = icMaxStatus(rv, icValidateCriticalError);
3798 }
3799 }
3800
3801 }
3802
3803 break;
3804 }
3805 default:
3806 {
3807 }
3808 }
3809
3810
3811 return rv;
3812 }
3813
3814 /**
3815 ****************************************************************************
3816 * Name: CIccTagLutBtoA::CIccTagLutBtoA
3817 *
3818 * Purpose: Constructor
3819 *
3820 *****************************************************************************
3821 */
CIccTagLutBtoA()3822 CIccTagLutBtoA::CIccTagLutBtoA()
3823 {
3824 m_bInputMatrix = true;
3825 }
3826
3827
3828 /**
3829 ****************************************************************************
3830 * Name: CIccTagLutBtoA::CIccTagLutBtoA
3831 *
3832 * Purpose: Copy Constructor
3833 *
3834 * Args:
3835 * ITLB2A = The CIccTagLutBtoA object to be copied
3836 *****************************************************************************
3837 */
CIccTagLutBtoA(const CIccTagLutBtoA & ITLB2A)3838 CIccTagLutBtoA::CIccTagLutBtoA(const CIccTagLutBtoA &ITLB2A) : CIccTagLutAtoB(ITLB2A)
3839 {
3840 }
3841
3842
3843 /**
3844 ****************************************************************************
3845 * Name: CIccTagLutBtoA::operator=
3846 *
3847 * Purpose: Copy Operator
3848 *
3849 * Args:
3850 * ITLB2A = The CIccTagLutBtoA object to be copied
3851 *****************************************************************************
3852 */
operator =(const CIccTagLutBtoA & ITLB2A)3853 CIccTagLutBtoA &CIccTagLutBtoA::operator=(const CIccTagLutBtoA &ITLB2A)
3854 {
3855 if (&ITLB2A == this)
3856 return *this;
3857
3858 CIccMBB::operator=(ITLB2A);
3859
3860 return *this;
3861 }
3862
3863
3864 /**
3865 ******************************************************************************
3866 * Name: CIccTagLutBtoA::Validate
3867 *
3868 * Purpose: Check tag data validity.
3869 *
3870 * Args:
3871 * sig = signature of tag being validated,
3872 * sReport = String to add report information to
3873 *
3874 * Return:
3875 * icValidateStatusOK if valid, or other error status.
3876 ******************************************************************************
3877 */
Validate(icTagSignature sig,std::string & sReport,const CIccProfile * pProfile) const3878 icValidateStatus CIccTagLutBtoA::Validate(icTagSignature sig, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
3879 {
3880 icValidateStatus rv = CIccMBB::Validate(sig, sReport, pProfile);
3881
3882 CIccInfo Info;
3883 std::string sSigName = Info.GetSigName(sig);
3884
3885 if (!pProfile) {
3886 sReport += icValidateWarningMsg;
3887 sReport += sSigName;
3888 sReport += " - Tag validation incomplete: Pointer to profile unavailable.\r\n";
3889 rv = icMaxStatus(rv, icValidateCriticalError);
3890 return rv;
3891 }
3892
3893 switch(sig) {
3894 case icSigBToA0Tag:
3895 case icSigBToA1Tag:
3896 case icSigBToA2Tag:
3897 case icSigGamutTag:
3898 {
3899 icUInt32Number nInput = icGetSpaceSamples(pProfile->m_Header.pcs);
3900
3901 icUInt32Number nOutput;
3902 if (sig==icSigGamutTag) {
3903 nOutput = 1;
3904 }
3905 else {
3906 nOutput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
3907 }
3908
3909 if (m_nOutput!=nOutput) {
3910 sReport += icValidateCriticalErrorMsg;
3911 sReport += sSigName;
3912 sReport += " - Incorrect number of output channels.\r\n";
3913 rv = icMaxStatus(rv, icValidateCriticalError);
3914 }
3915
3916 icUInt8Number i;
3917 if (m_CurvesB) {
3918 for (i=0; i<nInput; i++) {
3919 if (m_CurvesB[i]) {
3920 rv = icMaxStatus(rv, m_CurvesB[i]->Validate(sig, sReport, pProfile));
3921 }
3922 else {
3923 sReport += icValidateCriticalErrorMsg;
3924 sReport += sSigName;
3925 sReport += " - Incorrect number of B-curves.\r\n";
3926 rv = icMaxStatus(rv, icValidateCriticalError);
3927 }
3928 }
3929 }
3930
3931 if (m_CurvesM) {
3932 for (i=0; i<nInput; i++) {
3933 if (m_CurvesM[i]) {
3934 rv = icMaxStatus(rv, m_CurvesM[i]->Validate(sig, sReport, pProfile));
3935 }
3936 else {
3937 sReport += icValidateCriticalErrorMsg;
3938 sReport += sSigName;
3939 sReport += " - Incorrect number of M-curves.\r\n";
3940 rv = icMaxStatus(rv, icValidateCriticalError);
3941 }
3942 }
3943 }
3944
3945 if (m_CurvesA) {
3946 if (!m_CLUT) {
3947 sReport += icValidateNonCompliantMsg;
3948 sReport += sSigName;
3949 sReport += " - CLUT must be present if using A-curves.\r\n";
3950
3951 rv = icMaxStatus(rv, icValidateNonCompliant);
3952 }
3953
3954 for (i=0; i<nOutput; i++) {
3955 if (m_CurvesA[i]) {
3956 rv = icMaxStatus(rv, m_CurvesA[i]->Validate(sig, sReport, pProfile));
3957 }
3958 else {
3959 sReport += icValidateCriticalErrorMsg;
3960 sReport += sSigName;
3961 sReport += " - Incorrect number of A-curves.\r\n";
3962 rv = icMaxStatus(rv, icValidateCriticalError);
3963 }
3964 }
3965
3966 }
3967
3968 break;
3969 }
3970 default:
3971 {
3972 }
3973 }
3974
3975
3976 return rv;
3977 }
3978
3979
3980 /**
3981 ****************************************************************************
3982 * Name: CIccTagLut8::CIccTagLut8
3983 *
3984 * Purpose: Constructor
3985 *
3986 *****************************************************************************
3987 */
CIccTagLut8()3988 CIccTagLut8::CIccTagLut8()
3989 {
3990 memset(m_XYZMatrix, 0, sizeof(m_XYZMatrix));
3991 m_XYZMatrix[0] = m_XYZMatrix[4] = m_XYZMatrix[8] = icDtoF(1.0);
3992 m_nReservedByte = 0;
3993 }
3994
3995
3996 /**
3997 ****************************************************************************
3998 * Name: CIccTagLut8::CIccTagLut8
3999 *
4000 * Purpose: Copy Constructor
4001 *
4002 * Args:
4003 * ITL = The CIccTagLut8 object to be copied
4004 *****************************************************************************
4005 */
CIccTagLut8(const CIccTagLut8 & ITL)4006 CIccTagLut8::CIccTagLut8(const CIccTagLut8& ITL) : CIccMBB(ITL)
4007 {
4008 memcpy(&m_XYZMatrix, &ITL.m_XYZMatrix, sizeof(m_XYZMatrix));
4009 m_nReservedByte = 0;
4010 }
4011
4012
4013 /**
4014 ****************************************************************************
4015 * Name: CIccTagLut8::operator=
4016 *
4017 * Purpose: Copy Operator
4018 *
4019 * Args:
4020 * ITL = The CIccTagLut8 object to be copied
4021 *****************************************************************************
4022 */
operator =(const CIccTagLut8 & ITL)4023 CIccTagLut8 &CIccTagLut8::operator=(const CIccTagLut8 &ITL)
4024 {
4025 if (&ITL==this)
4026 return *this;
4027
4028 CIccMBB::operator=(ITL);
4029 memcpy(&m_XYZMatrix, &ITL.m_XYZMatrix, sizeof(m_XYZMatrix));
4030
4031 return *this;
4032 }
4033
4034
4035 /**
4036 ****************************************************************************
4037 * Name: CIccTagLut8::~CIccTagLut8
4038 *
4039 * Purpose: Destructor
4040 *
4041 *****************************************************************************
4042 */
~CIccTagLut8()4043 CIccTagLut8::~CIccTagLut8()
4044 {
4045 }
4046
4047
4048 /**
4049 ****************************************************************************
4050 * Name: CIccTagLut8::Read
4051 *
4052 * Purpose: Read in the tag contents into a data block
4053 *
4054 * Args:
4055 * size - # of bytes in tag,
4056 * pIO - IO object to read tag from
4057 *
4058 * Return:
4059 * true = successful, false = failure
4060 *****************************************************************************
4061 */
Read(icUInt32Number size,CIccIO * pIO)4062 bool CIccTagLut8::Read(icUInt32Number size, CIccIO *pIO)
4063 {
4064 icTagTypeSignature sig;
4065 icUInt32Number nStart, nEnd;
4066 icUInt8Number i, nGrid;
4067 LPIccCurve *pCurves;
4068 CIccTagCurve *pCurve;
4069
4070 if (size<13*sizeof(icUInt32Number) || !pIO) {
4071 return false;
4072 }
4073
4074 nStart = pIO->Tell();
4075 nEnd = nStart + size;
4076
4077 if (!pIO->Read32(&sig) ||
4078 !pIO->Read32(&m_nReserved) ||
4079 !pIO->Read8(&m_nInput) ||
4080 !pIO->Read8(&m_nOutput) ||
4081 !pIO->Read8(&nGrid) ||
4082 !pIO->Read8(&m_nReservedByte) ||
4083 pIO->Read32(m_XYZMatrix, 9) != 9)
4084 return false;
4085
4086 if (sig!=GetType())
4087 return false;
4088
4089 //B Curves
4090 pCurves = NewCurvesB();
4091
4092 for (i=0; i<m_nInput; i++) {
4093 if (256 > nEnd - pIO->Tell())
4094 return false;
4095
4096 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
4097
4098 pCurve->SetSize(256);
4099
4100 if (pIO->Read8Float(&(*pCurve)[0], 256) != 256)
4101 return false;
4102 }
4103
4104 //CLUT
4105 m_CLUT = new CIccCLUT(m_nInput, m_nOutput);
4106
4107 m_CLUT->Init(nGrid);
4108
4109 if (!m_CLUT->ReadData(nEnd - pIO->Tell(), pIO, 1))
4110 return false;
4111
4112 //A Curves
4113 pCurves = NewCurvesA();
4114
4115 for (i=0; i<m_nOutput; i++) {
4116 if (256 > nEnd - pIO->Tell())
4117 return false;
4118
4119 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
4120
4121 pCurve->SetSize(256);
4122
4123 if (pIO->Read8Float(&(*pCurve)[0], 256) != 256)
4124 return false;
4125 }
4126 return true;
4127 }
4128
4129
4130 /**
4131 ****************************************************************************
4132 * Name: CIccTagLut8::SetColorSpaces
4133 *
4134 * Purpose: Sets the input and output color spaces
4135 *
4136 * Args:
4137 * csInput = input color space signature,
4138 * csOutput = output color space signature
4139 *
4140 *****************************************************************************
4141 */
SetColorSpaces(icColorSpaceSignature csInput,icColorSpaceSignature csOutput)4142 void CIccTagLut8::SetColorSpaces(icColorSpaceSignature csInput, icColorSpaceSignature csOutput)
4143 {
4144 if (csInput==icSigXYZData) {
4145 int i;
4146
4147 if (!m_CurvesM && IsInputMatrix()) { //Transfer ownership of curves
4148 m_CurvesM = m_CurvesB;
4149 m_CurvesB = NULL;
4150
4151 LPIccCurve *pCurves = NewCurvesB();
4152 CIccTagCurve *pCurve;
4153 for (i=0; i<m_nInput; i++) {
4154 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
4155 pCurve->SetSize(0);
4156 }
4157
4158 m_bUseMCurvesAsBCurves = true;
4159 }
4160
4161 if (!m_Matrix) {
4162 CIccMatrix *pMatrix = NewMatrix();
4163 for (i=0; i<9; i++) {
4164 pMatrix->m_e[i] = icFtoD(m_XYZMatrix[i]);
4165 }
4166
4167 pMatrix->m_bUseConstants=false;
4168 }
4169 }
4170 else {
4171 m_XYZMatrix[0] = m_XYZMatrix[4] = m_XYZMatrix[8] = icDtoF(1.0);
4172 m_XYZMatrix[1] = m_XYZMatrix[2] = m_XYZMatrix[3] =
4173 m_XYZMatrix[5] = m_XYZMatrix[6] = m_XYZMatrix[7] = 0;
4174 }
4175
4176 CIccMBB::SetColorSpaces(csInput, csOutput);
4177 }
4178
4179
4180 /**
4181 ****************************************************************************
4182 * Name: CIccTagLut8::Write
4183 *
4184 * Purpose: Write the tag to a file
4185 *
4186 * Args:
4187 * pIO - The IO object to write tag to.
4188 *
4189 * Return:
4190 * true = succesful, false = failure
4191 *****************************************************************************
4192 */
Write(CIccIO * pIO)4193 bool CIccTagLut8::Write(CIccIO *pIO)
4194 {
4195 icTagTypeSignature sig = GetType();
4196 icUInt8Number i, nGrid;
4197 icS15Fixed16Number XYZMatrix[9];
4198 icUInt16Number nInputEntries, nOutputEntries;
4199 LPIccCurve *pCurves;
4200 CIccTagCurve *pCurve;
4201 icFloat32Number v;
4202
4203 if (m_Matrix) {
4204 for (i=0; i<9; i++)
4205 XYZMatrix[i] = icDtoF(m_Matrix->m_e[i]);
4206 }
4207 else {
4208 memset(XYZMatrix, 0, 9*sizeof(icS15Fixed16Number));
4209 XYZMatrix[0] = XYZMatrix[4] = XYZMatrix[8] = icDtoF(1.0);
4210 }
4211
4212 if (m_bUseMCurvesAsBCurves) {
4213 pCurves = m_CurvesM;
4214 }
4215 else {
4216 pCurves = m_CurvesB;
4217 }
4218
4219 if (!pCurves || !m_CurvesA || !m_CLUT)
4220 return false;
4221
4222 nGrid = m_CLUT->GridPoints();
4223
4224 nInputEntries = (icUInt16Number)(((CIccTagCurve*)pCurves[0])->GetSize());
4225 nOutputEntries = (icUInt16Number)(((CIccTagCurve*)m_CurvesA[0])->GetSize());
4226
4227 if (!pIO->Write32(&sig) ||
4228 !pIO->Write32(&m_nReserved) ||
4229 !pIO->Write8(&m_nInput) ||
4230 !pIO->Write8(&m_nOutput) ||
4231 !pIO->Write8(&nGrid) ||
4232 !pIO->Write8(&m_nReservedByte) ||
4233 pIO->Write32(XYZMatrix, 9) != 9)
4234 return false;
4235
4236 //B Curves
4237 for (i=0; i<m_nInput; i++) {
4238 if (pCurves[i]->GetType()!=icSigCurveType)
4239 return false;
4240
4241 pCurve = (CIccTagCurve*)pCurves[i];
4242 if (!pCurve)
4243 return false;
4244
4245 if (pCurve->GetSize()!=256) {
4246 icUInt32Number j;
4247
4248 for (j=0; j<256; j++) {
4249 v = pCurve->Apply((icFloat32Number)j / 255.0F);
4250 if (!pIO->Write8Float(&v, 1))
4251 return false;
4252 }
4253 }
4254 else {
4255 if (pIO->Write8Float(&(*pCurve)[0], 256)!=256)
4256 return false;
4257 }
4258 }
4259
4260 //CLUT
4261 if (!m_CLUT->WriteData(pIO, 1))
4262 return false;
4263
4264 //A Curves
4265 pCurves = m_CurvesA;
4266
4267 for (i=0; i<m_nOutput; i++) {
4268 if (pCurves[i]->GetType()!=icSigCurveType)
4269 return false;
4270
4271 pCurve = (CIccTagCurve*)pCurves[i];
4272
4273 if (!pCurve)
4274 return false;
4275
4276 if (pCurve->GetSize()!=256) {
4277 icUInt32Number j;
4278
4279 for (j=0; j<256; j++) {
4280 v = pCurve->Apply((icFloat32Number)j / 255.0F);
4281 if (!pIO->Write8Float(&v, 1))
4282 return false;
4283 }
4284 }
4285 else {
4286 if (pIO->Write8Float(&(*pCurve)[0], 256)!=256)
4287 return false;
4288 }
4289 }
4290 return true;
4291 }
4292
4293
4294 /**
4295 ******************************************************************************
4296 * Name: CIccTagLut8::Validate
4297 *
4298 * Purpose: Check tag data validity.
4299 *
4300 * Args:
4301 * sig = signature of tag being validated,
4302 * sReport = String to add report information to
4303 *
4304 * Return:
4305 * icValidateStatusOK if valid, or other error status.
4306 ******************************************************************************
4307 */
Validate(icTagSignature sig,std::string & sReport,const CIccProfile * pProfile) const4308 icValidateStatus CIccTagLut8::Validate(icTagSignature sig, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
4309 {
4310 icValidateStatus rv = CIccMBB::Validate(sig, sReport, pProfile);
4311
4312 CIccInfo Info;
4313 std::string sSigName = Info.GetSigName(sig);
4314
4315 if (!pProfile) {
4316 return rv;
4317 }
4318
4319 switch(sig) {
4320 case icSigAToB0Tag:
4321 case icSigAToB1Tag:
4322 case icSigAToB2Tag:
4323 case icSigBToA0Tag:
4324 case icSigBToA1Tag:
4325 case icSigBToA2Tag:
4326 case icSigGamutTag:
4327 {
4328 icUInt32Number nInput, nOutput;
4329 if (sig==icSigAToB0Tag || sig==icSigAToB1Tag || sig==icSigAToB2Tag || sig==icSigGamutTag) {
4330 nInput = icGetSpaceSamples(pProfile->m_Header.pcs);
4331 nOutput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
4332 }
4333 else {
4334 nInput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
4335 nOutput = icGetSpaceSamples(pProfile->m_Header.pcs);
4336 }
4337
4338 if (sig==icSigGamutTag) {
4339 nOutput = 1;
4340 }
4341
4342 icUInt8Number i;
4343 if (m_CurvesB) {
4344 for (i=0; i<nInput; i++) {
4345 if (m_CurvesB[i]) {
4346 rv = icMaxStatus(rv, m_CurvesB[i]->Validate(sig, sReport, pProfile));
4347 if (m_CurvesB[i]->GetType()==icSigCurveType) {
4348 CIccTagCurve *pTagCurve = (CIccTagCurve*)m_CurvesB[i];
4349 if (pTagCurve->GetSize()==1) {
4350 sReport += icValidateCriticalErrorMsg;
4351 sReport += sSigName;
4352 sReport += " - lut8Tags do not support single entry gamma curves.\r\n";
4353 rv = icMaxStatus(rv, icValidateCriticalError);
4354 }
4355 }
4356 }
4357 else {
4358 sReport += icValidateCriticalErrorMsg;
4359 sReport += sSigName;
4360 sReport += " - Incorrect number of B-curves.\r\n";
4361 rv = icMaxStatus(rv, icValidateCriticalError);
4362 }
4363 }
4364 }
4365
4366 if (m_Matrix) {
4367 rv = icMaxStatus(rv, m_Matrix->Validate(GetType(), sReport, pProfile));
4368 }
4369 else {
4370 int sum=0;
4371 for (int i=0; i<9; i++) {
4372 sum += m_XYZMatrix[i];
4373 }
4374 if (m_XYZMatrix[0]!=1.0 || m_XYZMatrix[4]!=1.0 || m_XYZMatrix[8]!=1.0 || sum!=3.0) {
4375 sReport += icValidateWarningMsg;
4376 sReport += sSigName;
4377 sReport += " - Matrix must be identity.\r\n";
4378 rv = icMaxStatus(rv, icValidateWarning);
4379 }
4380 }
4381
4382 if (m_CurvesA) {
4383
4384 for (i=0; i<nOutput; i++) {
4385 if (m_CurvesA[i]) {
4386 rv = icMaxStatus(rv, m_CurvesA[i]->Validate(sig, sReport, pProfile));
4387 if (m_CurvesA[i]->GetType()==icSigCurveType) {
4388 CIccTagCurve *pTagCurve = (CIccTagCurve*)m_CurvesA[i];
4389 if (pTagCurve->GetSize()==1) {
4390 sReport += icValidateCriticalErrorMsg;
4391 sReport += sSigName;
4392 sReport += " - lut8Tags do not support single entry gamma curves.\r\n";
4393 rv = icMaxStatus(rv, icValidateCriticalError);
4394 }
4395 }
4396 }
4397 else {
4398 sReport += icValidateCriticalErrorMsg;
4399 sReport += sSigName;
4400 sReport += " - Incorrect number of A-curves.\r\n";
4401 rv = icMaxStatus(rv, icValidateCriticalError);
4402 }
4403 }
4404
4405 }
4406
4407 break;
4408 }
4409 default:
4410 {
4411 }
4412 }
4413
4414
4415 return rv;
4416 }
4417
4418
4419 /**
4420 ****************************************************************************
4421 * Name: CIccTagLut16::CIccTagLut16
4422 *
4423 * Purpose: Constructor
4424 *
4425 *****************************************************************************
4426 */
CIccTagLut16()4427 CIccTagLut16::CIccTagLut16()
4428 {
4429 memset(m_XYZMatrix, 0, sizeof(m_XYZMatrix));
4430 m_XYZMatrix[0] = m_XYZMatrix[4] = m_XYZMatrix[8] = icDtoF(1.0);
4431 m_nReservedByte = 0;
4432 }
4433
4434
4435 /**
4436 ****************************************************************************
4437 * Name: CIccTagLut16::CIccTagLut16
4438 *
4439 * Purpose: Copy Constructor
4440 *
4441 * Args:
4442 * ITL = The CIccTagUnknown object to be copied
4443 *****************************************************************************
4444 */
CIccTagLut16(const CIccTagLut16 & ITL)4445 CIccTagLut16::CIccTagLut16(const CIccTagLut16& ITL) : CIccMBB(ITL)
4446 {
4447 memcpy(&m_XYZMatrix, &ITL.m_XYZMatrix, sizeof(m_XYZMatrix));
4448 m_nReservedByte = 0;
4449 }
4450
4451
4452 /**
4453 ****************************************************************************
4454 * Name: CIccTagLut16::operator=
4455 *
4456 * Purpose: Copy Operator
4457 *
4458 * Args:
4459 * ITL = The CIccTagLut16 object to be copied
4460 *****************************************************************************
4461 */
operator =(const CIccTagLut16 & ITL)4462 CIccTagLut16 &CIccTagLut16::operator=(const CIccTagLut16 &ITL)
4463 {
4464 if (&ITL==this)
4465 return *this;
4466
4467 CIccMBB::operator=(ITL);
4468 memcpy(&m_XYZMatrix, &ITL.m_XYZMatrix, sizeof(m_XYZMatrix));
4469
4470 return *this;
4471 }
4472
4473
4474 /**
4475 ****************************************************************************
4476 * Name: CIccTagLut16::~CIccTagLut16
4477 *
4478 * Purpose: Destructor
4479 *
4480 *****************************************************************************
4481 */
~CIccTagLut16()4482 CIccTagLut16::~CIccTagLut16()
4483 {
4484 }
4485
4486
4487 /**
4488 ****************************************************************************
4489 * Name: CIccTagLut16::Read
4490 *
4491 * Purpose: Read in the tag contents into a data block
4492 *
4493 * Args:
4494 * size - # of bytes in tag,
4495 * pIO - IO object to read tag from
4496 *
4497 * Return:
4498 * true = successful, false = failure
4499 *****************************************************************************
4500 */
Read(icUInt32Number size,CIccIO * pIO)4501 bool CIccTagLut16::Read(icUInt32Number size, CIccIO *pIO)
4502 {
4503 icTagTypeSignature sig;
4504 icUInt32Number nStart, nEnd;
4505 icUInt8Number i, nGrid;
4506 icUInt16Number nInputEntries, nOutputEntries;
4507 LPIccCurve *pCurves;
4508 CIccTagCurve *pCurve;
4509
4510 if (size<13*sizeof(icUInt32Number) || !pIO) {
4511 return false;
4512 }
4513
4514 nStart = pIO->Tell();
4515 nEnd = nStart + size;
4516
4517 if (!pIO->Read32(&sig) ||
4518 !pIO->Read32(&m_nReserved) ||
4519 !pIO->Read8(&m_nInput) ||
4520 !pIO->Read8(&m_nOutput) ||
4521 !pIO->Read8(&nGrid) ||
4522 !pIO->Read8(&m_nReservedByte) ||
4523 pIO->Read32(m_XYZMatrix, 9) != 9 ||
4524 !pIO->Read16(&nInputEntries) ||
4525 !pIO->Read16(&nOutputEntries))
4526 return false;
4527
4528 if (sig!=GetType())
4529 return false;
4530
4531
4532 //B Curves
4533 pCurves = NewCurvesB();
4534
4535 for (i=0; i<m_nInput; i++) {
4536 if (nInputEntries*sizeof(icUInt16Number) > nEnd - pIO->Tell())
4537 return false;
4538
4539 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
4540
4541 pCurve->SetSize(nInputEntries);
4542
4543 if (pIO->Read16Float(&(*pCurve)[0], nInputEntries) != nInputEntries)
4544 return false;
4545 }
4546
4547 //CLUT
4548 m_CLUT = new CIccCLUT(m_nInput, m_nOutput);
4549
4550 m_CLUT->Init(nGrid);
4551
4552 if (!m_CLUT->ReadData(nEnd - pIO->Tell(), pIO, 2))
4553 return false;
4554
4555 //A Curves
4556 pCurves = NewCurvesA();
4557
4558 for (i=0; i<m_nOutput; i++) {
4559 if (nOutputEntries*sizeof(icUInt16Number) > nEnd - pIO->Tell())
4560 return false;
4561
4562 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
4563
4564 pCurve->SetSize(nOutputEntries);
4565
4566 if (pIO->Read16Float(&(*pCurve)[0], nOutputEntries) != nOutputEntries)
4567 return false;
4568 }
4569 return true;
4570 }
4571
4572
4573 /**
4574 ****************************************************************************
4575 * Name: CIccTagLut16::SetColorSpaces
4576 *
4577 * Purpose: Sets the input and output color spaces
4578 *
4579 * Args:
4580 * csInput = input color space signature,
4581 * csOutput = output color space signature
4582 *
4583 *****************************************************************************
4584 */
SetColorSpaces(icColorSpaceSignature csInput,icColorSpaceSignature csOutput)4585 void CIccTagLut16::SetColorSpaces(icColorSpaceSignature csInput, icColorSpaceSignature csOutput)
4586 {
4587 if (csInput==icSigXYZData) {
4588 int i;
4589
4590 if (!m_CurvesM && IsInputMatrix()) { //Transfer ownership of curves
4591 m_CurvesM = m_CurvesB;
4592 m_CurvesB = NULL;
4593
4594 LPIccCurve *pCurves = NewCurvesB();
4595 CIccTagCurve *pCurve;
4596 for (i=0; i<m_nInput; i++) {
4597 pCurves[i] = pCurve = (CIccTagCurve*)CIccTag::Create(icSigCurveType);
4598 pCurve->SetSize(0);
4599 }
4600
4601 m_bUseMCurvesAsBCurves = true;
4602 }
4603
4604 if (!m_Matrix) {
4605 CIccMatrix *pMatrix = NewMatrix();
4606 for (i=0; i<9; i++) {
4607 pMatrix->m_e[i] = icFtoD(m_XYZMatrix[i]);
4608 }
4609
4610 pMatrix->m_bUseConstants=false;
4611 }
4612 }
4613 else {
4614 m_XYZMatrix[0] = m_XYZMatrix[4] = m_XYZMatrix[8] = icDtoF(1.0);
4615 m_XYZMatrix[1] = m_XYZMatrix[2] = m_XYZMatrix[3] =
4616 m_XYZMatrix[5] = m_XYZMatrix[6] = m_XYZMatrix[7] = 0;
4617 }
4618
4619 CIccMBB::SetColorSpaces(csInput, csOutput);
4620 }
4621
4622
4623 /**
4624 ****************************************************************************
4625 * Name: CIccTagLut16::Write
4626 *
4627 * Purpose: Write the tag to a file
4628 *
4629 * Args:
4630 * pIO - The IO object to write tag to.
4631 *
4632 * Return:
4633 * true = succesful, false = failure
4634 *****************************************************************************
4635 */
Write(CIccIO * pIO)4636 bool CIccTagLut16::Write(CIccIO *pIO)
4637 {
4638 icTagTypeSignature sig = GetType();
4639 icUInt8Number i, nGrid;
4640 icS15Fixed16Number XYZMatrix[9];
4641 icUInt16Number nInputEntries, nOutputEntries;
4642 LPIccCurve *pCurves;
4643 CIccTagCurve *pCurve;
4644
4645 if (m_Matrix) {
4646 for (i=0; i<9; i++) {
4647 XYZMatrix[i] = icDtoF(m_Matrix->m_e[i]);
4648 }
4649 }
4650 else {
4651 memset(XYZMatrix, 0, 9*sizeof(icS15Fixed16Number));
4652 XYZMatrix[0] = XYZMatrix[4] = XYZMatrix[8] = icDtoF(1.0);
4653 }
4654
4655 if (m_bUseMCurvesAsBCurves) {
4656 pCurves = m_CurvesM;
4657 }
4658 else {
4659 pCurves = m_CurvesB;
4660 }
4661
4662 if (!pCurves || !m_CurvesA || !m_CLUT)
4663 return false;
4664
4665 nGrid = m_CLUT->GridPoints();
4666
4667 nInputEntries = (icUInt16Number)(((CIccTagCurve*)pCurves[0])->GetSize());
4668 nOutputEntries = (icUInt16Number)(((CIccTagCurve*)m_CurvesA[0])->GetSize());
4669
4670 if (!pIO->Write32(&sig) ||
4671 !pIO->Write32(&m_nReserved) ||
4672 !pIO->Write8(&m_nInput) ||
4673 !pIO->Write8(&m_nOutput) ||
4674 !pIO->Write8(&nGrid) ||
4675 !pIO->Write8(&m_nReservedByte) ||
4676 pIO->Write32(XYZMatrix, 9) != 9 ||
4677 !pIO->Write16(&nInputEntries) ||
4678 !pIO->Write16(&nOutputEntries))
4679 return false;
4680
4681 //B Curves
4682 for (i=0; i<m_nInput; i++) {
4683 if (pCurves[i]->GetType()!=icSigCurveType)
4684 return false;
4685
4686 pCurve = (CIccTagCurve*)pCurves[i];
4687 if (!pCurve)
4688 return false;
4689
4690 if (pIO->Write16Float(&(*pCurve)[0], nInputEntries) != nInputEntries)
4691 return false;
4692 }
4693
4694 //CLUT
4695 if (!m_CLUT->WriteData(pIO, 2))
4696 return false;
4697
4698 //A Curves
4699 pCurves = m_CurvesA;
4700
4701 for (i=0; i<m_nOutput; i++) {
4702 if (pCurves[i]->GetType()!=icSigCurveType)
4703 return false;
4704
4705 pCurve = (CIccTagCurve*)pCurves[i];
4706
4707 if (pIO->Write16Float(&(*pCurve)[0], nOutputEntries) != nOutputEntries)
4708 return false;
4709 }
4710 return true;
4711 }
4712
4713
4714 /**
4715 ******************************************************************************
4716 * Name: CIccTagLut16::Validate
4717 *
4718 * Purpose: Check tag data validity.
4719 *
4720 * Args:
4721 * sig = signature of tag being validated,
4722 * sReport = String to add report information to
4723 *
4724 * Return:
4725 * icValidateStatusOK if valid, or other error status.
4726 ******************************************************************************
4727 */
Validate(icTagSignature sig,std::string & sReport,const CIccProfile * pProfile) const4728 icValidateStatus CIccTagLut16::Validate(icTagSignature sig, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
4729 {
4730 icValidateStatus rv = CIccMBB::Validate(sig, sReport, pProfile);
4731
4732 CIccInfo Info;
4733 std::string sSigName = Info.GetSigName(sig);
4734
4735 if (!pProfile) {
4736 rv = icMaxStatus(rv, icValidateWarning);
4737 return rv;
4738 }
4739
4740 switch(sig) {
4741 case icSigAToB0Tag:
4742 case icSigAToB1Tag:
4743 case icSigAToB2Tag:
4744 case icSigBToA0Tag:
4745 case icSigBToA1Tag:
4746 case icSigBToA2Tag:
4747 case icSigGamutTag:
4748 {
4749 icUInt32Number nInput, nOutput;
4750 if (sig==icSigAToB0Tag || sig==icSigAToB1Tag || sig==icSigAToB2Tag || sig==icSigGamutTag) {
4751 nInput = icGetSpaceSamples(pProfile->m_Header.pcs);
4752 nOutput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
4753 }
4754 else {
4755 nInput = icGetSpaceSamples(pProfile->m_Header.colorSpace);
4756 nOutput = icGetSpaceSamples(pProfile->m_Header.pcs);
4757 }
4758
4759 if (sig==icSigGamutTag) {
4760 nOutput = 1;
4761 }
4762
4763 icUInt8Number i;
4764 if (m_CurvesB) {
4765 for (i=0; i<nInput; i++) {
4766 if (m_CurvesB[i]) {
4767 rv = icMaxStatus(rv, m_CurvesB[i]->Validate(sig, sReport, pProfile));
4768 if (m_CurvesB[i]->GetType()==icSigCurveType) {
4769 CIccTagCurve *pTagCurve = (CIccTagCurve*)m_CurvesB[i];
4770 if (pTagCurve->GetSize()==1) {
4771 sReport += icValidateCriticalErrorMsg;
4772 sReport += sSigName;
4773 sReport += " - lut16Tags do not support single entry gamma curves.\r\n";
4774 rv = icMaxStatus(rv, icValidateCriticalError);
4775 }
4776 }
4777 }
4778 else {
4779 sReport += icValidateCriticalErrorMsg;
4780 sReport += sSigName;
4781 sReport += " - Incorrect number of B-curves.\r\n";
4782 rv = icMaxStatus(rv, icValidateCriticalError);
4783 }
4784 }
4785 }
4786
4787 if (m_Matrix) {
4788 rv = icMaxStatus(rv, m_Matrix->Validate(GetType(), sReport, pProfile));
4789 }
4790 else {
4791 int sum=0;
4792 for (int i=0; i<9; i++) {
4793 sum += m_XYZMatrix[i];
4794 }
4795 if (m_XYZMatrix[0]!=1.0 || m_XYZMatrix[4]!=1.0 || m_XYZMatrix[8]!=1.0 || sum!=3.0) {
4796 sReport += icValidateWarningMsg;
4797 sReport += sSigName;
4798 sReport += " - Matrix must be identity.\r\n";
4799 rv = icMaxStatus(rv, icValidateWarning);
4800 }
4801 }
4802
4803 if (m_CurvesA) {
4804
4805 for (i=0; i<nOutput; i++) {
4806 if (m_CurvesA[i]) {
4807 rv = icMaxStatus(rv, m_CurvesA[i]->Validate(sig, sReport, pProfile));
4808 if (m_CurvesA[i]->GetType()==icSigCurveType) {
4809 CIccTagCurve *pTagCurve = (CIccTagCurve*)m_CurvesA[i];
4810 if (pTagCurve->GetSize()==1) {
4811 sReport += icValidateCriticalErrorMsg;
4812 sReport += sSigName;
4813 sReport += " - lut16Tags do not support single entry gamma curves.\r\n";
4814 rv = icMaxStatus(rv, icValidateCriticalError);
4815 }
4816 }
4817 }
4818 else {
4819 sReport += icValidateCriticalErrorMsg;
4820 sReport += sSigName;
4821 sReport += " - Incorrect number of A-curves.\r\n";
4822 rv = icMaxStatus(rv, icValidateCriticalError);
4823 }
4824 }
4825
4826 }
4827
4828 break;
4829 }
4830 default:
4831 {
4832 }
4833 }
4834
4835
4836 return rv;
4837 }
4838
4839
4840 #ifdef USESAMPLEICCNAMESPACE
4841 } //namespace sampleICC
4842 #endif
4843