Bug Summary

File:IccProfLib/IccTagLut.cpp
Warning:line 4661, column 3
Value stored to 'nInputEntries' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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