Bug Summary

File:IccProfLib/IccTagBasic.cpp
Warning:line 4314, column 5
Value stored to 'n' 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 IccTagBasic.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/IccTagBasic.cpp
1/** @file
2 File: IccTagBasic.cpp
3
4 Contains: Implementation of the CIccTag class and basic inherited 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//////////////////////////////////////////////////////////////////////
70
71#ifdef WIN32
72 #pragma warning( disable: 4786) //disable warning in <list.h>
73 #include <windows.h>
74#endif
75#include <stdio.h>
76#include <math.h>
77#include <string.h>
78#include <stdlib.h>
79#include "IccTag.h"
80#include "IccUtil.h"
81#include "IccProfile.h"
82#include "IccTagFactory.h"
83#include "IccConvertUTF.h"
84#include "IccSparseMatrix.h"
85#include "IccCmm.h"
86
87#ifdef ICC_USE_ZLIB
88#include "zlib.h"
89#endif
90
91
92#ifndef __minmin
93#include <algorithm>
94using std::min;
95#define __minmin min
96#endif
97
98#ifdef USEREFICCMAXNAMESPACE
99namespace refIccMAX {
100#endif
101
102
103/**
104 ****************************************************************************
105 * Name: CIccTag::CIccTag
106 *
107 * Purpose: Constructor
108 *
109 *****************************************************************************
110 */
111CIccTag::CIccTag()
112{
113 m_nReserved = 0;
114}
115
116/**
117 ****************************************************************************
118 * Name: CIccTag::CIccTag
119 *
120 * Purpose: Destructor
121 *
122 *****************************************************************************
123 */
124CIccTag::~CIccTag()
125{
126
127}
128
129/**
130 ****************************************************************************
131 * Name: CIccTag::Create
132 *
133 * Purpose: This is a static tag creator based upon tag signature type
134 *
135 * Args:
136 * sig = tag type signature
137 *
138 * Return: Pointer to Allocated tag
139 *****************************************************************************
140 */
141CIccTag* CIccTag::Create(icTagTypeSignature sig)
142{
143 return CIccTagCreator::CreateTag(sig);
144}
145
146
147/**
148 ******************************************************************************
149 * Name: CIccTag::Validate
150 *
151 * Purpose: Check tag data validity. In base class we only look at the
152 * tag's reserved data value
153 *
154 * Args:
155 * sig = signature of tag being validated,
156 * sReport = String to add report information to
157 *
158 * Return:
159 * icValidateStatusOK if valid, or other error status.
160 ******************************************************************************
161 */
162icValidateStatus CIccTag::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
163{
164 icValidateStatus rv = icValidateOK;
165
166 if (m_nReserved != 0) {
167 CIccInfo Info;
168 sReport += icMsgValidateNonCompliant;
169 sReport += Info.GetSigPathName(sigPath);
170 sReport += " - Reserved Value must be zero.\r\n";
171
172 rv = icValidateNonCompliant;
173 }
174
175 return rv;
176}
177
178
179/**
180 ****************************************************************************
181 * Name: CIccTagUnknown::CIccTagUnknown
182 *
183 * Purpose: Constructor
184 *
185 *****************************************************************************
186 */
187CIccTagUnknown::CIccTagUnknown()
188{
189 m_nType = icSigUnknownType((icTagTypeSignature) 0x3f3f3f3f);
190 m_pData = NULL__null;
191}
192
193/**
194 ****************************************************************************
195 * Name: CIccTagUnknown::CIccTagUnknown
196 *
197 * Purpose: Copy Constructor
198 *
199 * Args:
200 * ITU = The CIccTagUnknown object to be copied
201 *****************************************************************************
202 */
203CIccTagUnknown::CIccTagUnknown(const CIccTagUnknown &ITU)
204{
205 m_nSize = ITU.m_nSize;
206 m_nType = ITU.m_nType;
207
208 m_pData = new icUInt8Number[m_nSize];
209 memcpy(m_pData, ITU.m_pData, sizeof(icUInt8Number)*m_nSize);
210}
211
212/**
213 ****************************************************************************
214 * Name: CIccTagUnknown::operator=
215 *
216 * Purpose: Copy Operator
217 *
218 * Args:
219 * UnknownTag = The CIccTagUnknown object to be copied
220 *****************************************************************************
221 */
222CIccTagUnknown &CIccTagUnknown::operator=(const CIccTagUnknown &UnknownTag)
223{
224 if (&UnknownTag == this)
225 return *this;
226
227 m_nSize = UnknownTag.m_nSize;
228 m_nType = UnknownTag.m_nType;
229
230 if (m_pData)
231 delete [] m_pData;
232 m_pData = new icUInt8Number[m_nSize];
233 memcpy(m_pData, UnknownTag.m_pData, sizeof(icUInt8Number)*m_nSize);
234
235 return *this;
236}
237
238/**
239 ****************************************************************************
240 * Name: CIccTagUnknown::~CIccTagUnknown
241 *
242 * Purpose: Destructor
243 *****************************************************************************
244 */
245CIccTagUnknown::~CIccTagUnknown()
246{
247 if (m_pData)
248 delete [] m_pData;
249}
250
251
252/**
253 ****************************************************************************
254 * Name: CIccTagUnknown::Read
255 *
256 * Purpose: Read in an unknown tag type into a data block
257 *
258 * Args:
259 * size - # of bytes in tag,
260 * pIO - IO object to read tag from
261 *
262 * Return:
263 * true = successful, false = failure
264 *****************************************************************************
265 */
266bool CIccTagUnknown::Read(icUInt32Number size, CIccIO *pIO)
267{
268 if (m_pData) {
269 delete [] m_pData;
270 m_pData = NULL__null;
271 }
272
273 if (size<sizeof(icTagTypeSignature) || !pIO) {
274 return false;
275 }
276
277 if (!pIO->Read32(&m_nType))
278 return false;
279
280 m_nSize = size - sizeof(icTagTypeSignature);
281
282 if (m_nSize > 0) { // size could be stored as smaller than expected value, therefore the size check
283
284 m_pData = new icUInt8Number[m_nSize];
285
286 if (pIO->Read8(m_pData, m_nSize) != (icInt32Number)m_nSize) {
287 return false;
288 }
289 } else {
290 return false;
291 }
292
293 return true;
294}
295
296
297/**
298 ****************************************************************************
299 * Name: CIccTagUnknown::Write
300 *
301 * Purpose: Write an unknown tag to a file
302 *
303 * Args:
304 * pIO - The IO object to write tag to.
305 *
306 * Return:
307 * true = succesful, false = failure
308 *****************************************************************************
309 */
310bool CIccTagUnknown::Write(CIccIO *pIO)
311{
312 if (!pIO)
313 return false;
314
315 if (!pIO->Write32(&m_nType))
316 return false;
317
318 if (m_nSize && m_pData) {
319 if (pIO->Write8(m_pData, m_nSize) != (icInt32Number)m_nSize)
320 return false;
321 }
322
323 return true;
324}
325
326
327/**
328 ****************************************************************************
329 * Name: CIccTagUnknown::Describe
330 *
331 * Purpose: Dump data associated with unknown tag to a string
332 *
333 * Args:
334 * sDescription - string to concatenate tag dump to
335 *****************************************************************************
336 */
337void CIccTagUnknown::Describe(std::string &sDescription)
338{
339 icChar buf[128];
340
341 sDescription = "Unknown Tag Type of ";
342 sprintf(buf, "%u Bytes.", m_nSize-4);
343 sDescription += buf;
344
345 sDescription += "\r\n\r\nData Follows:\r\n";
346
347 icMemDump(sDescription, m_pData+4, m_nSize-4);
348}
349
350
351/**
352 ****************************************************************************
353 * Name: CIccTagText::CIccTagText
354 *
355 * Purpose: Constructor
356 *
357 *****************************************************************************
358 */
359CIccTagText::CIccTagText()
360{
361 m_szText = (icChar*)malloc(1);
362 m_szText[0] = '\0';
363 m_nBufSize = 1;
364}
365
366/**
367 ****************************************************************************
368 * Name: CIccTagText::CIccTagText
369 *
370 * Purpose: Copy Constructor
371 *
372 * Args:
373 * ITT = The CIccTagText object to be copied
374 *****************************************************************************
375 */
376CIccTagText::CIccTagText(const CIccTagText &ITT)
377{
378 m_szText = (icChar*)malloc(1);
379 m_szText[0] = '\0';
380 m_nBufSize = 1;
381 SetText(ITT.m_szText);
382}
383
384/**
385 ****************************************************************************
386 * Name: CIccTagText::operator=
387 *
388 * Purpose: Copy Operator
389 *
390 * Args:
391 * TextTag = The CIccTagText object to be copied
392 *****************************************************************************
393 */
394CIccTagText &CIccTagText::operator=(const CIccTagText &TextTag)
395{
396 if (&TextTag == this)
397 return *this;
398
399 m_szText = (icChar*)malloc(1);
400 m_szText[0] = '\0';
401 m_nBufSize = 1;
402 SetText(TextTag.m_szText);
403
404 return *this;
405}
406
407/**
408 ****************************************************************************
409 * Name: CIccTagText::~CIccTagText
410 *
411 * Purpose: Destructor
412 *
413 *****************************************************************************
414 */
415CIccTagText::~CIccTagText()
416{
417 free(m_szText);
418}
419
420/**
421 ****************************************************************************
422 * Name: CIccTagText::Read
423 *
424 * Purpose: Read in a text type tag into a data block
425 *
426 * Args:
427 * size - # of bytes in tag,
428 * pIO - IO object to read tag from
429 *
430 * Return:
431 * true = successful, false = failure
432 *****************************************************************************
433 */
434bool CIccTagText::Read(icUInt32Number size, CIccIO *pIO)
435{
436 icTagTypeSignature sig;
437
438 if (size<sizeof(icTagTypeSignature) || !pIO) {
439 m_szText[0] = '\0';
440 return false;
441 }
442
443 if (!pIO->Read32(&sig))
444 return false;
445
446 if (!pIO->Read32(&m_nReserved))
447 return false;
448
449 icUInt32Number nSize = size - sizeof(icTagTypeSignature) - sizeof(icUInt32Number);
450
451 icChar *pBuf = GetBuffer(nSize);
452
453 if (nSize) {
454 if (pIO->Read8(pBuf, nSize) != (icInt32Number)nSize) {
455 return false;
456 }
457 }
458
459 Release();
460
461 return true;
462}
463
464/**
465 ****************************************************************************
466 * Name: CIccTagText::Write
467 *
468 * Purpose: Write a text type tag to a file
469 *
470 * Args:
471 * pIO - The IO object to write tag to.
472 *
473 * Return:
474 * true = succesful, false = failure
475 *****************************************************************************
476 */
477bool CIccTagText::Write(CIccIO *pIO)
478{
479 icTagTypeSignature sig = GetType();
480
481 if (!pIO)
482 return false;
483
484 if (!pIO->Write32(&sig))
485 return false;
486
487 if (!pIO->Write32(&m_nReserved))
488 return false;
489
490 if (!m_szText)
491 return false;
492
493 icUInt32Number nSize = (icUInt32Number)strlen(m_szText)+1;
494
495 if (pIO->Write8(m_szText, nSize) != (icInt32Number)nSize)
496 return false;
497
498 return true;
499}
500
501/**
502 ****************************************************************************
503 * Name: CIccTagText::Describe
504 *
505 * Purpose: Dump data associated with the tag to a string
506 *
507 * Args:
508 * sDescription - string to concatenate tag dump to
509 *****************************************************************************
510 */
511void CIccTagText::Describe(std::string &sDescription)
512{
513 sDescription += "\"";
514 if (m_szText && *m_szText)
515 sDescription += m_szText;
516
517 sDescription += "\"\r\n";
518}
519
520
521/**
522 ****************************************************************************
523 * Name: CIccTagText::SetText
524 *
525 * Purpose: Allows text data associated with the tag to be set.
526 *
527 * Args:
528 * szText - zero terminated string to put in tag
529 *****************************************************************************
530 */
531void CIccTagText::SetText(const icChar *szText)
532{
533 if (!szText)
534 SetText("");
535
536 icUInt32Number len=(icUInt32Number)strlen(szText) + 1;
537 icChar *szBuf = GetBuffer(len);
538
539 strcpy(szBuf, szText);
540 Release();
541}
542
543/**
544 ****************************************************************************
545 * Name: *CIccTagText::operator=
546 *
547 * Purpose: Define assignment operator to associate text with tag.
548 *
549 * Args:
550 * szText - zero terminated string to put in the tag
551 *
552 * Return: A pointer to the string assigned to the tag.
553 *****************************************************************************
554 */
555const icChar *CIccTagText::operator=(const icChar *szText)
556{
557 SetText(szText);
558 return m_szText;
559}
560
561/**
562 ******************************************************************************
563 * Name: CIccTagText::GetBuffer
564 *
565 * Purpose: This function allocates room and returns pointer to data buffer to
566 * put string into
567 *
568 * Args:
569 * nSize = Requested size of data buffer.
570 *
571 * Return: The character buffer array
572 *******************************************************************************
573 */
574icChar *CIccTagText::GetBuffer(icUInt32Number nSize)
575{
576 if (m_nBufSize < nSize) {
577 m_szText = (icChar*)icRealloc(m_szText, nSize+1);
578
579 if (m_szText) {
580 m_szText[nSize] = '\0';
581 m_nBufSize = nSize;
582 }
583 else
584 m_nBufSize = 0;
585 }
586
587 return m_szText;
588}
589
590/**
591 ****************************************************************************
592 * Name: CIccTagText::Release
593 *
594 * Purpose: This will resize the buffer to fit the zero terminated string in
595 * the buffer.
596 *****************************************************************************
597 */
598void CIccTagText::Release()
599{
600 icUInt32Number nSize = (icUInt32Number)strlen(m_szText)+1;
601
602 if (nSize < m_nBufSize-1) {
603 m_szText=(icChar*)icRealloc(m_szText, nSize+1);
604 m_nBufSize = nSize+1;
605 }
606}
607
608
609/**
610******************************************************************************
611* Name: CIccTagText::Validate
612*
613* Purpose: Check tag data validity.
614*
615* Args:
616* sig = signature of tag being validated,
617* sReport = String to add report information to
618*
619* Return:
620* icValidateStatusOK if valid, or other error status.
621******************************************************************************
622*/
623icValidateStatus CIccTagText::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
624{
625 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
626
627 CIccInfo Info;
628 std::string sSigPathName = Info.GetSigPathName(sigPath);
629 icSignature sig = icGetFirstSigPathSig(sigPath);
630
631 if (m_nBufSize) {
632 switch(sig) {
633 case icSigCopyrightTag:
634 break;
635 case icSigCharTargetTag:
636 if (m_nBufSize<7) {
637 sReport += icMsgValidateNonCompliant;
638 sReport += sSigPathName;
639 sReport += " - Tag must have at least seven text characters.\r\n";
640 rv = icMaxStatus(rv, icValidateNonCompliant);
641 }
642 break;
643 default:
644 sReport += icMsgValidateWarning;
645 sReport += sSigPathName;
646 sReport += " - Unknown Tag.\r\n";
647 rv = icMaxStatus(rv, icValidateWarning);
648 }
649 int i;
650 for (i=0; m_szText[i] && i<(int)m_nBufSize; i++) {
651 if (m_szText[i]&0x80) {
652 sReport += icMsgValidateWarning;
653 sReport += sSigPathName;
654 sReport += " - Text does not contain just 7-bit data.\r\n";
655 rv = icMaxStatus(rv, icValidateWarning);
656 }
657 }
658 }
659 else {
660 sReport += icMsgValidateWarning;
661 sReport += sSigPathName;
662 sReport += " - Empty Tag.\r\n";
663 rv = icMaxStatus(rv, icValidateWarning);
664 }
665
666
667 return rv;
668}
669
670
671
672/**
673 ****************************************************************************
674 * Name: CIccTagUtf8Text::CIccTagUtf8Text
675 *
676 * Purpose: Constructor
677 *
678 *****************************************************************************
679 */
680CIccTagUtf8Text::CIccTagUtf8Text()
681{
682 m_szText = (icUChar*)malloc(1);
683 m_szText[0] = '\0';
684 m_nBufSize = 1;
685}
686
687/**
688 ****************************************************************************
689 * Name: CIccTagUtf8Text::CIccTagUtf8Text
690 *
691 * Purpose: Copy Constructor
692 *
693 * Args:
694 * ITT = The CIccTagText object to be copied
695 *****************************************************************************
696 */
697CIccTagUtf8Text::CIccTagUtf8Text(const CIccTagUtf8Text &ITT)
698{
699 m_szText = (icUChar*)malloc(1);
700 m_szText[0] = '\0';
701 m_nBufSize = 1;
702 SetText(ITT.m_szText);
703}
704
705/**
706 ****************************************************************************
707 * Name: CIccTagUtf8Text::operator=
708 *
709 * Purpose: Copy Operator
710 *
711 * Args:
712 * TextTag = The CIccTagText object to be copied
713 *****************************************************************************
714 */
715CIccTagUtf8Text &CIccTagUtf8Text::operator=(const CIccTagUtf8Text &TextTag)
716{
717 if (&TextTag == this)
718 return *this;
719
720 m_szText = (icUChar*)malloc(1);
721 m_szText[0] = '\0';
722 m_nBufSize = 1;
723 SetText(TextTag.m_szText);
724
725 return *this;
726}
727
728/**
729 ****************************************************************************
730 * Name: CIccTagUtf8Text::~CIccTagUtf8Text
731 *
732 * Purpose: Destructor
733 *
734 *****************************************************************************
735 */
736CIccTagUtf8Text::~CIccTagUtf8Text()
737{
738 free(m_szText);
739}
740
741/**
742 ****************************************************************************
743 * Name: CIccTagUtf8Text::Read
744 *
745 * Purpose: Read in a text type tag into a data block
746 *
747 * Args:
748 * size - # of bytes in tag,
749 * pIO - IO object to read tag from
750 *
751 * Return:
752 * true = successful, false = failure
753 *****************************************************************************
754 */
755bool CIccTagUtf8Text::Read(icUInt32Number size, CIccIO *pIO)
756{
757 icTagTypeSignature sig;
758
759 if (size<sizeof(icTagTypeSignature) || !pIO) {
760 m_szText[0] = '\0';
761 return false;
762 }
763
764 if (!pIO->Read32(&sig))
765 return false;
766
767 if (!pIO->Read32(&m_nReserved))
768 return false;
769
770 if (size < sizeof(icTagTypeSignature) + sizeof(icUInt32Number))
771 return false;
772
773 icUInt32Number nSize = size - sizeof(icTagTypeSignature) - sizeof(icUInt32Number);
774
775 icUChar *pBuf = GetBuffer(nSize);
776
777 if (nSize) {
778 if (pIO->Read8(pBuf, nSize) != (icInt32Number)nSize) {
779 return false;
780 }
781 }
782
783 Release();
784
785 return true;
786}
787
788/**
789 ****************************************************************************
790 * Name: CIccTagUtf8Text::Write
791 *
792 * Purpose: Write a text type tag to a file
793 *
794 * Args:
795 * pIO - The IO object to write tag to.
796 *
797 * Return:
798 * true = succesful, false = failure
799 *****************************************************************************
800 */
801bool CIccTagUtf8Text::Write(CIccIO *pIO)
802{
803 icTagTypeSignature sig = GetType();
804
805 if (!pIO)
806 return false;
807
808 if (!pIO->Write32(&sig))
809 return false;
810
811 if (!pIO->Write32(&m_nReserved))
812 return false;
813
814 if (!m_szText)
815 return false;
816
817 icUInt32Number nSize = (icUInt32Number)strlen((icChar*)m_szText)+1;
818
819 if (pIO->Write8(m_szText, nSize) != (icInt32Number)nSize)
820 return false;
821
822 return true;
823}
824
825/**
826 ****************************************************************************
827 * Name: CIccTagUtf8Text::Describe
828 *
829 * Purpose: Dump data associated with the tag to a string
830 *
831 * Args:
832 * sDescription - string to concatenate tag dump to
833 *****************************************************************************
834 */
835void CIccTagUtf8Text::Describe(std::string &sDescription)
836{
837 sDescription += "\"";
838 if (m_szText && *m_szText)
839 sDescription += (icChar*)m_szText;
840
841 sDescription += "\"\r\n";
842}
843
844
845/**
846 ****************************************************************************
847 * Name: CIccTagUtf8Text::SetText
848 *
849 * Purpose: Allows text data associated with the tag to be set.
850 *
851 * Args:
852 * szText - zero terminated string to put in tag
853 *****************************************************************************
854 */
855void CIccTagUtf8Text::SetText(const icUChar *szText)
856{
857 if (!szText)
858 SetText("");
859
860 icUInt32Number len=(icUInt32Number)strlen((icChar*)szText) + 1;
861 icUChar *szBuf = GetBuffer(len);
862
863 strcpy((icChar*)szBuf, (icChar*)szText);
864 Release();
865}
866
867
868/**
869 ****************************************************************************
870 * Name: CIccTagUtf8Text::SetText
871 *
872 * Purpose: Allows text data associated with the tag to be set.
873 *
874 * Args:
875 * szText - zero terminated string to put in tag
876 *****************************************************************************
877 */
878void CIccTagUtf8Text::SetText(const icUChar16 *szText)
879{
880 if (!szText)
881 SetText("");
882
883 icUtf8Vector text;
884 icUInt32Number len;
885 for (len=0; szText[len]; len++);
886
887 icConvertUTF16toUTF8(szText, &szText[len], text, lenientConversion);
888
889 SetText((const icUChar*)&text[0]);
890}
891
892/**
893 ****************************************************************************
894 * Name: *CIccTagUtf8Text::operator=
895 *
896 * Purpose: Define assignment operator to associate text with tag.
897 *
898 * Args:
899 * szText - zero terminated string to put in the tag
900 *
901 * Return: A pointer to the string assigned to the tag.
902 *****************************************************************************
903 */
904const icUChar *CIccTagUtf8Text::operator=(const icUChar *szText)
905{
906 SetText(szText);
907 return (icUChar*)m_szText;
908}
909
910/**
911 ******************************************************************************
912 * Name: CIccTagUtf8Text::GetBuffer
913 *
914 * Purpose: This function allocates room and returns pointer to data buffer to
915 * put string into
916 *
917 * Args:
918 * nSize = Requested size of data buffer.
919 *
920 * Return: The character buffer array
921 *******************************************************************************
922 */
923icUChar *CIccTagUtf8Text::GetBuffer(icUInt32Number nSize)
924{
925 if (m_nBufSize < nSize) {
926 m_szText = (icUChar*)icRealloc(m_szText, nSize+1);
927
928 if (m_szText) {
929 m_szText[nSize] = '\0';
930 m_nBufSize = nSize;
931 }
932 else {
933 m_nBufSize = 0;
934 }
935 }
936
937 return m_szText;
938}
939
940/**
941 ****************************************************************************
942 * Name: CIccTagUtf8Text::Release
943 *
944 * Purpose: This will resize the buffer to fit the zero terminated string in
945 * the buffer.
946 *****************************************************************************
947 */
948void CIccTagUtf8Text::Release()
949{
950 icUInt32Number nSize = (icUInt32Number)strlen((icChar*)m_szText)+1;
951
952 if (nSize < m_nBufSize-1) {
953 m_szText=(icUChar*)icRealloc(m_szText, nSize+1);
954 m_nBufSize = nSize+1;
955 }
956}
957
958
959/**
960******************************************************************************
961* Name: CIccTagUtf8Text::Validate
962*
963* Purpose: Check tag data validity.
964*
965* Args:
966* sig = signature of tag being validated,
967* sReport = String to add report information to
968*
969* Return:
970* icValidateStatusOK if valid, or other error status.
971******************************************************************************
972*/
973icValidateStatus CIccTagUtf8Text::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
974{
975 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
976
977 CIccInfo Info;
978 std::string sSigPathName = Info.GetSigPathName(sigPath);
979
980 if (!m_nBufSize) {
981 sReport += icMsgValidateWarning;
982 sReport += sSigPathName;
983 sReport += " - Empty Tag.\r\n";
984 rv = icMaxStatus(rv, icValidateWarning);
985 }
986
987
988 return rv;
989}
990
991
992static unsigned char icFaultyXmlZipData[4] = { 0,0,0,1 };
993
994/**
995 ****************************************************************************
996 * Name: CIccTagZipUtf8Text::CIccTagZipUtf8Text
997 *
998 * Purpose: Constructor
999 *
1000 *****************************************************************************
1001 */
1002CIccTagZipUtf8Text::CIccTagZipUtf8Text()
1003{
1004 m_pZipBuf = NULL__null;
1005 m_nBufSize = 0;
1006}
1007
1008/**
1009 ****************************************************************************
1010 * Name: CIccTagZipUtf8Text::CIccTagZipUtf8Text
1011 *
1012 * Purpose: Copy Constructor
1013 *
1014 * Args:
1015 * ITT = The CIccTagText object to be copied
1016 *****************************************************************************
1017 */
1018CIccTagZipUtf8Text::CIccTagZipUtf8Text(const CIccTagZipUtf8Text &ITT)
1019{
1020 m_pZipBuf = NULL__null;
1021 m_nBufSize = 0;
1022 AllocBuffer(ITT.BufferSize());
1023 if (m_pZipBuf) {
1024 memcpy(m_pZipBuf, ITT.GetBuffer(), m_nBufSize);
1025 }
1026}
1027
1028/**
1029 ****************************************************************************
1030 * Name: CIccTagZipUtf8Text::operator=
1031 *
1032 * Purpose: Copy Operator
1033 *
1034 * Args:
1035 * TextTag = The CIccTagText object to be copied
1036 *****************************************************************************
1037 */
1038CIccTagZipUtf8Text &CIccTagZipUtf8Text::operator=(const CIccTagZipUtf8Text &ITT)
1039{
1040 if (&ITT == this)
1041 return *this;
1042
1043 AllocBuffer(ITT.BufferSize());
1044 if (m_pZipBuf) {
1045 memcpy(m_pZipBuf, ITT.GetBuffer(), m_nBufSize);
1046 }
1047
1048 return *this;
1049}
1050
1051/**
1052 ****************************************************************************
1053 * Name: CIccTagZipUtf8Text::~CIccTagZipUtf8Text
1054 *
1055 * Purpose: Destructor
1056 *
1057 *****************************************************************************
1058 */
1059CIccTagZipUtf8Text::~CIccTagZipUtf8Text()
1060{
1061 if (m_pZipBuf)
1062 free(m_pZipBuf);
1063}
1064
1065/**
1066 ****************************************************************************
1067 * Name: CIccTagZipUtf8Text::Read
1068 *
1069 * Purpose: Read in a text type tag into a data block
1070 *
1071 * Args:
1072 * size - # of bytes in tag,
1073 * pIO - IO object to read tag from
1074 *
1075 * Return:
1076 * true = successful, false = failure
1077 *****************************************************************************
1078 */
1079bool CIccTagZipUtf8Text::Read(icUInt32Number size, CIccIO *pIO)
1080{
1081 icTagTypeSignature sig;
1082
1083 if (size<sizeof(icTagTypeSignature) || !pIO) {
1084 AllocBuffer(0);
1085 return false;
1086 }
1087
1088 if (!pIO->Read32(&sig))
1089 return false;
1090
1091 if (!pIO->Read32(&m_nReserved))
1092 return false;
1093
1094 icUInt32Number nSize = size - sizeof(icTagTypeSignature) - sizeof(icUInt32Number);
1095
1096 icUChar *pBuf = AllocBuffer(nSize);
1097
1098 if (m_nBufSize && pBuf) {
1099 if (pIO->Read8(pBuf, m_nBufSize) != (icInt32Number)m_nBufSize) {
1100 return false;
1101 }
1102 }
1103
1104 return true;
1105}
1106
1107/**
1108 ****************************************************************************
1109 * Name: CIccTagZipUtf8Text::Write
1110 *
1111 * Purpose: Write a text type tag to a file
1112 *
1113 * Args:
1114 * pIO - The IO object to write tag to.
1115 *
1116 * Return:
1117 * true = succesful, false = failure
1118 *****************************************************************************
1119 */
1120bool CIccTagZipUtf8Text::Write(CIccIO *pIO)
1121{
1122 icTagTypeSignature sig = GetType();
1123
1124 if (!pIO)
1125 return false;
1126
1127 if (!pIO->Write32(&sig))
1128 return false;
1129
1130 if (!pIO->Write32(&m_nReserved))
1131 return false;
1132
1133 if (m_pZipBuf) {
1134 if (pIO->Write8(m_pZipBuf, m_nBufSize) != (icInt32Number)m_nBufSize)
1135 return false;
1136 }
1137 return true;
1138}
1139
1140/**
1141 ****************************************************************************
1142 * Name: CIccTagZipUtf8Text::Describe
1143 *
1144 * Purpose: Dump data associated with the tag to a string
1145 *
1146 * Args:
1147 * sDescription - string to concatenate tag dump to
1148 *****************************************************************************
1149 */
1150void CIccTagZipUtf8Text::Describe(std::string &sDescription)
1151{
1152 std::string str;
1153#ifdef ICC_USE_ZLIB
1154 if (!GetText(str)) {
1155 sDescription += "Error! - Unable to decompress text data.\r\n";
1156 }
1157 else if (m_nBufSize > 4 && !memcmp(m_pZipBuf, icFaultyXmlZipData, 4)) {
1158 sDescription += "Warning! - Correcting for improperly encoded ";
1159 sDescription += CIccTagCreator::GetTagTypeSigName(GetType());
1160 sDescription += " tag.\r\n\r\n";
1161 }
1162
1163 sDescription += "ZLib Compressed String=\"";
1164 sDescription += str;
1165 sDescription += "\"\r\n";
1166#else
1167 char size[30];
1168 sprintf(size, "%d", m_nBufSize);
1169 sDescription += "BEGIN_COMPESSED_DATA[\"";
1170 sDescription += size;
1171 sDescription += "]\r\n";
1172 if (m_nBufSize) {
1173 icMemDump(str, m_pZipBuf, m_nBufSize);
1174 sDescription += str;
1175 sDescription += "\r\n";
1176 }
1177 sDescription += "END_COMPRESSED_DATA\r\n";
1178#endif
1179}
1180
1181/**
1182 ****************************************************************************
1183 * Name: CIccTagZipUtf8Text::GetText
1184 *
1185 * Purpose: Allows text data associated with the tag to be set.
1186 *
1187 * Args:
1188 * text - string to put uncompressed text into
1189 *****************************************************************************
1190 */
1191bool CIccTagZipUtf8Text::GetText(std::string &str) const
1192{
1193#ifndef ICC_USE_ZLIB
1194 str="";
1195 return false;
1196#else
1197 int zstat;
1198 z_stream zstr;
1199 memset(&zstr, 0, sizeof(zstr));
1200 unsigned char buf[32767] = { 0 };
1201
1202 zstat = inflateInit(&zstr);
1203
1204 if (zstat != Z_OK) {
1205 return false;
1206 }
1207
1208 zstat = inflateReset(&zstr);
1209
1210 if (zstat != Z_OK) {
1211 return false;
1212 }
1213
1214 if (m_nBufSize > 4 && !memcmp(m_pZipBuf, icFaultyXmlZipData, 4)) {
1215 //xrite creates invalid zipXMLType tags
1216 zstr.next_in = m_pZipBuf+4;
1217 zstr.avail_in = m_nBufSize-4;
1218 }
1219 else {
1220 zstr.next_in = m_pZipBuf;
1221 zstr.avail_in = m_nBufSize;
1222 }
1223
1224 do {
1225 unsigned int i, n;
1226
1227 zstr.next_out = buf;
1228 zstr.avail_out = sizeof(buf);
1229
1230 zstat = inflate(&zstr, Z_SYNC_FLUSH);
1231
1232 if (zstat != Z_OK && zstat != Z_STREAM_END) {
1233 inflateEnd(&zstr);
1234 return false;
1235 }
1236
1237 n = sizeof(buf) - zstr.avail_out;
1238
1239 for (i = 0; i < n; i++) {
1240 str += buf[i];
1241 }
1242 } while (zstat != Z_STREAM_END);
1243
1244 inflateEnd(&zstr);
1245
1246 return true;
1247#endif
1248}
1249
1250
1251/**
1252 ****************************************************************************
1253 * Name: CIccTagZipUtf8Text::SetText
1254 *
1255 * Purpose: Allows text data associated with the tag to be set.
1256 *
1257 * Args:
1258 * szText - zero terminated string to put in tag
1259 *****************************************************************************
1260 */
1261bool CIccTagZipUtf8Text::SetText(const icUChar *szText)
1262{
1263#ifndef ICC_USE_ZLIB
1264 return false;
1265#else
1266 icUInt32Number nSize = (icUInt32Number)strlen((const char*)szText) + 1;
1267 icUtf8Vector compress;
1268 int i;
1269
1270 int zstat;
1271 z_stream zstr;
1272 unsigned char buf[32767];
1273 memset(&zstr, 0, sizeof(zstr));
1274
1275 zstat = deflateInit(&zstr, Z_DEFAULT_COMPRESSION);
1276
1277 if (zstat != Z_OK) {
1278 return false;
1279 }
1280
1281 zstat = deflateReset(&zstr);
1282 zstr.next_in = (Bytef*)szText;
1283 zstr.avail_in = nSize;
1284
1285 if (zstat != Z_OK) {
1286 return false;
1287 }
1288
1289
1290 do {
1291 int n;
1292 zstr.next_out = buf;
1293 zstr.avail_out = sizeof(buf);
1294
1295 zstat = deflate(&zstr, Z_FINISH);
1296
1297 if (zstat != Z_OK && zstat != Z_STREAM_END) {
1298 deflateEnd(&zstr);
1299 return false;
1300 }
1301
1302 n = sizeof(buf) - zstr.avail_out;
1303
1304 for (i = 0; i < n; i++) {
1305 compress.push_back(buf[i]);
1306 }
1307 } while (zstat != Z_STREAM_END);
1308
1309 deflateEnd(&zstr);
1310
1311 icUChar *pBuf = AllocBuffer(compress.size());
1312
1313 if (pBuf) {
1314 for (i = 0; i < m_nBufSize; i++) {
1315 pBuf[i] = compress[i];
1316}
1317 }
1318
1319 return true;
1320#endif
1321}
1322
1323/**
1324 ****************************************************************************
1325 * Name: CIccTagZipUtf8Text::SetText
1326 *
1327 * Purpose: Allows text data associated with the tag to be set.
1328 *
1329 * Args:
1330 * szText - zero terminated string to put in tag
1331 *****************************************************************************
1332 */
1333bool CIccTagZipUtf8Text::SetText(const icUChar16 *szText)
1334{
1335 if (!szText)
1336 return SetText("");
1337
1338 icUtf8Vector text;
1339 icUInt32Number len;
1340 for (len=0; szText[len]; len++);
1341
1342 icConvertUTF16toUTF8(szText, &szText[len], text, lenientConversion);
1343
1344 return SetText((const icUChar*)&text[0]);
1345}
1346
1347
1348
1349/**
1350 ******************************************************************************
1351 * Name: CIccTagZipUtf8Text::AllocBuffer
1352 *
1353 * Purpose: This function allocates room and returns pointer to data buffer to
1354 * put string into
1355 *
1356 * Args:
1357 * nSize = Requested size of data buffer.
1358 *
1359 * Return: The character buffer array
1360 *******************************************************************************
1361 */
1362icUChar *CIccTagZipUtf8Text::AllocBuffer(icUInt32Number nSize)
1363{
1364 if (m_nBufSize != nSize) {
1365 if (!nSize) {
1366 if (m_pZipBuf)
1367 free(m_pZipBuf);
1368
1369 m_nBufSize = nSize;
1370 return NULL__null;
1371 }
1372
1373 if (!m_nBufSize)
1374 m_pZipBuf = (icUChar*)malloc(nSize);
1375 else
1376 m_pZipBuf = (icUChar*)icRealloc(m_pZipBuf, nSize);
1377
1378 m_nBufSize = nSize;
1379
1380 }
1381
1382 return m_pZipBuf;
1383}
1384
1385
1386/**
1387******************************************************************************
1388* Name: CIccTagZipUtf8Text::Validate
1389*
1390* Purpose: Check tag data validity.
1391*
1392* Args:
1393* sig = signature of tag being validated,
1394* sReport = String to add report information to
1395*
1396* Return:
1397* icValidateStatusOK if valid, or other error status.
1398******************************************************************************
1399*/
1400icValidateStatus CIccTagZipUtf8Text::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
1401{
1402 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
1403
1404 CIccInfo Info;
1405 std::string sSigPathName = Info.GetSigPathName(sigPath);
1406
1407 if (!m_nBufSize) {
1408 sReport += icMsgValidateWarning;
1409 sReport += sSigPathName;
1410 sReport += " - Empty Tag.\r\n";
1411 rv = icMaxStatus(rv, icValidateWarning);
1412 }
1413 else {
1414#ifdef ICC_USE_ZLIB
1415 std::string sText;
1416 if (!GetText(sText)) {
1417 sReport += icMsgValidateNonCompliant;
1418 sReport += sSigPathName;
1419 sReport += " - Unable to get text for tag (possibly corrupt compressed data).\r\n";
1420 rv = icMaxStatus(rv, icValidateNonCompliant);
1421 }
1422 else if (m_nBufSize > 4 && !memcmp(m_pZipBuf, icFaultyXmlZipData, 4)) {
1423 sReport += icMsgValidateNonCompliant;
1424 sReport += sSigPathName;
1425 sReport += " - Improperly encoded ";
1426 sReport += CIccTagCreator::GetTagTypeSigName(GetType());
1427 sReport += " tag.\r\n";
1428 rv = icMaxStatus(rv, icValidateNonCompliant);
1429 }
1430#else
1431 sReport += icMsgValidateWarning;
1432 sReport += sSigPathName;
1433 sReport += " - Zip compression not supported by CMM - unable to validate text compression.\r\n";
1434 rv = icMaxStatus(rv, icValidateWarning);
1435#endif
1436 }
1437
1438 return rv;
1439}
1440
1441
1442
1443/**
1444 ****************************************************************************
1445 * Name: CIccTagUtf16Text::CIccTagUtf16Text
1446 *
1447 * Purpose: Constructor
1448 *
1449 *****************************************************************************
1450 */
1451CIccTagUtf16Text::CIccTagUtf16Text()
1452{
1453 m_szText = (icUChar16*)malloc(1*sizeof(icUChar16));
1454 m_szText[0] = 0;
1455 m_nBufSize = 1;
1456}
1457
1458/**
1459 ****************************************************************************
1460 * Name: CIccTagUtf16Text::CIccTagUtf16Text
1461 *
1462 * Purpose: Copy Constructor
1463 *
1464 * Args:
1465 * ITT = The CIccTagText object to be copied
1466 *****************************************************************************
1467 */
1468CIccTagUtf16Text::CIccTagUtf16Text(const CIccTagUtf16Text &ITT)
1469{
1470 m_szText = (icUChar16*)malloc(1*sizeof(icUChar16));
1471 m_szText[0] = 0;
1472 m_nBufSize = 1;
1473 SetText(ITT.m_szText);
1474}
1475
1476/**
1477 ****************************************************************************
1478 * Name: CIccTagUtf16Text::operator=
1479 *
1480 * Purpose: Copy Operator
1481 *
1482 * Args:
1483 * TextTag = The CIccTagText object to be copied
1484 *****************************************************************************
1485 */
1486CIccTagUtf16Text &CIccTagUtf16Text::operator=(const CIccTagUtf16Text &TextTag)
1487{
1488 if (&TextTag == this)
1489 return *this;
1490
1491 m_szText = (icUChar16*)malloc(1*sizeof(icUChar16));
1492 m_szText[0] = '\0';
1493 m_nBufSize = 1;
1494 SetText(TextTag.m_szText);
1495
1496 return *this;
1497}
1498
1499/**
1500 ****************************************************************************
1501 * Name: CIccTagUtf16Text::~CIccTagUtf16Text
1502 *
1503 * Purpose: Destructor
1504 *
1505 *****************************************************************************
1506 */
1507CIccTagUtf16Text::~CIccTagUtf16Text()
1508{
1509 free(m_szText);
1510}
1511
1512/**
1513 ****************************************************************************
1514 * Name: CIccTagUtf16Text::GetLength
1515 *
1516 * Purpose: Get length of utf16 string
1517 *
1518 *****************************************************************************
1519 */
1520icUInt32Number CIccTagUtf16Text::GetLength() const
1521{
1522 icUInt32Number n;
1523 if (!m_szText || !m_nBufSize)
1524 return 0;
1525
1526 for (n=0; n<m_nBufSize && m_szText[n]; n++);
1527
1528 return n;
1529}
1530
1531/**
1532 ****************************************************************************
1533 * Name: CIccTagUtf16Text::Read
1534 *
1535 * Purpose: Read in a text type tag into a data block
1536 *
1537 * Args:
1538 * size - # of bytes in tag,
1539 * pIO - IO object to read tag from
1540 *
1541 * Return:
1542 * true = successful, false = failure
1543 *****************************************************************************
1544 */
1545bool CIccTagUtf16Text::Read(icUInt32Number size, CIccIO *pIO)
1546{
1547 icTagTypeSignature sig;
1548
1549 if (size<sizeof(icTagTypeSignature) || !pIO) {
1550 m_szText[0] = '\0';
1551 return false;
1552 }
1553
1554 if (!pIO->Read32(&sig))
1555 return false;
1556
1557 if (!pIO->Read32(&m_nReserved))
1558 return false;
1559
1560 icUInt32Number nSize = (size - sizeof(icTagTypeSignature) - sizeof(icUInt32Number))/sizeof(icUChar16);
1561
1562 icUChar16 *pBuf = GetBuffer(nSize);
1563
1564 if (nSize) {
1565 if (pIO->Read16(pBuf, nSize) != (icInt32Number)nSize) {
1566 return false;
1567 }
1568 }
1569
1570 Release();
1571
1572 return true;
1573}
1574
1575/**
1576 ****************************************************************************
1577 * Name: CIccTagUtf16Text::Write
1578 *
1579 * Purpose: Write a text type tag to a file
1580 *
1581 * Args:
1582 * pIO - The IO object to write tag to.
1583 *
1584 * Return:
1585 * true = succesful, false = failure
1586 *****************************************************************************
1587 */
1588bool CIccTagUtf16Text::Write(CIccIO *pIO)
1589{
1590 icTagTypeSignature sig = GetType();
1591
1592 if (!pIO)
1593 return false;
1594
1595 if (!pIO->Write32(&sig))
1596 return false;
1597
1598 if (!pIO->Write32(&m_nReserved))
1599 return false;
1600
1601 if (!m_szText)
1602 return false;
1603
1604 icUInt32Number nSize = GetLength();
1605
1606 if (nSize) {
1607 if (pIO->Write16(m_szText, nSize) != (icInt32Number)nSize)
1608 return false;
1609 }
1610
1611 return true;
1612}
1613
1614/**
1615 ****************************************************************************
1616 * Name: CIccTagUtf16Text::Describe
1617 *
1618 * Purpose: Dump data associated with the tag to a string
1619 *
1620 * Args:
1621 * sDescription - string to concatenate tag dump to
1622 *****************************************************************************
1623 */
1624void CIccTagUtf16Text::Describe(std::string &sDescription)
1625{
1626 sDescription += "\"";
1627 if (m_szText && *m_szText) {
1628 std::string buf;
1629 sDescription += GetText(buf);
1630 }
1631
1632 sDescription += "\"\r\n";
1633}
1634
1635/**
1636 ****************************************************************************
1637 * Name: CIccTagUtf16Text::GetText
1638 *
1639 * Purpose: Allows text data associated with the tag to be set.
1640 *
1641 * Args:
1642 * szText - zero terminated string to put in tag
1643 *****************************************************************************
1644 */
1645const icChar *CIccTagUtf16Text::GetText(std::string &buf) const
1646{
1647 icUtf8Vector str;
1648
1649 icConvertUTF16toUTF8(m_szText, &m_szText[GetLength()], str, lenientConversion);
1650
1651 buf.clear();
1652 icUtf8Vector::iterator c;
1653 c=str.begin();
1654 if (str.size()>2 && (str[0]==0xff && str[1]==0xfe)) {
1655 c++; c++;
1656 }
1657 for (; c!=str.end(); c++)
1658 buf.push_back(*c);
1659
1660 return buf.c_str();
1661}
1662
1663
1664/**
1665 ****************************************************************************
1666 * Name: CIccTagUtf16Text::SetText
1667 *
1668 * Purpose: Allows text data associated with the tag to be set.
1669 *
1670 * Args:
1671 * szText - zero terminated string to put in tag
1672 *****************************************************************************
1673 */
1674void CIccTagUtf16Text::SetText(const icUChar16 *szText)
1675{
1676 if (!szText) {
1677 icUChar16 c=0;
1678 SetText(&c);
1679 }
1680
1681 icUInt32Number n;
1682 for (n=0; szText[n]; n++);
1683
1684 icUInt32Number len=n + 1;
1685 icUChar16 *szBuf = GetBuffer(len);
1686
1687 memcpy(szBuf, szText, len*sizeof(icUChar16));
1688 Release();
1689}
1690
1691/**
1692 ****************************************************************************
1693 * Name: CIccTagUtf16Text::SetText
1694 *
1695 * Purpose: Allows text data associated with the tag to be set.
1696 *
1697 * Args:
1698 * szText - zero terminated string to put in tag
1699 *****************************************************************************
1700 */
1701void CIccTagUtf16Text::SetText(const icUChar *szText)
1702{
1703 if (!szText) {
1704 icUChar16 c=0;
1705 SetText(&c);
1706 }
1707
1708 icUtf16Vector str;
1709 icConvertUTF8toUTF16(szText, szText+strlen((icChar*)szText)+1, str, lenientConversion);
1710
1711 int pos = 0;
1712 if (str[0]==0xfeff) {
1713 pos = 1;
1714 }
1715
1716 icUInt32Number nSize = (icUInt32Number)(str.size()-pos);
1717 icUChar16 *szBuf = GetBuffer(nSize);
1718
1719 if (nSize)
1720 memcpy(m_szText, &str[pos], nSize*sizeof(icUChar));
1721 Release();
1722}
1723
1724/**
1725 ****************************************************************************
1726 * Name: *CIccTagUtf16Text::operator=
1727 *
1728 * Purpose: Define assignment operator to associate text with tag.
1729 *
1730 * Args:
1731 * szText - zero terminated string to put in the tag
1732 *
1733 * Return: A pointer to the string assigned to the tag.
1734 *****************************************************************************
1735 */
1736const icUChar16 *CIccTagUtf16Text::operator=(const icUChar16 *szText)
1737{
1738 SetText(szText);
1739 return (icUChar16*)m_szText;
1740}
1741
1742/**
1743 ******************************************************************************
1744 * Name: CIccTagUtf16Text::GetBuffer
1745 *
1746 * Purpose: This function allocates room and returns pointer to data buffer to
1747 * put string into
1748 *
1749 * Args:
1750 * nSize = Requested size of data buffer.
1751 *
1752 * Return: The utf16 character buffer array
1753 *******************************************************************************
1754 */
1755icUChar16 *CIccTagUtf16Text::GetBuffer(icUInt32Number nSize)
1756{
1757 if (m_nBufSize < nSize) {
1758 m_szText = (icUChar16*)icRealloc(m_szText, (nSize+1)*sizeof(icUChar16));
1759
1760 m_szText[nSize] = 0;
1761
1762 m_nBufSize = nSize;
1763 }
1764
1765 return m_szText;
1766}
1767
1768/**
1769 ****************************************************************************
1770 * Name: CIccTagUtf16Text::Release
1771 *
1772 * Purpose: This will resize the buffer to fit the zero terminated string in
1773 * the buffer.
1774 *****************************************************************************
1775 */
1776void CIccTagUtf16Text::Release()
1777{
1778 icUInt32Number nSize = GetLength()+1;
1779
1780 if (nSize < m_nBufSize-1) {
1781 m_szText=(icUChar16*)icRealloc(m_szText, (nSize+1)*sizeof(icUChar16));
1782 m_nBufSize = nSize+1;
1783 }
1784}
1785
1786
1787/**
1788******************************************************************************
1789* Name: CIccTagUtf16Text::Validate
1790*
1791* Purpose: Check tag data validity.
1792*
1793* Args:
1794* sig = signature of tag being validated,
1795* sReport = String to add report information to
1796*
1797* Return:
1798* icValidateStatusOK if valid, or other error status.
1799******************************************************************************
1800*/
1801icValidateStatus CIccTagUtf16Text::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
1802{
1803 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
1804
1805 CIccInfo Info;
1806 std::string sSigPathName = Info.GetSigPathName(sigPath);
1807
1808 if (!m_nBufSize) {
1809 sReport += icMsgValidateWarning;
1810 sReport += sSigPathName;
1811 sReport += " - Empty Tag.\r\n";
1812 rv = icMaxStatus(rv, icValidateWarning);
1813 }
1814
1815 return rv;
1816}
1817
1818
1819
1820/**
1821 ****************************************************************************
1822 * Name: CIccTagTextDescription::CIccTagTextDescription
1823 *
1824 * Purpose: Constructor
1825 *
1826 *****************************************************************************
1827 */
1828CIccTagTextDescription::CIccTagTextDescription()
1829{
1830 m_szText = (icChar*)malloc(1);
1831 m_szText[0] = '\0';
1832 m_nASCIISize = 1;
1833
1834 m_uzUnicodeText = (icUInt16Number*)malloc(sizeof(icUInt16Number));
1835 m_uzUnicodeText[0] = 0;
1836 m_nUnicodeSize = 1;
1837 m_nUnicodeLanguageCode = 0;
1838
1839 m_nScriptSize = 0;
1840 m_nScriptCode = 0;
1841 memset(m_szScriptText, 0, sizeof(m_szScriptText));
1842
1843 m_bInvalidScript = false;
1844}
1845
1846/**
1847 ****************************************************************************
1848 * Name: CIccTagTextDescription::CIccTagTextDescription
1849 *
1850 * Purpose: Copy Constructor
1851 *
1852 * Args:
1853 * ITTD = The CIccTagTextDescription object to be copied
1854 *****************************************************************************
1855 */
1856CIccTagTextDescription::CIccTagTextDescription(const CIccTagTextDescription &ITTD)
1857{
1858 m_nASCIISize = ITTD.m_nASCIISize;
1859 m_nUnicodeSize = ITTD.m_nUnicodeSize;
1860 m_nUnicodeLanguageCode = ITTD.m_nUnicodeLanguageCode;
1861 m_nScriptSize = ITTD.m_nScriptSize;
1862 m_nScriptCode = ITTD.m_nScriptCode;
1863
1864 if (m_nASCIISize) {
1865 m_szText = (icChar*)malloc(m_nASCIISize * sizeof(icChar));
1866 memcpy(m_szText, ITTD.m_szText, m_nASCIISize*sizeof(icChar));
1867 }
1868 else {
1869 m_nASCIISize = 1;
1870 m_szText = (icChar*)calloc(m_nASCIISize, sizeof(icChar));
1871 m_szText[0] = '\0';
1872 }
1873
1874 if (m_nUnicodeSize) {
1875 m_uzUnicodeText = (icUInt16Number*)malloc((m_nUnicodeSize) * sizeof(icUInt16Number));
1876 memcpy(m_uzUnicodeText, ITTD.m_uzUnicodeText, m_nUnicodeSize*sizeof(icUInt16Number));
1877 }
1878 else {
1879 m_nUnicodeSize = 1;
1880 m_uzUnicodeText = (icUInt16Number*)calloc(m_nUnicodeSize, sizeof(icUInt16Number));
1881 m_uzUnicodeText[0] = 0;
1882 }
1883
1884 memcpy(m_szScriptText, ITTD.m_szScriptText, sizeof(m_szScriptText));
1885
1886 m_bInvalidScript = ITTD.m_bInvalidScript;
1887}
1888
1889
1890/**
1891 ****************************************************************************
1892 * Name: CIccTagTextDescription::operator=
1893 *
1894 * Purpose: Copy Operator
1895 *
1896 * Args:
1897 * TextDescTag = The CIccTagTextDescription object to be copied
1898 *****************************************************************************
1899 */
1900CIccTagTextDescription &CIccTagTextDescription::operator=(const CIccTagTextDescription& TextDescTag)
1901{
1902 if (&TextDescTag == this)
1903 return *this;
1904
1905 m_nASCIISize = TextDescTag.m_nASCIISize;
1906 m_nUnicodeSize = TextDescTag.m_nUnicodeSize;
1907 m_nUnicodeLanguageCode = TextDescTag.m_nUnicodeLanguageCode;
1908 m_nScriptSize = TextDescTag.m_nScriptSize;
1909 m_nScriptCode = TextDescTag.m_nScriptCode;
1910
1911 if (m_szText)
1912 free(m_szText);
1913 if (m_nASCIISize) {
1914 m_szText = (icChar*)calloc(m_nASCIISize, sizeof(icChar));
1915 memcpy(m_szText, TextDescTag.m_szText, m_nASCIISize*sizeof(icChar));
1916 }
1917 else {
1918 m_nASCIISize = 1;
1919 m_szText = (icChar*)calloc(m_nASCIISize, sizeof(icChar));
1920 m_szText[0] = '\0';
1921 }
1922
1923 if (m_uzUnicodeText)
1924 free(m_uzUnicodeText);
1925 if (m_nUnicodeSize) {
1926 m_uzUnicodeText = (icUInt16Number*)calloc(m_nUnicodeSize, sizeof(icUInt16Number));
1927 memcpy(m_uzUnicodeText, TextDescTag.m_uzUnicodeText, m_nUnicodeSize*sizeof(icUInt16Number));
1928 }
1929 else {
1930 m_nUnicodeSize = 1;
1931 m_uzUnicodeText = (icUInt16Number*)calloc(m_nUnicodeSize, sizeof(icUInt16Number));
1932 m_uzUnicodeText[0] = 0;
1933 }
1934
1935 memcpy(m_szScriptText, TextDescTag.m_szScriptText, sizeof(m_szScriptText));
1936
1937 m_bInvalidScript = TextDescTag.m_bInvalidScript;
1938
1939 return *this;
1940}
1941
1942/**
1943 ****************************************************************************
1944 * Name: CIccTagTextDescription::~CIccTagTextDescription
1945 *
1946 * Purpose: Destructor
1947 *
1948 *****************************************************************************
1949 */
1950CIccTagTextDescription::~CIccTagTextDescription()
1951{
1952 free(m_szText);
1953 free(m_uzUnicodeText);
1954}
1955
1956/**
1957 ****************************************************************************
1958 * Name: CIccTagTextDescription::Read
1959 *
1960 * Purpose: Read in the tag contents into a data block
1961 *
1962 * Args:
1963 * size - # of bytes in tag,
1964 * pIO - IO object to read tag from
1965 *
1966 * Return:
1967 * true = successful, false = failure
1968 *****************************************************************************
1969 */
1970bool CIccTagTextDescription::Read(icUInt32Number size, CIccIO *pIO)
1971{
1972 icTagTypeSignature sig;
1973 icUInt32Number nEnd;
1974
1975 nEnd = pIO->Tell() + size;
1976
1977 if (size<3*sizeof(icUInt32Number) || !pIO) {
1978 m_szText[0] = '\0';
1979 return false;
1980 }
1981
1982 icUInt32Number nSize;
1983
1984 if (!pIO->Read32(&sig) ||
1985 !pIO->Read32(&m_nReserved) ||
1986 !pIO->Read32(&nSize))
1987 return false;
1988
1989 if (3*sizeof(icUInt32Number) + nSize > size)
1990 return false;
1991
1992 icChar *pBuf = GetBuffer(nSize);
1993
1994 if (nSize) {
1995 if (pIO->Read8(pBuf, nSize) != (icInt32Number)nSize) {
1996 return false;
1997 }
1998 }
1999 else
2000 m_szText[0] = '\0';
2001
2002 Release();
2003
2004 if (pIO->Tell() + 2 * sizeof(icUInt32Number) > nEnd)
2005 return false;
2006
2007 if (!pIO->Read32(&m_nUnicodeLanguageCode) ||
2008 !pIO->Read32(&nSize))
2009 return false;
2010
2011 icUInt16Number *pBuf16 = GetUnicodeBuffer(nSize);
2012
2013 if (nSize) {
2014 if (pIO->Read16(pBuf16, nSize) != (icInt32Number)nSize) {
2015 return false;
2016 }
2017 }
2018 else
2019 pBuf16[0] = 0;
2020
2021 ReleaseUnicode();
2022
2023 if (pIO->Tell()+3 > (icInt32Number)nEnd)
2024 return false;
2025
2026 if (!pIO->Read16(&m_nScriptCode) ||
2027 !pIO->Read8(&m_nScriptSize))
2028 return false;
2029
2030 if (pIO->Tell() + m_nScriptSize> (icInt32Number)nEnd ||
2031 m_nScriptSize > sizeof(m_szScriptText))
2032 return false;
2033
2034 int nScriptLen = pIO->Read8(m_szScriptText, 67);
2035
2036 if (!nScriptLen)
2037 return false;
2038
2039 if (nScriptLen<67) {
2040 memset(&m_szScriptText[0], 0, 67-nScriptLen);
2041 m_bInvalidScript = true;
2042 }
2043
2044 return true;
2045}
2046
2047/**
2048 ****************************************************************************
2049 * Name: CIccTagTextDescription::Write
2050 *
2051 * Purpose: Write the tag to a file
2052 *
2053 * Args:
2054 * pIO - The IO object to write tag to.
2055 *
2056 * Return:
2057 * true = succesful, false = failure
2058 *****************************************************************************
2059 */
2060bool CIccTagTextDescription::Write(CIccIO *pIO)
2061{
2062 icTagTypeSignature sig = GetType();
2063 icUInt32Number zero = 0;
2064
2065 if (!pIO)
2066 return false;
2067
2068 if (!pIO->Write32(&sig) ||
2069 !pIO->Write32(&m_nReserved) ||
2070 !pIO->Write32(&m_nASCIISize))
2071 return false;
2072
2073 if (m_nASCIISize) {
2074 if (pIO->Write8(m_szText, m_nASCIISize) != (icInt32Number)m_nASCIISize)
2075 return false;
2076 }
2077
2078 if (!pIO->Write32(&m_nUnicodeLanguageCode))
2079 return false;
2080
2081 if (m_nUnicodeSize > 1) {
2082 if (!pIO->Write32(&m_nUnicodeSize) ||
2083 pIO->Write16(m_uzUnicodeText, m_nUnicodeSize) != (icInt32Number)m_nUnicodeSize)
2084 return false;
2085 }
2086 else {
2087 if (!pIO->Write32(&zero))
2088 return false;
2089 }
2090
2091 if (!pIO->Write16(&m_nScriptCode) ||
2092 !pIO->Write8(&m_nScriptSize) ||
2093 pIO->Write8(m_szScriptText, 67)!= 67)
2094 return false;
2095
2096 m_bInvalidScript = false;
2097
2098 return true;
2099}
2100
2101/**
2102 ****************************************************************************
2103 * Name: CIccTagTextDescription::Describe
2104 *
2105 * Purpose: Dump data associated with the tag to a string
2106 *
2107 * Args:
2108 * sDescription - string to concatenate tag dump to
2109 *****************************************************************************
2110 */
2111void CIccTagTextDescription::Describe(std::string &sDescription)
2112{
2113 sDescription += "\"";
2114 if (m_szText && *m_szText)
2115 sDescription += m_szText;
2116
2117 sDescription += "\"\r\n";
2118}
2119
2120
2121/**
2122 ****************************************************************************
2123 * Name: CIccTagTextDescription::SetText
2124 *
2125 * Purpose: Allows text data associated with the tag to be set.
2126 *
2127 * Args:
2128 * szText - zero terminated string to put in tag
2129 *****************************************************************************
2130 */
2131void CIccTagTextDescription::SetText(const icChar *szText)
2132{
2133 m_bInvalidScript = false;
2134
2135 if (!szText)
2136 SetText("");
2137
2138 icUInt32Number len=(icUInt32Number)strlen(szText) + 1;
2139 icChar *szBuf = GetBuffer(len);
2140
2141 strcpy(szBuf, szText);
2142 Release();
2143}
2144
2145/**
2146 ****************************************************************************
2147 * Name: CIccTagTextDescription::operator=
2148 *
2149 * Purpose: Define assignment operator to associate text with tag.
2150 *
2151 * Args:
2152 * szText - zero terminated string to put in the tag
2153 *
2154 * Return: A pointer to the string assigned to the tag.
2155 *****************************************************************************
2156 */
2157const icChar *CIccTagTextDescription::operator=(const icChar *szText)
2158{
2159 SetText(szText);
2160 return m_szText;
2161}
2162
2163/**
2164 ****************************************************************************
2165 * Name: CIccTagTextDescription::GetBuffer
2166 *
2167 * Purpose: This function allocates room and returns pointer to data buffer to
2168 * put string into
2169 *
2170 * Args:
2171 * nSize = Requested size of data buffer.
2172 *
2173 * Return:
2174 *****************************************************************************
2175 */
2176icChar *CIccTagTextDescription::GetBuffer(icUInt32Number nSize)
2177{
2178 if (m_nASCIISize < nSize) {
2179 m_szText = (icChar*)icRealloc(m_szText, nSize+1);
2180
2181 m_szText[nSize] = '\0';
2182
2183 m_nASCIISize = nSize;
2184 }
2185
2186 return m_szText;
2187}
2188
2189/**
2190 ****************************************************************************
2191 * Name: CIccTagTextDescription::Release
2192 *
2193 * Purpose: This will resize the buffer to fit the zero terminated string in
2194 * the buffer.
2195 *****************************************************************************
2196 */
2197void CIccTagTextDescription::Release()
2198{
2199 icUInt32Number nSize = (icUInt32Number)strlen(m_szText);
2200
2201 if (nSize < m_nASCIISize-1) {
2202 m_szText=(icChar*)icRealloc(m_szText, nSize+1);
2203 m_nASCIISize = nSize+1;
2204 }
2205}
2206
2207/**
2208 ****************************************************************************
2209 * Name: CIccTagTextDescription::GetUnicodeBuffer
2210 *
2211 * Purpose: This function allocates room and returns pointer to data buffer to
2212 * put string into
2213 *
2214 * Args:
2215 * nSize = Requested size of data buffer.
2216 *
2217 * Return:
2218 *****************************************************************************
2219 */
2220icUInt16Number *CIccTagTextDescription::GetUnicodeBuffer(icUInt32Number nSize)
2221{
2222 if (m_nUnicodeSize < nSize) {
2223 m_uzUnicodeText = (icUInt16Number*)icRealloc(m_uzUnicodeText, (nSize+1)*sizeof(icUInt16Number));
2224
2225 m_uzUnicodeText[nSize] = 0;
2226
2227 m_nUnicodeSize = nSize;
2228 }
2229
2230 return m_uzUnicodeText;
2231}
2232
2233/**
2234 ****************************************************************************
2235 * Name: CIccTagTextDescription::ReleaseUnicode
2236 *
2237 * Purpose: This will resize the buffer to fit the zero terminated string in
2238 * the buffer.
2239 *****************************************************************************
2240 */
2241void CIccTagTextDescription::ReleaseUnicode()
2242{
2243 int i;
2244 for (i=0; m_uzUnicodeText[i]; i++);
2245
2246 icUInt32Number nSize = i+1;
2247
2248 if (nSize < m_nUnicodeSize-1) {
2249 m_uzUnicodeText=(icUInt16Number*)icRealloc(m_uzUnicodeText, (nSize+1)*sizeof(icUInt16Number));
2250 m_nUnicodeSize = nSize+1;
2251 }
2252}
2253
2254
2255/**
2256******************************************************************************
2257* Name: CIccTagTextDescription::Validate
2258*
2259* Purpose: Check tag data validity.
2260*
2261* Args:
2262* sig = signature of tag being validated,
2263* sReport = String to add report information to
2264*
2265* Return:
2266* icValidateStatusOK if valid, or other error status.
2267******************************************************************************
2268*/
2269icValidateStatus CIccTagTextDescription::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
2270{
2271 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
2272
2273 CIccInfo Info;
2274 std::string sSigPathName = Info.GetSigPathName(sigPath);
2275
2276 if (m_nScriptSize>67) {
2277 sReport += icMsgValidateNonCompliant;
2278 sReport += sSigPathName;
2279 sReport += " - ScriptCode count must not be greater than 67.\r\n";
2280
2281 rv =icMaxStatus(rv, icValidateNonCompliant);
2282 }
2283
2284 if (m_bInvalidScript) {
2285 sReport += icMsgValidateNonCompliant;
2286 sReport += sSigPathName;
2287 sReport += " - ScriptCode must contain 67 bytes.\r\n";
2288
2289 rv =icMaxStatus(rv, icValidateNonCompliant);
2290 }
2291
2292 return rv;
2293}
2294
2295/**
2296 ****************************************************************************
2297 * Name: CIccTagSignature::CIccTagSignature
2298 *
2299 * Purpose: Constructor
2300 *
2301 *****************************************************************************
2302 */
2303CIccTagSignature::CIccTagSignature()
2304{
2305 m_nSig = 0x3f3f3f3f; //'????';
2306}
2307
2308
2309
2310/**
2311 ****************************************************************************
2312 * Name: CIccTagSignature::CIccTagSignature
2313 *
2314 * Purpose: Copy Constructor
2315 *
2316 * Args:
2317 * ITS = The CIccTagSignature object to be copied
2318 *****************************************************************************
2319 */
2320CIccTagSignature::CIccTagSignature(const CIccTagSignature &ITS)
2321{
2322 m_nSig = ITS.m_nSig;
2323}
2324
2325
2326
2327/**
2328 ****************************************************************************
2329 * Name: CIccTagSignature::operator=
2330 *
2331 * Purpose: Copy Operator
2332 *
2333 * Args:
2334 * SignatureTag = The CIccTagSignature object to be copied
2335 *****************************************************************************
2336 */
2337CIccTagSignature &CIccTagSignature::operator=(const CIccTagSignature &SignatureTag)
2338{
2339 if (&SignatureTag == this)
2340 return *this;
2341
2342 m_nSig = SignatureTag.m_nSig;
2343
2344 return *this;
2345}
2346
2347
2348/**
2349 ****************************************************************************
2350 * Name: CIccTagSignature::~CIccTagSignature
2351 *
2352 * Purpose: Destructor
2353 *
2354 *****************************************************************************
2355 */
2356CIccTagSignature::~CIccTagSignature()
2357{
2358}
2359
2360/**
2361 ****************************************************************************
2362 * Name: CIccTagSignature::Read
2363 *
2364 * Purpose: Read in the tag contents into a data block
2365 *
2366 * Args:
2367 * size - # of bytes in tag,
2368 * pIO - IO object to read tag from
2369 *
2370 * Return:
2371 * true = successful, false = failure
2372 *****************************************************************************
2373 */
2374bool CIccTagSignature::Read(icUInt32Number size, CIccIO *pIO)
2375{
2376 icTagTypeSignature sig;
2377
2378 if (sizeof(icTagTypeSignature) + 2*sizeof(icUInt32Number) > size)
2379 return false;
2380
2381 if (!pIO) {
2382 m_nSig = 0x3f3f3f3f; //'????';
2383 return false;
2384 }
2385
2386 if (!pIO->Read32(&sig))
2387 return false;
2388
2389 if (!pIO->Read32(&m_nReserved))
2390 return false;
2391
2392 if (!pIO->Read32(&m_nSig))
2393 return false;
2394
2395 return true;
2396}
2397
2398/**
2399 ****************************************************************************
2400 * Name: CIccTagSignature::Write
2401 *
2402 * Purpose: Write the tag to a file
2403 *
2404 * Args:
2405 * pIO - The IO object to write tag to.
2406 *
2407 * Return:
2408 * true = succesful, false = failure
2409 *****************************************************************************
2410 */
2411bool CIccTagSignature::Write(CIccIO *pIO)
2412{
2413 icTagTypeSignature sig = GetType();
2414
2415 if (!pIO)
2416 return false;
2417
2418 if (!pIO->Write32(&sig))
2419 return false;
2420
2421 if (!pIO->Write32(&m_nReserved))
2422 return false;
2423
2424 if (!pIO->Write32(&m_nSig))
2425 return false;
2426
2427 return true;
2428}
2429
2430
2431/**
2432 ****************************************************************************
2433 * Name: CIccTagSignature::Describe
2434 *
2435 * Purpose: Dump data associated with the tag to a string
2436 *
2437 * Args:
2438 * sDescription - string to concatenate tag dump to
2439 *****************************************************************************
2440 */
2441void CIccTagSignature::Describe(std::string &sDescription)
2442{
2443 CIccInfo Fmt;
2444
2445 sDescription += Fmt.GetSigName(m_nSig);
2446 sDescription += "\r\n";
2447}
2448
2449
2450/**
2451******************************************************************************
2452* Name: CIccTagSignature::Validate
2453*
2454* Purpose: Check tag data validity.
2455*
2456* Args:
2457* sig = signature of tag being validated,
2458* sReport = String to add report information to
2459*
2460* Return:
2461* icValidateStatusOK if valid, or other error status.
2462******************************************************************************
2463*/
2464icValidateStatus CIccTagSignature::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
2465{
2466 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
2467
2468 CIccInfo Info;
2469 std::string sSigPathName = Info.GetSigPathName(sigPath);
2470 icSignature sig = icGetFirstSigPathSig(sigPath);
2471 char buf[128];
2472
2473 if (sig==icSigTechnologyTag) {
2474 switch(m_nSig) {
2475 case icSigFilmScanner:
2476 case icSigDigitalCamera:
2477 case icSigReflectiveScanner:
2478 case icSigInkJetPrinter:
2479 case icSigThermalWaxPrinter:
2480 case icSigElectrophotographicPrinter:
2481 case icSigElectrostaticPrinter:
2482 case icSigDyeSublimationPrinter:
2483 case icSigPhotographicPaperPrinter:
2484 case icSigFilmWriter:
2485 case icSigVideoMonitor:
2486 case icSigVideoCamera:
2487 case icSigProjectionTelevision:
2488 case icSigCRTDisplay:
2489 case icSigPMDisplay:
2490 case icSigAMDisplay:
2491 case icSigPhotoCD:
2492 case icSigPhotoImageSetter:
2493 case icSigGravure:
2494 case icSigOffsetLithography:
2495 case icSigSilkscreen:
2496 case icSigFlexography:
2497 case icSigMotionPictureFilmScanner:
2498 case icSigMotionPictureFilmRecorder:
2499 case icSigDigitalMotionPictureCamera:
2500 case icSigDigitalCinemaProjector:
2501 break;
2502
2503 default:
2504 {
2505 sReport += icMsgValidateNonCompliant;
2506 sReport += sSigPathName;
2507 sprintf(buf, " - %s: Unknown Technology.\r\n", Info.GetSigName(m_nSig));
2508 sReport += buf;
2509 rv = icMaxStatus(rv, icValidateNonCompliant);
2510 }
2511 }
2512 }
2513 else if (sig==icSigPerceptualRenderingIntentGamutTag ||
2514 sig==icSigSaturationRenderingIntentGamutTag) {
2515 switch(m_nSig) {
2516 case icSigPerceptualReferenceMediumGamut:
2517 break;
2518
2519 default:
2520 {
2521 sReport += icMsgValidateNonCompliant;
2522 sReport += sSigPathName;
2523 sprintf(buf, " - %s: Unknown Reference Medium Gamut.\r\n", Info.GetSigName(m_nSig));
2524 sReport += buf;
2525 rv = icMaxStatus(rv, icValidateNonCompliant);
2526 }
2527 }
2528 }
2529 else if (sig==icSigColorimetricIntentImageStateTag) {
2530 switch(m_nSig) {
2531 case icSigSceneColorimetryEstimates:
2532 case icSigSceneAppearanceEstimates:
2533 case icSigFocalPlaneColorimetryEstimates:
2534 case icSigReflectionHardcopyOriginalColorimetry:
2535 case icSigReflectionPrintOutputColorimetry:
2536 break;
2537
2538 default:
2539 {
2540 sReport += icMsgValidateNonCompliant;
2541 sReport += sSigPathName;
2542 sprintf(buf, " - %s: Unknown Colorimetric Intent Image State.\r\n", Info.GetSigName(m_nSig));
2543 sReport += buf;
2544 rv = icMaxStatus(rv, icValidateNonCompliant);
2545 }
2546 }
2547 }
2548
2549
2550 return rv;
2551}
2552
2553/**
2554 ****************************************************************************
2555 * Name: CIccTagNamedColor2::CIccTagNamedColor2
2556 *
2557 * Purpose: Constructor
2558 *
2559 * Args:
2560 * nSize = number of named color entries,
2561 * nDeviceCoords = number of device channels
2562 *****************************************************************************
2563 */
2564CIccTagNamedColor2::CIccTagNamedColor2(int nSize/*=1*/, int nDeviceCoords/*=0*/)
2565{
2566 m_nSize = nSize <1 ? 1 : nSize;
2567 m_nVendorFlags = 0;
2568 m_nDeviceCoords = nDeviceCoords;
2569 if (nDeviceCoords<0)
2570 m_nDeviceCoords = nDeviceCoords = 0;
2571
2572 if (nDeviceCoords>0)
2573 nDeviceCoords--;
2574
2575 m_szPrefix[0] = '\0';
2576 m_szSufix[0] = '\0';
2577 m_csPCS = icSigUnknownData((icColorSpaceSignature) 0x3f3f3f3f);
2578 m_csDevice = icSigUnknownData((icColorSpaceSignature) 0x3f3f3f3f);
2579
2580 m_nColorEntrySize = 32/*rootName*/ + (3/*PCS*/ + 1/*iAny*/ + nDeviceCoords)*sizeof(icFloatNumber);
2581
2582 m_NamedColor = (SIccNamedColorEntry*)calloc(nSize, m_nColorEntrySize);
2583
2584 m_NamedLab = NULL__null;
2585}
2586
2587
2588/**
2589 ****************************************************************************
2590 * Name: CIccTagNamedColor2::CIccTagNamedColor2
2591 *
2592 * Purpose: Copy Constructor
2593 *
2594 * Args:
2595 * ITNC = The CIccTagNamedColor2 object to be copied
2596 *****************************************************************************
2597 */
2598CIccTagNamedColor2::CIccTagNamedColor2(const CIccTagNamedColor2 &ITNC)
2599{
2600 m_nColorEntrySize = ITNC.m_nColorEntrySize;
2601 m_nVendorFlags = ITNC.m_nVendorFlags;
2602 m_nDeviceCoords = ITNC.m_nDeviceCoords;
2603 m_nSize = ITNC.m_nSize;
2604
2605 m_csPCS = ITNC.m_csPCS;
2606 m_csDevice = ITNC.m_csDevice;
2607
2608 memcpy(m_szPrefix, ITNC.m_szPrefix, sizeof(m_szPrefix));
2609 memcpy(m_szSufix, ITNC.m_szSufix, sizeof(m_szSufix));
2610
2611 m_NamedColor = (SIccNamedColorEntry*)calloc(m_nSize, m_nColorEntrySize);
2612 memcpy(m_NamedColor, ITNC.m_NamedColor, m_nColorEntrySize*m_nSize);
2613
2614 m_NamedLab = NULL__null;
2615}
2616
2617
2618/**
2619 ****************************************************************************
2620 * Name: CIccTagNamedColor2::operator=
2621 *
2622 * Purpose: Copy Operator
2623 *
2624 * Args:
2625 * NamedColor2Tag = The CIccTagNamedColor2 object to be copied
2626 *****************************************************************************
2627 */
2628CIccTagNamedColor2 &CIccTagNamedColor2::operator=(const CIccTagNamedColor2 &NamedColor2Tag)
2629{
2630 if (&NamedColor2Tag == this)
2631 return *this;
2632
2633 m_nColorEntrySize = NamedColor2Tag.m_nColorEntrySize;
2634 m_nVendorFlags = NamedColor2Tag.m_nVendorFlags;
2635 m_nDeviceCoords = NamedColor2Tag.m_nDeviceCoords;
2636 m_nSize = NamedColor2Tag.m_nSize;
2637
2638 m_csPCS = NamedColor2Tag.m_csPCS;
2639 m_csDevice = NamedColor2Tag.m_csDevice;
2640
2641 memcpy(m_szPrefix, NamedColor2Tag.m_szPrefix, sizeof(m_szPrefix));
2642 memcpy(m_szSufix, NamedColor2Tag.m_szSufix, sizeof(m_szSufix));
2643
2644 if (m_NamedColor)
2645 free(m_NamedColor);
2646 m_NamedColor = (SIccNamedColorEntry*)calloc(m_nSize, m_nColorEntrySize);
2647 memcpy(m_NamedColor, NamedColor2Tag.m_NamedColor, m_nColorEntrySize*m_nSize);
2648
2649 m_NamedLab = NULL__null;
2650
2651 return *this;
2652}
2653
2654
2655/**
2656 ****************************************************************************
2657 * Name: CIccTagNamedColor2::~CIccTagNamedColor2
2658 *
2659 * Purpose: Destructor
2660 *
2661 *****************************************************************************
2662 */
2663CIccTagNamedColor2::~CIccTagNamedColor2()
2664{
2665 if (m_NamedColor)
2666 free(m_NamedColor);
2667
2668 if (m_NamedLab)
2669 delete [] m_NamedLab;
2670}
2671
2672/**
2673 ****************************************************************************
2674 * Name: CIccTagNamedColor2::SetSize
2675 *
2676 * Purpose: Sets the size of the named color array.
2677 *
2678 * Args:
2679 * nSize - number of named color entries,
2680 * nDeviceCoords - number of device channels
2681 *****************************************************************************
2682 */
2683bool CIccTagNamedColor2::SetSize(icUInt32Number nSize, icInt32Number nDeviceCoords/*=-1*/)
2684{
2685 if (nSize <1)
2686 nSize = 1;
2687 if (nDeviceCoords<0)
2688 nDeviceCoords = m_nDeviceCoords;
2689
2690 icInt32Number nNewCoords=nDeviceCoords;
2691
2692 if (nDeviceCoords>0)
2693 nDeviceCoords--;
2694
2695 icUInt32Number nColorEntrySize = 32/*rootName*/ + (3/*PCS*/ + 1/*iAny*/ + nDeviceCoords)*sizeof(icFloatNumber);
2696
2697 SIccNamedColorEntry* pNamedColor = (SIccNamedColorEntry*)calloc(nSize, nColorEntrySize);
2698
2699 if (!pNamedColor)
2700 return false;
2701
2702 icUInt32Number i, nCopy = __minmin(nSize, m_nSize);
2703 icUInt32Number j, nCoords = __minmin(nNewCoords, (icInt32Number)m_nDeviceCoords);
2704
2705 for (i=0; i<nCopy; i++) {
2706 SIccNamedColorEntry *pFrom = (SIccNamedColorEntry*)((icChar*)m_NamedColor + i*m_nColorEntrySize);
2707 SIccNamedColorEntry *pTo = (SIccNamedColorEntry*)((icChar*)pNamedColor + i*nColorEntrySize);
2708
2709 strcpy(pTo->rootName, pFrom->rootName);
2710 for (j=0; j<3; j++)
2711 pTo->pcsCoords[j] = pFrom->pcsCoords[j];
2712
2713 for (j=0; j<nCoords; j++) {
2714 pTo->deviceCoords[j] = pFrom->deviceCoords[j];
2715 }
2716 }
2717 free(m_NamedColor);
2718
2719 m_nColorEntrySize = nColorEntrySize;
2720
2721 m_NamedColor = pNamedColor;
2722 m_nSize = nSize;
2723 m_nDeviceCoords = nNewCoords;
2724
2725 ResetPCSCache();
2726
2727 return true;
2728}
2729
2730
2731/**
2732****************************************************************************
2733* Name: CIccTagNamedColor2::SetPrefix
2734*
2735* Purpose: Set contents of suffix member field
2736*
2737* Args:
2738* szPrefix - string to set prefix to
2739*****************************************************************************
2740*/
2741void CIccTagNamedColor2::SetPrefix(const icChar *szPrefix)
2742{
2743 strncpy(m_szPrefix, szPrefix, sizeof(m_szPrefix));
2744 m_szPrefix[sizeof(m_szPrefix)-1]='\0';
2745}
2746
2747
2748/**
2749****************************************************************************
2750* Name: CIccTagNamedColor2::SetSufix
2751*
2752* Purpose: Set contents of suffix member field
2753*
2754* Args:
2755* szPrefix - string to set prefix to
2756*****************************************************************************
2757*/
2758void CIccTagNamedColor2::SetSufix(const icChar *szSufix)
2759{
2760 strncpy(m_szSufix, szSufix, sizeof(m_szSufix));
2761 m_szSufix[sizeof(m_szSufix)-1]='\0';
2762}
2763
2764
2765/**
2766 ****************************************************************************
2767 * Name: CIccTagNamedColor2::Read
2768 *
2769 * Purpose: Read in the tag contents into a data block
2770 *
2771 * Args:
2772 * size - # of bytes in tag,
2773 * pIO - IO object to read tag from
2774 *
2775 * Return:
2776 * true = successful, false = failure
2777 *****************************************************************************
2778 */
2779bool CIccTagNamedColor2::Read(icUInt32Number size, CIccIO *pIO)
2780{
2781 icTagTypeSignature sig;
2782 icUInt32Number nNum, nCoords;
2783
2784 icUInt32Number nTagHdrSize = sizeof(icTagTypeSignature) +
2785 sizeof(icUInt32Number) + //m_nReserved=0
2786 sizeof(icUInt32Number) + //VendorFlags
2787 sizeof(icUInt32Number) + //Num Colors
2788 sizeof(icUInt32Number) + //Num Device Coords
2789 sizeof(m_szPrefix) +
2790 sizeof(m_szSufix);
2791 if (nTagHdrSize > size)
2792 return false;
2793
2794 if (!pIO) {
2795 return false;
2796 }
2797
2798 if (!pIO->Read32(&sig) ||
2799 !pIO->Read32(&m_nReserved) ||
2800 !pIO->Read32(&m_nVendorFlags) ||
2801 !pIO->Read32(&nNum) ||
2802 !pIO->Read32(&nCoords) ||
2803 pIO->Read8(m_szPrefix, sizeof(m_szPrefix))!=sizeof(m_szPrefix) ||
2804 pIO->Read8(m_szSufix, sizeof(m_szSufix))!=sizeof(m_szSufix)) {
2805 return false;
2806 }
2807
2808 size -= nTagHdrSize;
2809
2810 icUInt32Number nCount = size / (32+(3+nCoords)*sizeof(icUInt16Number));
2811
2812 if (nCount < nNum)
2813 return false;
2814
2815 if (!SetSize(nNum, nCoords))
2816 return false;
2817
2818 icUInt32Number i;
2819 SIccNamedColorEntry *pNamedColor=m_NamedColor;
2820
2821 for (i=0; i<nNum; i++) {
2822 if (pIO->Read8(&pNamedColor->rootName, sizeof(pNamedColor->rootName))!=sizeof(pNamedColor->rootName) ||
2823 pIO->ReadUInt16Float(&pNamedColor->pcsCoords, 3)!=3)
2824 return false;
2825 if (nCoords) {
2826 if (pIO->ReadUInt16Float(&pNamedColor->deviceCoords, nCoords)!=(icInt32Number)nCoords)
2827 return false;
2828 }
2829 pNamedColor = (SIccNamedColorEntry*)((icChar*)pNamedColor + m_nColorEntrySize);
2830 }
2831
2832 return true;
2833}
2834
2835
2836/**
2837 ****************************************************************************
2838 * Name: CIccTagNamedColor2::Write
2839 *
2840 * Purpose: Write the tag to a file
2841 *
2842 * Args:
2843 * pIO - The IO object to write tag to.
2844 *
2845 * Return:
2846 * true = succesful, false = failure
2847 *****************************************************************************
2848 */
2849bool CIccTagNamedColor2::Write(CIccIO *pIO)
2850{
2851 icTagTypeSignature sig = GetType();
2852
2853 if (!pIO)
2854 return false;
2855
2856 if (!pIO->Write32(&sig))
2857 return false;
2858
2859 if (!pIO->Write32(&m_nReserved))
2860 return false;
2861
2862 if (!pIO->Write32(&m_nVendorFlags))
2863 return false;
2864
2865 if (!pIO->Write32(&m_nSize))
2866 return false;
2867
2868 if (!pIO->Write32(&m_nDeviceCoords))
2869 return false;
2870
2871 if (!pIO->Write8(m_szPrefix, sizeof(m_szPrefix)))
2872 return false;
2873
2874 if (!pIO->Write8(m_szSufix, sizeof(m_szSufix)))
2875 return false;
2876
2877 icUInt32Number i;
2878 SIccNamedColorEntry *pNamedColor=m_NamedColor;
2879
2880 for (i=0; i<m_nSize; i++) {
2881 if (pIO->Write8(&pNamedColor->rootName, sizeof(pNamedColor->rootName))!=sizeof(pNamedColor->rootName) ||
2882 pIO->WriteUInt16Float(&pNamedColor->pcsCoords, 3)!=3)
2883 return false;
2884 if (m_nDeviceCoords) {
2885 if (pIO->WriteUInt16Float(&pNamedColor->deviceCoords, m_nDeviceCoords) != (icInt32Number)m_nDeviceCoords)
2886 return false;
2887 }
2888 pNamedColor = (SIccNamedColorEntry*)((icChar*)pNamedColor + m_nColorEntrySize);
2889 }
2890
2891 return true;
2892}
2893
2894
2895/**
2896 ****************************************************************************
2897 * Name: CIccTagNamedColor2::Describe
2898 *
2899 * Purpose: Dump data associated with the tag to a string
2900 *
2901 * Args:
2902 * sDescription - string to concatenate tag dump to
2903 *****************************************************************************
2904 */
2905void CIccTagNamedColor2::Describe(std::string &sDescription)
2906{
2907 icChar buf[128], szColorVal[40], szColor[40];
2908
2909 icUInt32Number i, j;
2910 SIccNamedColorEntry *pNamedColor=m_NamedColor;
2911
2912 sDescription.reserve(sDescription.size() + m_nSize*79);
2913
2914 sprintf(buf, "BEGIN_NAMED_COLORS flags=%08x %u %u\r\n", m_nVendorFlags, m_nSize, m_nDeviceCoords);
2915 sDescription += buf;
2916
2917 sprintf(buf, "Prefix=\"%s\"\r\n", m_szPrefix);
2918 sDescription += buf;
2919
2920 sprintf(buf, "Sufix= \"%s\"\r\n", m_szSufix);
2921 sDescription += buf;
2922
2923 for (i=0; i<m_nSize; i++) {
2924 sprintf(buf, "Color[%u]: %s :", i, pNamedColor->rootName);
2925 sDescription += buf;
2926
2927 icFloatNumber pcsCoord[3];
2928 for (j=0; j<3; j++)
2929 pcsCoord[j] = pNamedColor->pcsCoords[j];
2930
2931 if (m_csPCS==icSigLabData) {
2932 for (j=0; j<3; j++)
2933 pcsCoord[j] = (icFloatNumber)(pcsCoord[j] * 65535.0 / 65280.0);
2934 }
2935
2936 for (j=0; j<3; j++) {
2937 icColorIndexName(szColor, m_csPCS, j, 3, "P");
2938 icColorValue(szColorVal, pcsCoord[j], m_csPCS, j);
2939 sprintf(buf, " %s=%s", szColor, szColorVal);
2940 sDescription += buf;
2941 }
2942 if (m_nDeviceCoords) {
2943 sDescription += " :";
2944 for (j=0; j<m_nDeviceCoords; j++) {
2945 icColorIndexName(szColor, m_csDevice, j, m_nDeviceCoords, "D");
2946 icColorValue(szColorVal, pNamedColor->deviceCoords[j], m_csDevice, j);
2947 sprintf(buf, " %s=%s", szColor, szColorVal);
2948 sDescription += buf;
2949 }
2950 }
2951 sDescription += "\r\n";
2952
2953 pNamedColor = (SIccNamedColorEntry*)((icChar*)pNamedColor + m_nColorEntrySize);
2954 }
2955}
2956
2957/**
2958 ****************************************************************************
2959 * Name: CIccTagNamedColor2::SetColorSpaces
2960 *
2961 * Purpose: Set the device and PCS color space of the tag
2962 *
2963 * Args:
2964 * csPCS = PCS color space signature,
2965 * csDevice = Device color space signature
2966 *
2967 *****************************************************************************
2968 */
2969void CIccTagNamedColor2::SetColorSpaces(icColorSpaceSignature csPCS, icColorSpaceSignature csDevice)
2970{
2971 m_csPCS = csPCS;
2972 m_csDevice = csDevice;
2973}
2974
2975/**
2976 ****************************************************************************
2977 * Name: CIccTagNamedColor2::FindRootColor
2978 *
2979 * Purpose: Find the root color name
2980 *
2981 * Args:
2982 * szRootColor = string containing the root color name to be found
2983 *
2984 * Return: Index of the named color array where the root color name was found,
2985 * if the color was not found -1 is returned
2986 *****************************************************************************
2987 */
2988icInt32Number CIccTagNamedColor2::FindRootColor(const icChar *szRootColor) const
2989{
2990 for (icUInt32Number i=0; i<m_nSize; i++) {
2991 if (stricmpstrcasecmp(m_NamedColor[i].rootName,szRootColor) == 0)
2992 return i;
2993 }
2994
2995 return -1;
2996}
2997
2998/**
2999 ****************************************************************************
3000 * Name: CIccTagNamedColor2::ResetPCSCache
3001 *
3002 * Purpose: This function is called if entry values change between calls
3003 * to FindPCSColor()
3004 *
3005 *****************************************************************************
3006 */
3007void CIccTagNamedColor2::ResetPCSCache()
3008{
3009 if (m_NamedLab) {
3010 delete [] m_NamedLab;
3011 m_NamedLab = NULL__null;
3012 }
3013}
3014
3015/**
3016****************************************************************************
3017* Name: CIccTagNamedColor2::InitFindPCSColor
3018*
3019* Purpose: Initialization needed for using FindPCSColor
3020*
3021* Return:
3022* true if successfull, false if failure
3023*****************************************************************************
3024*/
3025bool CIccTagNamedColor2::InitFindCachedPCSColor()
3026{
3027 icFloatNumber *pXYZ, *pLab;
3028
3029 if (!m_NamedLab) {
3030 m_NamedLab = new SIccNamedLabEntry[m_nSize];
3031 if (!m_NamedLab)
3032 return false;
3033
3034 if (m_csPCS != icSigLabData) {
3035 for (icUInt32Number i=0; i<m_nSize; i++) {
3036 pLab = m_NamedLab[i].lab;
3037 pXYZ = m_NamedColor[i].pcsCoords;
3038 icXyzFromPcs(pXYZ);
3039 icXYZtoLab(pLab, pXYZ);
3040 }
3041 }
3042 else {
3043 for (icUInt32Number i=0; i<m_nSize; i++) {
3044 pLab = m_NamedLab[i].lab;
3045 Lab2ToLab4(pLab, m_NamedColor[i].pcsCoords);
3046 icLabFromPcs(pLab);
3047 }
3048 }
3049 }
3050
3051 return true;
3052}
3053
3054/**
3055 ****************************************************************************
3056 * Name: CIccTagNamedColor2::FindPCSColor
3057 *
3058 * Purpose: Find the PCS color within the specified deltaE
3059 *
3060 * Args:
3061 * pPCS = PCS co-ordinates,
3062 * dMinDE = the minimum deltaE (tolerance)
3063 *
3064 * Return: Index of the named color array where the PCS color was found,
3065 * if the color was not found within the tolerance -1 is returned
3066 *****************************************************************************
3067 */
3068icInt32Number CIccTagNamedColor2::FindCachedPCSColor(icFloatNumber *pPCS, icFloatNumber dMinDE/*=1000.0*/) const
3069{
3070 icFloatNumber dCalcDE, dLeastDE=0.0;
3071 icFloatNumber pLabIn[3];
3072 icFloatNumber *pXYZ, *pLab;
3073 icInt32Number leastDEindex = -1;
3074 if (m_csPCS != icSigLabData) {
3075 pXYZ = pPCS;
3076 icXyzFromPcs(pXYZ);
3077 icXYZtoLab(pLabIn,pXYZ);
3078 }
3079 else {
3080 Lab2ToLab4(pLabIn, pPCS);
3081 icLabFromPcs(pLabIn);
3082 }
3083
3084 if (!m_NamedLab)
3085 return -1;
3086
3087 for (icUInt32Number i=0; i<m_nSize; i++) {
3088 pLab = m_NamedLab[i].lab;
3089
3090 dCalcDE = icDeltaE(pLabIn, pLab);
3091
3092 if (i==0) {
3093 dLeastDE = dCalcDE;
3094 leastDEindex = i;
3095 }
3096
3097 if (dCalcDE<dMinDE) {
3098 if (dCalcDE<dLeastDE) {
3099 dLeastDE = dCalcDE;
3100 leastDEindex = i;
3101 }
3102 }
3103 }
3104
3105 return leastDEindex;
3106}
3107
3108/**
3109****************************************************************************
3110* Name: CIccTagNamedColor2::FindPCSColor
3111*
3112* Purpose: Find the PCS color within the specified deltaE
3113*
3114* Args:
3115* pPCS = PCS co-ordinates,
3116* dMinDE = the minimum deltaE (tolerance)
3117*
3118* Return: Index of the named color array where the PCS color was found,
3119* if the color was not found within the tolerance -1 is returned
3120*****************************************************************************
3121*/
3122icInt32Number CIccTagNamedColor2::FindPCSColor(icFloatNumber *pPCS, icFloatNumber dMinDE/*=1000.0*/)
3123{
3124 if (!m_NamedLab)
3125 InitFindCachedPCSColor();
3126
3127 return FindCachedPCSColor(pPCS, dMinDE);
3128}
3129
3130/**
3131 ****************************************************************************
3132 * Name: CIccTagNamedColor2::FindColor
3133 *
3134 * Purpose: Find the color with given name
3135 *
3136 * Args:
3137 * szColor = the color name
3138 *
3139 * Return: Index of the named color array where the color name was found,
3140 * if the color was not found -1 is returned
3141 *****************************************************************************
3142 */
3143icInt32Number CIccTagNamedColor2::FindColor(const icChar *szColor) const
3144{
3145 std::string sColorName;
3146 icInt32Number i, j;
3147
3148 j = (icInt32Number)strlen(m_szPrefix);
3149 if (j != 0) {
3150 if (strncmp(szColor, m_szPrefix, j))
3151 return -1;
3152 }
3153
3154 j = (icInt32Number)strlen(m_szSufix);
3155 i = (icInt32Number)strlen(szColor);
3156 if (j != 0) {
3157 if (strncmp(szColor+(i-j), m_szSufix, j))
3158 return -1;
3159 }
3160
3161
3162 for ( i=0; i<(icInt32Number)m_nSize; i++) {
3163 sColorName = m_szPrefix;
3164 sColorName += m_NamedColor[i].rootName;
3165 sColorName += m_szSufix;
3166
3167 if (strcmp(sColorName.c_str(),szColor) == 0)
3168 return i;
3169 }
3170
3171 return -1;
3172}
3173
3174/**
3175 ****************************************************************************
3176 * Name: CIccTagNamedColor2::FindDeviceColor
3177 *
3178 * Purpose: Find the device color
3179 *
3180 * Args:
3181 * pDevColor = device color co-ordinates
3182 *
3183 * Return: Index of the named color array where the closest device color
3184 * was found, if device representation is absent -1 is returned.
3185 *****************************************************************************
3186 */
3187icInt32Number CIccTagNamedColor2::FindDeviceColor(icFloatNumber *pDevColor) const
3188{
3189 if (!m_nDeviceCoords)
3190 return -1;
3191
3192 icFloatNumber dCalcDiff=0.0, dLeastDiff=0.0;
3193 icFloatNumber *pDevOut;
3194 icInt32Number leastDiffindex = -1;
3195
3196
3197 for (icUInt32Number i=0; i<m_nSize; i++) {
3198 pDevOut = m_NamedColor[i].deviceCoords;
3199
3200 for (icUInt32Number j=0; j<m_nDeviceCoords; j++) {
3201 dCalcDiff += (pDevColor[j]-pDevOut[j])*(pDevColor[j]-pDevOut[j]);
3202 }
3203 dCalcDiff = (icFloatNumber)sqrt(dCalcDiff);
3204
3205 if (i==0) {
3206 dLeastDiff = dCalcDiff;
3207 leastDiffindex = i;
3208 }
3209
3210 if (dCalcDiff<dLeastDiff) {
3211 dLeastDiff = dCalcDiff;
3212 leastDiffindex = i;
3213 }
3214
3215 dCalcDiff = 0.0;
3216 }
3217
3218 return leastDiffindex;
3219}
3220
3221/**
3222 ****************************************************************************
3223 * Name: CIccTagNamedColor2::GetColorName
3224 *
3225 * Purpose: Extracts the color name from the named color array
3226 *
3227 * Args:
3228 * sColorName = string where color name will be stored,
3229 * index = array index of the color name
3230 *
3231 * Return:
3232 * true = if the index is within range,
3233 * false = index out of range
3234 *****************************************************************************
3235 */
3236bool CIccTagNamedColor2::GetColorName(std::string &sColorName, icInt32Number index) const
3237{
3238 if (index > (icInt32Number)m_nSize-1)
3239 return false;
3240
3241 sColorName += m_szPrefix;
3242 SIccNamedColorEntry * pNamedColor = (SIccNamedColorEntry*)((icChar*)m_NamedColor + m_nColorEntrySize * index);
3243 sColorName += pNamedColor->rootName;
3244 sColorName += m_szSufix;
3245
3246 return true;
3247}
3248
3249/**
3250 ****************************************************************************
3251 * Name: CIccTagNamedColor2::UnitClip
3252 *
3253 * Purpose: Clip number so that its between 0-1
3254 *
3255 * Args:
3256 * v = number to be clipped
3257 *
3258 * Return: Clipped number
3259 *
3260 *****************************************************************************
3261 */
3262icFloatNumber CIccTagNamedColor2::UnitClip(icFloatNumber v) const
3263{
3264 if (v<0)
3265 v = 0;
3266 if (v>1.0)
3267 v = 1.0;
3268
3269 return v;
3270}
3271
3272/**
3273 ****************************************************************************
3274 * Name: CIccTagNamedColor2::NegClip
3275 *
3276 * Purpose: Negative numbers are clipped to zero
3277 *
3278 * Args:
3279 * v = number to be clipped
3280 *
3281 * Return: Clipped number
3282 *
3283 *****************************************************************************
3284 */
3285icFloatNumber CIccTagNamedColor2::NegClip(icFloatNumber v) const
3286{
3287 if (v<0)
3288 v=0;
3289
3290 return v;
3291}
3292
3293
3294/**
3295 ****************************************************************************
3296 * Name: CIccTagNamedColor2::Lab2ToLab4
3297 *
3298 * Purpose: Convert version 2 Lab to version 4 Lab
3299 *
3300 * Args:
3301 * Dst = array to store version 4 Lab coordinates,
3302 * Src = array containing version 2 Lab coordinates
3303 *
3304 *****************************************************************************
3305 */
3306void CIccTagNamedColor2::Lab2ToLab4(icFloatNumber *Dst, const icFloatNumber *Src) const
3307{
3308 Dst[0] = UnitClip((icFloatNumber)(Src[0] * 65535.0 / 65280.0));
3309 Dst[1] = UnitClip((icFloatNumber)(Src[1] * 65535.0 / 65280.0));
3310 Dst[2] = UnitClip((icFloatNumber)(Src[2] * 65535.0 / 65280.0));
3311}
3312
3313/**
3314 ****************************************************************************
3315 * Name: CIccTagNamedColor2::Lab4ToLab2
3316 *
3317 * Purpose: Convert version 4 Lab to version 2 Lab
3318 *
3319 * Args:
3320 * Dst = array to store version 2 Lab coordinates,
3321 * Src = array containing version 4 Lab coordinates
3322 *
3323 *****************************************************************************
3324 */
3325void CIccTagNamedColor2::Lab4ToLab2(icFloatNumber *Dst, const icFloatNumber *Src) const
3326{
3327 Dst[0] = (icFloatNumber)(Src[0] * 65280.0 / 65535.0);
3328 Dst[1] = (icFloatNumber)(Src[1] * 65280.0 / 65535.0);
3329 Dst[2] = (icFloatNumber)(Src[2] * 65280.0 / 65535.0);
3330}
3331
3332
3333/**
3334******************************************************************************
3335* Name: CIccTagNamedColor2::Validate
3336*
3337* Purpose: Check tag data validity.
3338*
3339* Args:
3340* sig = signature of tag being validated,
3341* sReport = String to add report information to
3342*
3343* Return:
3344* icValidateStatusOK if valid, or other error status.
3345******************************************************************************
3346*/
3347icValidateStatus CIccTagNamedColor2::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
3348{
3349 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
3350
3351 CIccInfo Info;
3352 std::string sSigPathName = Info.GetSigPathName(sigPath);
3353
3354 if (!m_nSize) {
3355 sReport += icMsgValidateWarning;
3356 sReport += sSigPathName;
3357 sReport += " - Empty tag!\r\n";
3358 rv = icMaxStatus(rv, icValidateWarning);
3359 }
3360
3361 if (m_nDeviceCoords) {
3362 if (pProfile) {
3363 icUInt32Number nCoords = icGetSpaceSamples(pProfile->m_Header.colorSpace);
3364 if (m_nDeviceCoords != nCoords) {
3365 sReport += icMsgValidateNonCompliant;
3366 sReport += sSigPathName;
3367 sReport += " - Incorrect number of device co-ordinates.\r\n";
3368 rv = icMaxStatus(rv, icValidateNonCompliant);
3369 }
3370 }
3371 else {
3372 sReport += icMsgValidateWarning;
3373 sReport += sSigPathName;
3374 sReport += " - Tag validation incomplete: Pointer to profile unavailable.\r\n";
3375 rv = icMaxStatus(rv, icValidateWarning);
3376 }
3377 }
3378
3379
3380 return rv;
3381}
3382
3383
3384/**
3385 ****************************************************************************
3386 * Name: CIccTagXYZ::CIccTagXYZ
3387 *
3388 * Purpose: Constructor
3389 *
3390 * Args:
3391 * nSize = number of XYZ entries
3392 *
3393 *****************************************************************************
3394 */
3395CIccTagXYZ::CIccTagXYZ(int nSize/*=1*/)
3396{
3397 m_nSize = nSize;
3398 if (m_nSize <1)
3399 m_nSize = 1;
3400 m_XYZ = (icXYZNumber*)calloc(nSize, sizeof(icXYZNumber));
3401}
3402
3403
3404/**
3405 ****************************************************************************
3406 * Name: CIccTagXYZ::CIccTagXYZ
3407 *
3408 * Purpose: Copy Constructor
3409 *
3410 * Args:
3411 * ITXYZ = The CIccTagXYZ object to be copied
3412 *****************************************************************************
3413 */
3414CIccTagXYZ::CIccTagXYZ(const CIccTagXYZ &ITXYZ)
3415{
3416 m_nSize = ITXYZ.m_nSize;
3417
3418 m_XYZ = (icXYZNumber*)calloc(m_nSize, sizeof(icXYZNumber));
3419 memcpy(m_XYZ, ITXYZ.m_XYZ, sizeof(icXYZNumber)*m_nSize);
3420}
3421
3422
3423
3424/**
3425 ****************************************************************************
3426 * Name: CIccTagXYZ::operator=
3427 *
3428 * Purpose: Copy Operator
3429 *
3430 * Args:
3431 * XYZTag = The CIccTagXYZ object to be copied
3432 *****************************************************************************
3433 */
3434CIccTagXYZ &CIccTagXYZ::operator=(const CIccTagXYZ &XYZTag)
3435{
3436 if (&XYZTag == this)
3437 return *this;
3438
3439 m_nSize = XYZTag.m_nSize;
3440
3441 if (m_XYZ)
3442 free(m_XYZ);
3443 m_XYZ = (icXYZNumber*)calloc(m_nSize, sizeof(icXYZNumber));
3444 memcpy(m_XYZ, XYZTag.m_XYZ, sizeof(icXYZNumber)*m_nSize);
3445
3446 return *this;
3447}
3448
3449
3450/**
3451 ****************************************************************************
3452 * Name: CIccTagXYZ::~CIccTagXYZ
3453 *
3454 * Purpose: Destructor
3455 *
3456 *****************************************************************************
3457 */
3458CIccTagXYZ::~CIccTagXYZ()
3459{
3460 if (m_XYZ)
3461 free(m_XYZ);
3462}
3463
3464
3465/**
3466 ****************************************************************************
3467 * Name: CIccTagXYZ::Read
3468 *
3469 * Purpose: Read in the tag contents into a data block
3470 *
3471 * Args:
3472 * size - # of bytes in tag,
3473 * pIO - IO object to read tag from
3474 *
3475 * Return:
3476 * true = successful, false = failure
3477 *****************************************************************************
3478 */
3479bool CIccTagXYZ::Read(icUInt32Number size, CIccIO *pIO)
3480{
3481 icTagTypeSignature sig;
3482
3483 if (sizeof(icTagTypeSignature) +
3484 sizeof(icUInt32Number) +
3485 sizeof(icXYZNumber) > size)
3486 return false;
3487
3488 if (!pIO) {
3489 return false;
3490 }
3491
3492 if (!pIO->Read32(&sig))
3493 return false;
3494
3495 if (!pIO->Read32(&m_nReserved))
3496 return false;
3497
3498 icUInt32Number nNum=((size-2*sizeof(icUInt32Number)) / sizeof(icXYZNumber));
3499 icUInt32Number nNum32 = nNum*sizeof(icXYZNumber)/sizeof(icUInt32Number);
3500
3501 if (!SetSize(nNum))
3502 return false;
3503
3504 if (pIO->Read32(m_XYZ, nNum32) != (icInt32Number)nNum32 )
3505 return false;
3506
3507 return true;
3508}
3509
3510
3511/**
3512 ****************************************************************************
3513 * Name: CIccTagXYZ::Write
3514 *
3515 * Purpose: Write the tag to a file
3516 *
3517 * Args:
3518 * pIO - The IO object to write tag to.
3519 *
3520 * Return:
3521 * true = succesful, false = failure
3522 *****************************************************************************
3523 */
3524bool CIccTagXYZ::Write(CIccIO *pIO)
3525{
3526 icTagTypeSignature sig = GetType();
3527
3528 if (!pIO)
3529 return false;
3530
3531 if (!pIO->Write32(&sig))
3532 return false;
3533
3534 if (!pIO->Write32(&m_nReserved))
3535 return false;
3536
3537 icUInt32Number nNum32 = m_nSize * sizeof(icXYZNumber)/sizeof(icUInt32Number);
3538
3539 if (
3540 pIO->Write32(m_XYZ, nNum32) != (icInt32Number)nNum32)
3541 return false;
3542
3543 return true;
3544}
3545
3546
3547/**
3548 ****************************************************************************
3549 * Name: CIccTagXYZ::Describe
3550 *
3551 * Purpose: Dump data associated with the tag to a string
3552 *
3553 * Args:
3554 * sDescription - string to concatenate tag dump to
3555 *****************************************************************************
3556 */
3557void CIccTagXYZ::Describe(std::string &sDescription)
3558{
3559 icChar buf[128];
3560
3561 if (m_nSize == 1 ) {
3562 sprintf(buf, "X=%.4lf, Y=%.4lf, Z=%.4lf\r\n", icFtoD(m_XYZ[0].X), icFtoD(m_XYZ[0].Y), icFtoD(m_XYZ[0].Z));
3563 sDescription += buf;
3564 }
3565 else {
3566 icUInt32Number i;
3567 sDescription.reserve(sDescription.size() + m_nSize*79);
3568
3569 for (i=0; i<m_nSize; i++) {
3570 sprintf(buf, "value[%u]: X=%.4lf, Y=%.4lf, Z=%.4lf\r\n", i, icFtoD(m_XYZ[i].X), icFtoD(m_XYZ[i].Y), icFtoD(m_XYZ[i].Z));
3571 sDescription += buf;
3572 }
3573 }
3574}
3575
3576/**
3577 ****************************************************************************
3578 * Name: CIccTagXYZ::SetSize
3579 *
3580 * Purpose: Sets the size of the XYZ array.
3581 *
3582 * Args:
3583 * nSize - number of XYZ entries,
3584 * bZeroNew - flag to zero newly formed values
3585 *****************************************************************************
3586 */
3587bool CIccTagXYZ::SetSize(icUInt32Number nSize, bool bZeroNew/*=true*/)
3588{
3589 if (nSize==m_nSize)
3590 return true;
3591
3592 m_XYZ = (icXYZNumber*)icRealloc(m_XYZ, nSize*sizeof(icXYZNumber));
3593
3594 if (!m_XYZ) {
3595 m_nSize = 0;
3596 return false;
3597 }
3598
3599 if (bZeroNew && m_nSize < nSize) {
3600 memset(&m_XYZ[m_nSize], 0, (nSize-m_nSize)*sizeof(icXYZNumber));
3601 }
3602 m_nSize = nSize;
3603
3604 return true;
3605}
3606
3607
3608/**
3609******************************************************************************
3610* Name: CIccTagXYZ::Validate
3611*
3612* Purpose: Check tag data validity.
3613*
3614* Args:
3615* sig = signature of tag being validated,
3616* sReport = String to add report information to
3617*
3618* Return:
3619* icValidateStatusOK if valid, or other error status.
3620******************************************************************************
3621*/
3622icValidateStatus CIccTagXYZ::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
3623{
3624 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
3625
3626 CIccInfo Info;
3627 std::string sSigPathName = Info.GetSigPathName(sigPath);
3628
3629 if (!m_nSize) {
3630 sReport += icMsgValidateWarning;
3631 sReport += sSigPathName;
3632 sReport += " - Empty tag.\r\n";
3633
3634 rv = icMaxStatus(rv, icValidateWarning);
3635 return rv;
3636 }
3637
3638 for (int i=0; i<(int)m_nSize; i++) {
3639 rv = icMaxStatus(rv, Info.CheckData(sReport, m_XYZ[i], sSigPathName + ":XYZ"));
3640 }
3641
3642 return rv;
3643}
3644
3645
3646/**
3647 ****************************************************************************
3648 * Name: CIccTagChromaticity::CIccTagChromaticity
3649 *
3650 * Purpose: Constructor
3651 *
3652 * Args:
3653 * nSize = number of xy entries
3654 *
3655 *****************************************************************************
3656 */
3657CIccTagChromaticity::CIccTagChromaticity(int nSize/*=3*/)
3658{
3659 m_nChannels = nSize;
3660 if (m_nChannels <3)
3661 m_nChannels = 3;
3662 m_xy = (icChromaticityNumber*)calloc(nSize, sizeof(icChromaticityNumber));
3663}
3664
3665
3666/**
3667 ****************************************************************************
3668 * Name: CIccTagChromaticity::CIccTagChromaticity
3669 *
3670 * Purpose: Copy Constructor
3671 *
3672 * Args:
3673 * ITCh = The CIccTagChromaticity object to be copied
3674 *****************************************************************************
3675 */
3676CIccTagChromaticity::CIccTagChromaticity(const CIccTagChromaticity &ITCh)
3677{
3678 m_nChannels = ITCh.m_nChannels;
3679
3680 m_xy = (icChromaticityNumber*)calloc(m_nChannels, sizeof(icChromaticityNumber));
3681 memcpy(m_xy, ITCh.m_xy, sizeof(icChromaticityNumber)*m_nChannels);
3682}
3683
3684
3685/**
3686 ****************************************************************************
3687 * Name: CIccTagChromaticity::operator=
3688 *
3689 * Purpose: Copy Operator
3690 *
3691 * Args:
3692 * ChromTag = The CIccTagChromaticity object to be copied
3693 *****************************************************************************
3694 */
3695CIccTagChromaticity &CIccTagChromaticity::operator=(const CIccTagChromaticity &ChromTag)
3696{
3697 if (&ChromTag == this)
3698 return *this;
3699
3700 m_nChannels = ChromTag.m_nChannels;
3701
3702 if (m_xy)
3703 free(m_xy);
3704 m_xy = (icChromaticityNumber*)calloc(m_nChannels, sizeof(icChromaticityNumber));
3705 memcpy(m_xy, ChromTag.m_xy, sizeof(icChromaticityNumber)*m_nChannels);
3706
3707 return *this;
3708}
3709
3710
3711/**
3712 ****************************************************************************
3713 * Name: CIccTagChromaticity::~CIccTagChromaticity
3714 *
3715 * Purpose: Destructor
3716 *
3717 *****************************************************************************
3718 */
3719CIccTagChromaticity::~CIccTagChromaticity()
3720{
3721 if (m_xy)
3722 free(m_xy);
3723}
3724
3725
3726/**
3727 ****************************************************************************
3728 * Name: CIccTagChromaticity::Read
3729 *
3730 * Purpose: Read in the tag contents into a data block
3731 *
3732 * Args:
3733 * size - # of bytes in tag,
3734 * pIO - IO object to read tag from
3735 *
3736 * Return:
3737 * true = successful, false = failure
3738 *****************************************************************************
3739 */
3740bool CIccTagChromaticity::Read(icUInt32Number size, CIccIO *pIO)
3741{
3742 icTagTypeSignature sig;
3743 icUInt16Number nChannels;
3744
3745 if (sizeof(icTagTypeSignature) +
3746 sizeof(icUInt32Number) +
3747 sizeof(icUInt32Number) +
3748 sizeof(icChromaticityNumber) > size)
3749 return false;
3750
3751 if (!pIO) {
3752 return false;
3753 }
3754
3755 if (!pIO->Read32(&sig))
3756 return false;
3757
3758 if (!pIO->Read32(&m_nReserved))
3759 return false;
3760
3761 if (!pIO->Read16(&nChannels) ||
3762 !pIO->Read16(&m_nColorantType))
3763 return false;
3764
3765 icUInt32Number nNum = (size-3*sizeof(icUInt32Number)) / sizeof(icChromaticityNumber);
3766 icUInt32Number nNum32 = nNum*sizeof(icChromaticityNumber)/sizeof(icU16Fixed16Number);
3767
3768 if (nNum < nChannels)
3769 return false;
3770
3771 if (!SetSize((icUInt16Number)nNum))
3772 return false;
3773
3774 if (pIO->Read32(&m_xy[0], nNum32) != (icInt32Number)nNum32 )
3775 return false;
3776
3777 return true;
3778}
3779
3780
3781/**
3782 ****************************************************************************
3783 * Name: CIccTagChromaticity::Write
3784 *
3785 * Purpose: Write the tag to a file
3786 *
3787 * Args:
3788 * pIO - The IO object to write tag to.
3789 *
3790 * Return:
3791 * true = succesful, false = failure
3792 *****************************************************************************
3793 */
3794bool CIccTagChromaticity::Write(CIccIO *pIO)
3795{
3796 icTagTypeSignature sig = GetType();
3797
3798 if (!pIO)
3799 return false;
3800
3801 if (!pIO->Write32(&sig))
3802 return false;
3803
3804 if (!pIO->Write32(&m_nReserved))
3805 return false;
3806
3807 if (!pIO->Write16(&m_nChannels))
3808 return false;
3809
3810 if (!pIO->Write16(&m_nColorantType))
3811 return false;
3812
3813 icUInt32Number nNum32 = m_nChannels*sizeof(icChromaticityNumber)/sizeof(icU16Fixed16Number);
3814
3815 if (pIO->Write32(&m_xy[0], nNum32) != (icInt32Number)nNum32)
3816 return false;
3817
3818 return true;
3819}
3820
3821
3822/**
3823 ****************************************************************************
3824 * Name: CIccTagChromaticity::Describe
3825 *
3826 * Purpose: Dump data associated with the tag to a string
3827 *
3828 * Args:
3829 * sDescription - string to concatenate tag dump to
3830 *****************************************************************************
3831 */
3832void CIccTagChromaticity::Describe(std::string &sDescription)
3833{
3834 icChar buf[128];
3835 CIccInfo Fmt;
3836
3837 icUInt32Number i;
3838 //sDescription.reserve(sDescription.size() + m_nChannels*79);
3839 sprintf(buf, "Number of Channels : %u\r\n", m_nChannels);
3840 sDescription += buf;
3841
3842 sprintf(buf, "Colorant Encoding : %s\r\n", Fmt.GetColorantEncoding((icColorantEncoding)m_nColorantType));
3843 sDescription += buf;
3844
3845 for (i=0; i<m_nChannels; i++) {
3846 sprintf(buf, "value[%u]: x=%.3lf, y=%.3lf\r\n", i, icUFtoD(m_xy[i].x), icUFtoD(m_xy[i].y));
3847 sDescription += buf;
3848 }
3849
3850}
3851
3852/**
3853 ****************************************************************************
3854 * Name: CIccTagChromaticity::SetSize
3855 *
3856 * Purpose: Sets the size of the xy chromaticity array.
3857 *
3858 * Args:
3859 * nSize - number of xy entries,
3860 * bZeroNew - flag to zero newly formed values
3861 *****************************************************************************
3862 */
3863bool CIccTagChromaticity::SetSize(icUInt16Number nSize, bool bZeroNew/*=true*/)
3864{
3865 if (m_nChannels == nSize)
3866 return true;
3867
3868 m_xy = (icChromaticityNumber*)icRealloc(m_xy, nSize*sizeof(icChromaticityNumber));
3869
3870 if (!m_xy) {
3871 m_nChannels = 0;
3872 return false;
3873 }
3874
3875 if (bZeroNew && nSize > m_nChannels) {
3876 memset(&m_xy[m_nChannels], 0, (nSize - m_nChannels)*sizeof(icChromaticityNumber));
3877 }
3878
3879 m_nChannels = nSize;
3880 return true;
3881}
3882
3883
3884/**
3885******************************************************************************
3886* Name: CIccTagChromaticity::Validate
3887*
3888* Purpose: Check tag data validity.
3889*
3890* Args:
3891* sig = signature of tag being validated,
3892* sReport = String to add report information to
3893*
3894* Return:
3895* icValidateStatusOK if valid, or other error status.
3896******************************************************************************
3897*/
3898icValidateStatus CIccTagChromaticity::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
3899{
3900 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
3901
3902 CIccInfo Info;
3903 std::string sSigPathName = Info.GetSigPathName(sigPath);
3904
3905 if (m_nColorantType) {
3906
3907 if (m_nChannels!=3) {
3908 sReport += icMsgValidateCriticalError;
3909 sReport += sSigPathName;
3910 sReport += " - Number of device channels must be three.\r\n";
3911 rv = icMaxStatus(rv, icValidateCriticalError);
3912 }
3913
3914 switch(m_nColorantType) {
3915 case icColorantITU:
3916 {
3917 if ( (m_xy[0].x != icDtoUF((icFloatNumber)0.640)) || (m_xy[0].y != icDtoUF((icFloatNumber)0.330)) ||
3918 (m_xy[1].x != icDtoUF((icFloatNumber)0.300)) || (m_xy[1].y != icDtoUF((icFloatNumber)0.600)) ||
3919 (m_xy[2].x != icDtoUF((icFloatNumber)0.150)) || (m_xy[2].y != icDtoUF((icFloatNumber)0.060)) ) {
3920 sReport += icMsgValidateNonCompliant;
3921 sReport += sSigPathName;
3922 sReport += " - Chromaticity data does not match specification.\r\n";
3923 rv = icMaxStatus(rv, icValidateNonCompliant);
3924 }
3925 break;
3926 }
3927
3928 case icColorantSMPTE:
3929 {
3930 if ( (m_xy[0].x != icDtoUF((icFloatNumber)0.630)) || (m_xy[0].y != icDtoUF((icFloatNumber)0.340)) ||
3931 (m_xy[1].x != icDtoUF((icFloatNumber)0.310)) || (m_xy[1].y != icDtoUF((icFloatNumber)0.595)) ||
3932 (m_xy[2].x != icDtoUF((icFloatNumber)0.155)) || (m_xy[2].y != icDtoUF((icFloatNumber)0.070)) ) {
3933 sReport += icMsgValidateNonCompliant;
3934 sReport += sSigPathName;
3935 sReport += " - Chromaticity data does not match specification.\r\n";
3936 rv = icMaxStatus(rv, icValidateNonCompliant);
3937 }
3938 break;
3939 }
3940
3941 case icColorantEBU:
3942 {
3943 if ( (m_xy[0].x != icDtoUF((icFloatNumber)0.64)) || (m_xy[0].y != icDtoUF((icFloatNumber)0.33)) ||
3944 (m_xy[1].x != icDtoUF((icFloatNumber)0.29)) || (m_xy[1].y != icDtoUF((icFloatNumber)0.60)) ||
3945 (m_xy[2].x != icDtoUF((icFloatNumber)0.15)) || (m_xy[2].y != icDtoUF((icFloatNumber)0.06)) ) {
3946 sReport += icMsgValidateNonCompliant;
3947 sReport += sSigPathName;
3948 sReport += " - Chromaticity data does not match specification.\r\n";
3949 rv = icMaxStatus(rv, icValidateNonCompliant);
3950 }
3951 break;
3952 }
3953
3954 case icColorantP22:
3955 {
3956 if ( (m_xy[0].x != icDtoUF((icFloatNumber)0.625)) || (m_xy[0].y != icDtoUF((icFloatNumber)0.340)) ||
3957 (m_xy[1].x != icDtoUF((icFloatNumber)0.280)) || (m_xy[1].y != icDtoUF((icFloatNumber)0.605)) ||
3958 (m_xy[2].x != icDtoUF((icFloatNumber)0.155)) || (m_xy[2].y != icDtoUF((icFloatNumber)0.070)) ) {
3959 sReport += icMsgValidateNonCompliant;
3960 sReport += sSigPathName;
3961 sReport += " - Chromaticity data does not match specification.\r\n";
3962 rv = icMaxStatus(rv, icValidateNonCompliant);
3963 }
3964 break;
3965 }
3966
3967 default:
3968 {
3969 sReport += icMsgValidateNonCompliant;
3970 sReport += sSigPathName;
3971 sReport += " - Invalid colorant type encoding.\r\n";
3972 rv = icMaxStatus(rv, icValidateNonCompliant);
3973 }
3974 }
3975 }
3976
3977 return rv;
3978}
3979
3980
3981/**
3982 ****************************************************************************
3983 * Name: CIccTagSparseMatrixArray::CIccTagSparseMatrixArray
3984 *
3985 * Purpose: CIccTagSparseMatrixArray Constructor
3986 *
3987 * Args:
3988 * nSize = number of data entries
3989 *
3990 *****************************************************************************
3991 */
3992CIccTagSparseMatrixArray::CIccTagSparseMatrixArray(int nNumMatrices/* =1 */, int nChannelsPerMatrix/* =4 */)
3993{
3994 m_nSize = nNumMatrices;
3995 m_nChannelsPerMatrix = nChannelsPerMatrix;
3996 m_nMatrixType = icSparseMatrixFloat32;
3997
3998 if (m_nSize <1)
3999 m_nSize = 1;
4000 if (nChannelsPerMatrix<4)
4001 m_nChannelsPerMatrix = 4;
4002
4003 m_RawData = (icUInt8Number*)calloc(m_nSize, GetBytesPerMatrix());
4004
4005 m_bNonZeroPadding = false;
4006}
4007
4008
4009/**
4010 ****************************************************************************
4011 * Name: CIccTagSparseMatrixArray::CIccTagSparseMatrixArray
4012 *
4013 * Purpose: Copy Constructor
4014 *
4015 * Args:
4016 * ITFN = The CIccTagFixedNum object to be copied
4017 *****************************************************************************
4018 */
4019CIccTagSparseMatrixArray::CIccTagSparseMatrixArray(const CIccTagSparseMatrixArray &ITSMA)
4020{
4021 m_nSize = ITSMA.m_nSize;
4022 m_nChannelsPerMatrix = ITSMA.m_nChannelsPerMatrix;
4023 m_nMatrixType = ITSMA.m_nMatrixType;
4024
4025 m_RawData = (icUInt8Number*)calloc(m_nSize, GetBytesPerMatrix());
4026 memcpy(m_RawData, ITSMA.m_RawData, m_nSize*GetBytesPerMatrix());
4027
4028 m_bNonZeroPadding = ITSMA.m_bNonZeroPadding;
4029}
4030
4031
4032/**
4033 ****************************************************************************
4034 * Name: CIccTagSparseMatrixArray::operator=
4035 *
4036 * Purpose: Copy Operator
4037 *
4038 * Args:
4039 * ITFN = The CIccTagSparseMatrixArray object to be copied
4040 *****************************************************************************
4041 */
4042CIccTagSparseMatrixArray &CIccTagSparseMatrixArray::operator=(const CIccTagSparseMatrixArray &ITSMA)
4043{
4044 if (&ITSMA == this)
4045 return *this;
4046
4047 m_nSize = ITSMA.m_nSize;
4048 m_nChannelsPerMatrix = ITSMA.m_nChannelsPerMatrix;
4049
4050 if (m_RawData)
4051 free(m_RawData);
4052 m_RawData = (icUInt8Number*)calloc(m_nSize, m_nChannelsPerMatrix);
4053 memcpy(m_RawData, ITSMA.m_RawData, m_nSize*GetBytesPerMatrix());
4054
4055 m_bNonZeroPadding = ITSMA.m_bNonZeroPadding;
4056
4057 return *this;
4058}
4059
4060
4061
4062/**
4063 ****************************************************************************
4064 * Name: CIccTagSparseMatrixArray::~CIccTagSparseMatrixArray
4065 *
4066 * Purpose: Destructor
4067 *
4068 *****************************************************************************
4069 */
4070CIccTagSparseMatrixArray::~CIccTagSparseMatrixArray()
4071{
4072 if (m_RawData)
4073 free(m_RawData);
4074}
4075
4076
4077/**
4078 ****************************************************************************
4079 * Name: CIccTagSparseMatrixArray::Read
4080 *
4081 * Purpose: Read in the tag contents into a data block
4082 *
4083 * Args:
4084 * size - # of bytes in tag,
4085 * pIO - IO object to read tag from
4086 *
4087 * Return:
4088 * true = successful, false = failure
4089 *****************************************************************************
4090 */
4091bool CIccTagSparseMatrixArray::Read(icUInt32Number size, CIccIO *pIO)
4092{
4093 icTagTypeSignature sig;
4094 icUInt16Number nChannels;
4095 icUInt16Number nMatrixType;
4096 icUInt32Number nBytesPerMatrix;
4097 icUInt32Number nNumMatrices;
4098
4099 icUInt32Number nHdrSize = sizeof(icTagTypeSignature) +
4100 sizeof(icUInt32Number) +
4101 2*sizeof(icUInt16Number) +
4102 sizeof(icUInt32Number);
4103
4104 if (nHdrSize +sizeof(icUInt16Number) > size)
4105 return false;
4106
4107 if (!pIO) {
4108 return false;
4109 }
4110
4111 if (!pIO->Read32(&sig) ||
4112 !pIO->Read32(&m_nReserved) ||
4113 !pIO->Read16(&nChannels) ||
4114 !pIO->Read16(&nMatrixType) ||
4115 !pIO->Read32(&nNumMatrices))
4116 return false;
4117
4118 m_nMatrixType = (icSparseMatrixType)nMatrixType;
4119
4120 icUInt32Number nSizeLeft = size - nHdrSize;
4121
4122 Reset(nNumMatrices, nChannels);
4123 nBytesPerMatrix = GetBytesPerMatrix();
4124
4125 if (m_nSize) {
4126 icUInt32Number pos;
4127 icUInt16Number nRows;
4128
4129 int i, j;
4130 icUInt32Number n, nAligned;
4131 CIccSparseMatrix mtx;
4132
4133 m_bNonZeroPadding = false;
4134
4135 pos = nHdrSize;
4136 for (i=0; i<(int)m_nSize; i++) {
4137 icUInt8Number *pMatrix = m_RawData + i*nBytesPerMatrix;
4138
4139 n=2*sizeof(icUInt16Number);
4140
4141 if (nSizeLeft<n)
4142 return false;
4143 if (pIO->Read16(pMatrix, 2)!=2) {
4144 return false;
4145 }
4146
4147 nSizeLeft -= n;
4148 pos += n;
4149
4150 nRows = *((icUInt16Number*)pMatrix);
4151
4152 n=(nRows+1)*sizeof(icUInt16Number);
4153
4154 if (nSizeLeft<n)
4155 return false;
4156 if (pIO->Read16(pMatrix+2*sizeof(icUInt16Number), nRows+1)!=nRows+1) {
4157 return false;
4158 }
4159
4160 nSizeLeft -= n;
4161 pos += n;
4162 mtx.Reset(pMatrix, nBytesPerMatrix, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), true);
4163
4164 if (mtx.GetNumEntries()>mtx.MaxEntries(nChannels*sizeof(icFloatNumber), mtx.Rows(), sizeof(icFloatNumber)))
4165 return false;
4166
4167 n=mtx.GetNumEntries()*sizeof(icUInt16Number);
4168
4169 if (nSizeLeft<n)
4170 return false;
4171
4172 if (pIO->Read16(mtx.GetColumnsForRow(0), mtx.GetNumEntries())!=mtx.GetNumEntries())
4173 return false;
4174
4175 nSizeLeft -= n;
4176 pos += n;
4177
4178 nAligned = ((pos+3)/4)*4;
4179 if (nAligned != pos) {
4180 n = nAligned - pos;
4181 if (nSizeLeft < n)
4182 return false;
4183
4184 char zbuf[3];
4185 if (pIO->Read8(&zbuf[0], n)!=n)
4186 return false;
4187 for (j=0; j<(int)n; j++) {
4188 if (zbuf[j])
4189 m_bNonZeroPadding = true;
4190 }
4191
4192 nSizeLeft -= n;
4193 pos += n;
4194 }
4195
4196 switch(m_nMatrixType) {
4197 case icSparseMatrixUInt8:
4198 n=mtx.GetNumEntries()*sizeof(icUInt8Number);
4199 if (nSizeLeft<n)
4200 return false;
4201
4202 if (pIO->ReadUInt8Float(mtx.GetData()->getPtr(0), mtx.GetNumEntries())!=mtx.GetNumEntries())
4203 return false;
4204
4205 break;
4206
4207 case icSparseMatrixUInt16:
4208 n=mtx.GetNumEntries()*sizeof(icUInt16Number);
4209 if (nSizeLeft<n)
4210 return false;
4211
4212 if (pIO->ReadUInt16Float(mtx.GetData()->getPtr(0), mtx.GetNumEntries())!=mtx.GetNumEntries())
4213 return false;
4214
4215 break;
4216
4217 case icSparseMatrixFloat16:
4218 n=mtx.GetNumEntries()*sizeof(icFloat16Number);
4219 if (nSizeLeft<n)
4220 return false;
4221
4222 if (pIO->ReadFloat16Float(mtx.GetData()->getPtr(0), mtx.GetNumEntries())!=mtx.GetNumEntries())
4223 return false;
4224
4225 break;
4226
4227 case icSparseMatrixFloat32:
4228 n=mtx.GetNumEntries()*sizeof(icFloat32Number);
4229 if (nSizeLeft<n)
4230 return false;
4231
4232 if (pIO->ReadFloat32Float(mtx.GetData()->getPtr(0), mtx.GetNumEntries())!=mtx.GetNumEntries())
4233 return false;
4234
4235 break;
4236
4237 default:
4238 return false;
4239 }
4240 nSizeLeft -= n;
4241 pos += n;
4242
4243 nAligned = ((pos+3)/4)*4;
4244 if (nAligned != pos) {
4245 n = nAligned - pos;
4246 if (nSizeLeft < n)
4247 return false;
4248
4249 icUInt8Number zbuf[3];
4250 if (pIO->Read8(&zbuf[0], n)!=n)
4251 return false;
4252 for (j=0; j<(int)n; j++) {
4253 if (zbuf[j])
4254 m_bNonZeroPadding = true;
4255 }
4256
4257 nSizeLeft -= n;
4258 pos += n;
4259 }
4260 }
4261 if (nSizeLeft) {
4262 icUInt8Number b;
4263 for (i=0; i<(int)nSizeLeft; i++) {
4264 if (!pIO->Read8(&b))
4265 return false;
4266 if (b)
4267 m_bNonZeroPadding = true;
4268 }
4269 }
4270 }
4271
4272 return true;
4273}
4274
4275
4276/**
4277 ****************************************************************************
4278 * Name: CIccTagSparseMatrixArray::Write
4279 *
4280 * Purpose: Write the tag to a file
4281 *
4282 * Args:
4283 * pIO - The IO object to write tag to.
4284 *
4285 * Return:
4286 * true = succesful, false = failure
4287 *****************************************************************************
4288 */
4289bool CIccTagSparseMatrixArray::Write(CIccIO *pIO)
4290{
4291 icTagTypeSignature sig = GetType();
4292 icUInt16Number nTemp = m_nMatrixType;
4293
4294 if (!pIO)
4295 return false;
4296
4297 if (!pIO->Write32(&sig) ||
4298 !pIO->Write32(&m_nReserved) ||
4299 !pIO->Write16(&m_nChannelsPerMatrix) ||
4300 !pIO->Write16(&nTemp) ||
4301 !pIO->Write32(&m_nSize))
4302 return false;
4303
4304 icUInt32Number nBytesPerMatrix = m_nChannelsPerMatrix * sizeof(icFloatNumber);
4305 CIccSparseMatrix mtx;
4306 icUInt16Number nRows;
4307 int i, n;
4308
4309 for (i=0; i<(int)m_nSize; i++) {
4310 icUInt8Number *pMatrix = m_RawData + i*nBytesPerMatrix;
4311 mtx.Reset(pMatrix, nBytesPerMatrix, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), true);
4312 nRows = mtx.Rows();
4313
4314 n=(nRows+3)*sizeof(icUInt16Number);
Value stored to 'n' is never read
4315
4316 if (pIO->Write16(pMatrix, nRows+3)!=nRows+3 ||
4317 pIO->Write16(mtx.GetColumnsForRow(0), mtx.GetNumEntries())!=mtx.GetNumEntries()) {
4318 return false;
4319 }
4320
4321 if (!pIO->Align32())
4322 return false;
4323
4324 switch(m_nMatrixType) {
4325 case icSparseMatrixUInt8:
4326 if (pIO->WriteUInt8Float(mtx.GetData()->getPtr(), mtx.GetNumEntries())!=mtx.GetNumEntries()) {
4327 return false;
4328 }
4329 break;
4330 case icSparseMatrixUInt16:
4331 if (pIO->WriteUInt16Float(mtx.GetData()->getPtr(), mtx.GetNumEntries())!=mtx.GetNumEntries()) {
4332 return false;
4333 }
4334 break;
4335 case icSparseMatrixFloat16:
4336 if (pIO->WriteFloat16Float(mtx.GetData()->getPtr(), mtx.GetNumEntries())!=mtx.GetNumEntries()) {
4337 return false;
4338 }
4339 break;
4340 case icSparseMatrixFloat32:
4341 if (pIO->WriteFloat32Float(mtx.GetData()->getPtr(), mtx.GetNumEntries())!=mtx.GetNumEntries()) {
4342 return false;
4343 }
4344 break;
4345 default:
4346 return false;
4347 }
4348
4349 if (!pIO->Align32())
4350 return false;
4351
4352 }
4353
4354 return true;
4355}
4356
4357/**
4358 ****************************************************************************
4359 * Name: CIccTagSparseMatrixArray::Describe
4360 *
4361 * Purpose: Dump data associated with the tag to a string
4362 *
4363 * Args:
4364 * sDescription - string to concatenate tag dump to
4365 *****************************************************************************
4366 */
4367void CIccTagSparseMatrixArray::Describe(std::string &sDescription)
4368{
4369 icChar buf[128];
4370
4371 sDescription += "Begin_SparseMatrix_Array\r\n";
4372 sprintf(buf, "OutputChannels = %d\r\n", m_nChannelsPerMatrix);
4373 sDescription += buf;
4374 sprintf(buf, "MatrixType = %d\r\n", m_nMatrixType);
4375 sDescription += buf;
4376
4377 int i, r, c;
4378 icUInt32Number nBytesPerMatrix = m_nChannelsPerMatrix * sizeof(icFloatNumber);
4379 for (i=0; i<(int)m_nSize; i++) {
4380 CIccSparseMatrix mtx(&m_RawData[i*nBytesPerMatrix], nBytesPerMatrix, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), true);
4381
4382 sprintf(buf, "\r\nBegin_Matrix_%d\r\n", i);
4383 sDescription += buf;
4384
4385 icUInt16Number *start = mtx.GetRowStart();
4386 icUInt16Number *cols = mtx.GetColumnsForRow(0);
4387 for (r=0; r<mtx.Rows(); r++) {
4388 icUInt16Number rs = start[r];
4389 icUInt16Number re = start[r+1];
4390 sprintf(buf, "Row%d:", r);
4391 sDescription += buf;
4392
4393 for (c=rs; c<re; c++) {
4394 sprintf(buf, " (%d, %.4lf)", cols[c], mtx.GetData()->get(c));
4395 sDescription += buf;
4396 }
4397 }
4398
4399 sprintf(buf, "End_Matrix_%d\r\n", i);
4400 sDescription += buf;
4401 }
4402 sDescription += "\r\nEnd_SparseMatrix_Array\r\n";
4403
4404}
4405
4406/**
4407 ****************************************************************************
4408 * Name: CIccTagSparseMatrixArray::Validate
4409 *
4410 * Purpose: Validates tag data
4411 *
4412 * Args:
4413 * sigPath - signature path of tag in profile to validate
4414 * sReport - string to put validation report results
4415 * profile - pointer to profile that contains the tag
4416 *****************************************************************************
4417 */
4418icValidateStatus CIccTagSparseMatrixArray::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
4419{
4420 icValidateStatus rv = icValidateOK;
4421 CIccInfo Info;
4422 std::string sSigPathName = Info.GetSigPathName(sigPath);
4423
4424 switch(m_nMatrixType) {
4425 case icSparseMatrixUInt8:
4426 case icSparseMatrixUInt16:
4427 case icSparseMatrixFloat16:
4428 case icSparseMatrixFloat32:
4429 break;
4430 default:
4431 sReport += icMsgValidateCriticalError;
4432 sReport += sSigPathName;
4433 sReport += " - Invalid Sparse Matrix Type.\r\n";
4434 rv = icMaxStatus(rv, icValidateCriticalError);
4435
4436 }
4437
4438 bool bCheckPCS=false;
4439
4440 icSignature sig1 = icGetFirstSigPathSig(sigPath);
4441 icSignature sig2 = icGetSecondSigPathSig(sigPath);
4442
4443 if (sig1==icSigSpectralWhitePointTag) {
4444 bCheckPCS = true;
4445 }
4446
4447 if (bCheckPCS && pProfile) {
4448 if (!icIsSameColorSpaceType(pProfile->m_Header.spectralPCS, icSigSparseMatrixReflectanceData)((((icUInt32Number)pProfile->m_Header.spectralPCS)&0xffff0000
)==((icUInt32Number)(icSigSparseMatrixReflectanceData)))
) {
4449 sReport += icMsgValidateCriticalError;
4450 sReport += sSigPathName;
4451 sReport += " - SparseMatrix data incompatible with spectral PCS.\r\n";
4452 rv = icMaxStatus(rv, icValidateCriticalError);
4453 }
4454 else if (icGetSpaceSamples((icColorSpaceSignature)pProfile->m_Header.spectralPCS)!=m_nChannelsPerMatrix) {
4455 sReport += icMsgValidateCriticalError;
4456 sReport += sSigPathName;
4457 sReport += " - SparseMatrix Output channels doesn't match spectral PCS channels.\r\n";
4458 rv = icMaxStatus(rv, icValidateCriticalError);
4459 }
4460 }
4461
4462 if (m_bNonZeroPadding) {
4463 sReport += icMsgValidateNonCompliant;
4464 sReport += sSigPathName;
4465 sReport += " - Non zero padding in matrices used.\r\n";
4466 rv = icMaxStatus(rv, icValidateNonCompliant);
4467 }
4468
4469 if (!m_nSize) {
4470 sReport += icMsgValidateWarning;
4471 sReport += sSigPathName;
4472 sReport += " - No Matrices Defined.\r\n";
4473 rv = icMaxStatus(rv, icValidateWarning);
4474 return rv;
4475 }
4476
4477 if (!m_RawData) {
4478 sReport += icMsgValidateCriticalError;
4479 sReport += sSigPathName;
4480 sReport += " - Data dont defined for matrices\r\n";
4481 rv = icMaxStatus(rv, icValidateCriticalError);
4482 return rv;
4483 }
4484
4485 icUInt16Number nRows, nCols;
4486 CIccSparseMatrix mtx;
4487 int i;
4488
4489 icUInt16Number nBytesPerMatrix = m_nChannelsPerMatrix * sizeof(icFloatNumber);
4490
4491 mtx.Reset(m_RawData, nBytesPerMatrix, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), true);
4492 nRows = mtx.Rows();
4493 nCols = mtx.Cols();
4494 icUInt32Number nMaxElements = CIccSparseMatrix::MaxEntries(nBytesPerMatrix, nRows, sizeof(icFloatNumber));
4495 char buf[128];
4496 icUInt8Number *temp = new icUInt8Number[nBytesPerMatrix];
4497
4498 for (i=0; i<(int)m_nSize; i++) {
4499 mtx.Reset(m_RawData+i*nBytesPerMatrix, nBytesPerMatrix, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), true);
4500 if (mtx.Rows() != nRows || mtx.Cols() != nCols) {
4501 sReport += icMsgValidateCriticalError;
4502 sReport += sSigPathName;
4503 sprintf(buf, " - Matrix[%d] doesn't have matching rows and columns.\r\n", i);
4504 sReport += buf;
4505 rv = icMaxStatus(rv, icValidateCriticalError);
4506 }
4507
4508 if (mtx.GetNumEntries()>nMaxElements) {
4509 sReport += icMsgValidateCriticalError;
4510 sReport += sSigPathName;
4511 sprintf(buf, " - Matrix[%d] entries exceeds number supported by Output channels.\r\n", i);
4512 sReport += buf;
4513 rv = icMaxStatus(rv, icValidateCriticalError);
4514 }
4515
4516 if (!mtx.IsValid()) {
4517 sReport += icMsgValidateCriticalError;
4518 sReport += sSigPathName;
4519 sprintf(buf, " - Matrix[%d] has an invalid matrix structure.\r\n", i);
4520 sReport += buf;
4521 rv = icMaxStatus(rv, icValidateCriticalError);
4522 }
4523
4524 if (i<(int)(m_nSize-1)) {
4525 CIccSparseMatrix umtx(temp, nBytesPerMatrix, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), false);
4526 CIccSparseMatrix mtx2(m_RawData+(i+1)*nBytesPerMatrix, nBytesPerMatrix, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), true);
4527
4528 umtx.Init(nRows, nCols);
4529 if (!umtx.Union(mtx, mtx2)) {
4530 sReport += icMsgValidateCriticalError;
4531 sReport += sSigPathName;
4532 sprintf(buf, " - Interpolation from Matrix[%d] exceeds number of supported Output channels.\r\n", i);
4533 sReport += buf;
4534 rv = icMaxStatus(rv, icValidateCriticalError);
4535 }
4536 }
4537 }
4538 delete [] temp;
4539
4540 return rv;
4541}
4542
4543
4544/**
4545 ****************************************************************************
4546 * Name: CIccTagSparseMatrixArray::Reset
4547 *
4548 * Purpose: Sets the size of the data array erasing all previous values
4549 *
4550 * Args:
4551 * nNumMatrices - number of matrices
4552 * numChannelsPerMatrix - Equivalent number of output channels that
4553 * determines the fixed block size for each matrix
4554 *****************************************************************************
4555 */
4556bool CIccTagSparseMatrixArray::Reset(icUInt32Number nNumMatrices, icUInt16Number nChannelsPerMatrix)
4557{
4558 if (nNumMatrices==m_nSize && nChannelsPerMatrix==m_nChannelsPerMatrix)
4559 return true;
4560
4561 m_nSize = nNumMatrices;
4562 m_nChannelsPerMatrix = nChannelsPerMatrix;
4563
4564 icUInt32Number nSize = m_nSize * GetBytesPerMatrix();
4565
4566 m_RawData = (icUInt8Number *)icRealloc(m_RawData, nSize);
4567
4568 if (!m_RawData) {
4569 m_nSize = 0;
4570 return false;
4571 }
4572
4573 memset(m_RawData, 0, nSize);
4574 return true;
4575}
4576
4577
4578/**
4579****************************************************************************
4580* Name: CIccTagSparseMatrixArray::GetValues
4581*
4582* Purpose: Gets values from the num array tag as floating point numbers
4583*
4584* Args:
4585* nSize - number of data entries,
4586* bZeroNew - flag to zero newly formed values
4587*****************************************************************************
4588*/
4589bool CIccTagSparseMatrixArray::GetSparseMatrix(CIccSparseMatrix &mtx, int nIndex, bool bInitFromData/*=true*/)
4590{
4591 if (nIndex<0 || nIndex>(int)m_nSize) {
4592 mtx.Reset(NULL__null, 0, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), false);
4593 return false;
4594 }
4595
4596 icUInt32Number nBytesPerMatrix = GetBytesPerMatrix();
4597
4598 mtx.Reset(m_RawData+nIndex*GetBytesPerMatrix(), nBytesPerMatrix, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), bInitFromData);
4599
4600 return true;
4601}
4602
4603bool CIccTagSparseMatrixArray::GetValues(icFloatNumber *DstVector, icUInt32Number nStart/*=0*/, icUInt32Number nVectorSize/*=1*/) const
4604{
4605 icUInt32Number nBytesPerMatrix = GetBytesPerMatrix();
4606 if (nVectorSize!=nBytesPerMatrix)
4607 return false;
4608 if (nStart % nBytesPerMatrix != 0)
4609 return false;
4610
4611 if (nStart / nBytesPerMatrix > m_nSize)
4612 return false;
4613
4614 memcpy(DstVector, m_RawData+nStart, nVectorSize);
4615 return true;
4616}
4617
4618
4619/**
4620****************************************************************************
4621* Name: CIccTagSparseMatrixArray::Interpolate
4622*
4623* Purpose: Gets values from the num array tag as floating point numbers
4624*
4625* Args:
4626* nSize - number of data entries,
4627* bZeroNew - flag to zero newly formed values
4628*****************************************************************************
4629*/
4630bool CIccTagSparseMatrixArray::Interpolate(icFloatNumber *DstVector, icFloatNumber pos,
4631 icUInt32Number nVectorSize, icFloatNumber *zeroVals) const
4632{
4633 icUInt32Number nMatrix = m_nSize;
4634
4635 if (!nMatrix || nVectorSize != GetBytesPerMatrix())
4636 return false;
4637
4638 if (zeroVals)
4639 nMatrix ++;
4640 else if (nMatrix<=1)
4641 return false;
4642
4643 if (pos<0.0)
4644 pos=0.0;
4645 if (pos>1.0)
4646 pos=1.0;
4647
4648 icFloatNumber fpos = (icFloatNumber)(nMatrix-1) * pos;
4649 icUInt32Number iPos = (icUInt32Number)fpos;
4650 icFloatNumber x = fpos - iPos;
4651
4652 if (iPos == nMatrix-1) {
4653 iPos--;
4654 x = (icFloatNumber)1.0;
4655 }
4656
4657 icUInt8Number *lo, *hi;
4658
4659 if (zeroVals) {
4660 if (!iPos) {
4661 lo = (icUInt8Number*)zeroVals;
4662 hi = m_RawData;
4663 }
4664 else {
4665 lo = &m_RawData[(iPos-1)*nVectorSize];
4666 hi = &lo[nVectorSize];
4667 }
4668 }
4669 else {
4670 lo = &m_RawData[iPos*nVectorSize];
4671 hi = &lo[nVectorSize];
4672 }
4673
4674 CIccSparseMatrix mlo(lo, nVectorSize, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), true);
4675 CIccSparseMatrix mhi(hi, nVectorSize, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), true);
4676 CIccSparseMatrix dst((icUInt8Number*)DstVector, nVectorSize, icSparseMatrixFloatNum((icSparseMatrixType)0x0000), false);
4677
4678 if (mlo.Rows()!=mhi.Rows() || mlo.Cols()!=mhi.Cols())
4679 return false;
4680
4681 if (!dst.Interp(1.0f-x, mlo, x, mhi))
4682 return false;
4683
4684 return true;
4685}
4686
4687
4688/**
4689****************************************************************************
4690* Name: CIccTagSparseMatrixArray::ValuePos
4691*
4692* Purpose: Gets position of a value int the num array tag
4693*
4694* Args:
4695* DstPos - position of val in array
4696* val - value to look for in array.
4697* bNoZero - flag indicating whether first entry is zero
4698*****************************************************************************
4699*/
4700bool CIccTagSparseMatrixArray::ValuePos(icFloatNumber &DstPos, icFloatNumber val, bool &bNoZero) const
4701{
4702 //ValuePos not supported for Sparse Matrices
4703 return false;
4704}
4705
4706
4707/**
4708 ****************************************************************************
4709 * Name: CIccTagFixedNum::CIccTagFixedNum
4710 *
4711 * Purpose: CIccTagFixedNumConstructor
4712 *
4713 * Args:
4714 * nSize = number of data entries
4715 *
4716 *****************************************************************************
4717 */
4718template <class T, icTagTypeSignature Tsig>
4719CIccTagFixedNum<T, Tsig>::CIccTagFixedNum(int nSize/*=1*/)
4720{
4721 m_nSize = nSize;
4722 if (m_nSize <1)
4723 m_nSize = 1;
4724 m_Num = (T*)calloc(nSize, sizeof(T));
4725}
4726
4727
4728/**
4729 ****************************************************************************
4730 * Name: CIccTagFixedNum::CIccTagFixedNum
4731 *
4732 * Purpose: Copy Constructor
4733 *
4734 * Args:
4735 * ITFN = The CIccTagFixedNum object to be copied
4736 *****************************************************************************
4737 */
4738template <class T, icTagTypeSignature Tsig>
4739CIccTagFixedNum<T, Tsig>::CIccTagFixedNum(const CIccTagFixedNum<T, Tsig> &ITFN)
4740{
4741 m_nSize = ITFN.m_nSize;
4742 m_Num = (T*)calloc(m_nSize, sizeof(T));
4743 memcpy(m_Num, ITFN.m_Num, m_nSize*sizeof(T));
4744}
4745
4746
4747/**
4748 ****************************************************************************
4749 * Name: CIccTagFixedNum::operator=
4750 *
4751 * Purpose: Copy Operator
4752 *
4753 * Args:
4754 * ITFN = The CIccTagFixedNum object to be copied
4755 *****************************************************************************
4756 */
4757template <class T, icTagTypeSignature Tsig>
4758CIccTagFixedNum<T, Tsig> &CIccTagFixedNum<T, Tsig>::operator=(const CIccTagFixedNum<T, Tsig> &ITFN)
4759{
4760 if (&ITFN == this)
4761 return *this;
4762
4763 m_nSize = ITFN.m_nSize;
4764
4765 if (m_Num)
4766 free(m_Num);
4767 m_Num = (T*)calloc(m_nSize, sizeof(T));
4768 memcpy(m_Num, ITFN.m_Num, m_nSize*sizeof(T));
4769
4770 return *this;
4771}
4772
4773
4774
4775/**
4776 ****************************************************************************
4777 * Name: CIccTagFixedNum::~CIccTagFixedNum
4778 *
4779 * Purpose: Destructor
4780 *
4781 *****************************************************************************
4782 */
4783template <class T, icTagTypeSignature Tsig>
4784CIccTagFixedNum<T, Tsig>::~CIccTagFixedNum()
4785{
4786 if (m_Num)
4787 free(m_Num);
4788}
4789
4790/**
4791 ****************************************************************************
4792 * Name: CIccTagFixedNum::GetClassName
4793 *
4794 * Purpose: Returns the tag type class name
4795 *
4796 *****************************************************************************
4797 */
4798template <class T, icTagTypeSignature Tsig>
4799const icChar* CIccTagFixedNum<T, Tsig>::GetClassName() const
4800{
4801 if (Tsig==icSigS15Fixed16ArrayType)
4802 return "CIccTagS15Fixed16";
4803 else
4804 return "CIccTagU16Fixed16";
4805}
4806
4807
4808/**
4809 ****************************************************************************
4810 * Name: CIccTagFixedNum::Read
4811 *
4812 * Purpose: Read in the tag contents into a data block
4813 *
4814 * Args:
4815 * size - # of bytes in tag,
4816 * pIO - IO object to read tag from
4817 *
4818 * Return:
4819 * true = successful, false = failure
4820 *****************************************************************************
4821 */
4822template <class T, icTagTypeSignature Tsig>
4823bool CIccTagFixedNum<T, Tsig>::Read(icUInt32Number size, CIccIO *pIO)
4824{
4825 icTagTypeSignature sig;
4826
4827 if (sizeof(icTagTypeSignature) +
4828 sizeof(icUInt32Number) +
4829 sizeof(T) > size)
4830 return false;
4831
4832 if (!pIO) {
4833 return false;
4834 }
4835
4836 if (!pIO->Read32(&sig))
4837 return false;
4838
4839 if (!pIO->Read32(&m_nReserved))
4840 return false;
4841
4842 icUInt32Number nSize=((size-2*sizeof(icUInt32Number)) / sizeof(T));
4843
4844 if (!SetSize(nSize))
4845 return false;
4846
4847 if (pIO->Read32(m_Num, nSize) != (icInt32Number)nSize )
4848 return false;
4849
4850 return true;
4851}
4852
4853
4854/**
4855 ****************************************************************************
4856 * Name: CIccTagFixedNum::Write
4857 *
4858 * Purpose: Write the tag to a file
4859 *
4860 * Args:
4861 * pIO - The IO object to write tag to.
4862 *
4863 * Return:
4864 * true = succesful, false = failure
4865 *****************************************************************************
4866 */
4867template <class T, icTagTypeSignature Tsig>
4868bool CIccTagFixedNum<T, Tsig>::Write(CIccIO *pIO)
4869{
4870 icTagTypeSignature sig = GetType();
4871
4872 if (!pIO)
4873 return false;
4874
4875 if (!pIO->Write32(&sig))
4876 return false;
4877
4878 if (!pIO->Write32(&m_nReserved))
4879 return false;
4880
4881 if (pIO->Write32(m_Num, m_nSize) != (icInt32Number)m_nSize)
4882 return false;
4883
4884 return true;
4885}
4886
4887/**
4888 ****************************************************************************
4889 * Name: CIccTagFixedNum::Describe
4890 *
4891 * Purpose: Dump data associated with the tag to a string
4892 *
4893 * Args:
4894 * sDescription - string to concatenate tag dump to
4895 *****************************************************************************
4896 */
4897template <class T, icTagTypeSignature Tsig>
4898void CIccTagFixedNum<T, Tsig>::Describe(std::string &sDescription)
4899{
4900 icChar buf[128];
4901
4902 if (m_nSize == 1 ) {
4903 if (Tsig==icSigS15Fixed16ArrayType)
4904 sprintf(buf, "Value = %.4lf\r\n", icFtoD(m_Num[0]));
4905 else
4906 sprintf(buf, "Value = %.4lf\r\n", icUFtoD(m_Num[0]));
4907 sDescription += buf;
4908 }
4909 else {
4910 icUInt32Number i;
4911
4912 if (Tsig==icSigS15Fixed16ArrayType && m_nSize==9) {
4913 sDescription += "Matrix Form:\r\n";
4914 icMatrixDump(sDescription, (icS15Fixed16Number*)m_Num);
4915
4916 sDescription += "\r\nArrayForm:\r\n";
4917 }
4918 sDescription.reserve(sDescription.size() + m_nSize*79);
4919
4920 for (i=0; i<m_nSize; i++) {
4921 if (Tsig==icSigS15Fixed16ArrayType)
4922 sprintf(buf, "Value[%u] = %8.4lf\r\n", i, icFtoD(m_Num[i]));
4923 else
4924 sprintf(buf, "Value[%u] = %8.4lf\r\n", i, icUFtoD(m_Num[i]));
4925 sDescription += buf;
4926 }
4927 }
4928}
4929
4930/**
4931 ****************************************************************************
4932 * Name: CIccTagFixedNum::SetSize
4933 *
4934 * Purpose: Sets the size of the data array.
4935 *
4936 * Args:
4937 * nSize - number of data entries,
4938 * bZeroNew - flag to zero newly formed values
4939 *****************************************************************************
4940 */
4941template <class T, icTagTypeSignature Tsig>
4942bool CIccTagFixedNum<T, Tsig>::SetSize(icUInt32Number nSize, bool bZeroNew/*=true*/)
4943{
4944 if (nSize==m_nSize)
4945 return true;
4946
4947 m_Num = (T*)icRealloc(m_Num, nSize*sizeof(T));
4948
4949 if (!m_Num) {
4950 m_nSize = 0;
4951 return false;
4952 }
4953
4954 if (bZeroNew && m_nSize < nSize) {
4955 memset(&m_Num[m_nSize], 0, (nSize-m_nSize)*sizeof(T));
4956 }
4957 m_nSize = nSize;
4958
4959 return true;
4960}
4961
4962/**
4963****************************************************************************
4964* Name: CIccTagFixedNum::GetValues
4965*
4966* Purpose: Gets values from the num array tag as floating point numbers
4967*
4968* Args:
4969* nSize - number of data entries,
4970* bZeroNew - flag to zero newly formed values
4971*****************************************************************************
4972*/
4973template <class T, icTagTypeSignature Tsig>
4974bool CIccTagFixedNum<T, Tsig>::GetValues(icFloatNumber *DstVector, icUInt32Number nStart, icUInt32Number nVectorSize) const
4975{
4976 if (nVectorSize+nStart >m_nSize)
4977 return false;
4978
4979 icUInt32Number i;
4980
4981 switch (Tsig) {
4982 case icSigS15Fixed16ArrayType:
4983 for (i=0; i<m_nSize; i++) {
4984 DstVector[i] = (icFloatNumber)icFtoD(m_Num[i+nStart]);
4985 }
4986 break;
4987 case icSigU16Fixed16ArrayType:
4988 for (i=0; i<m_nSize; i++) {
4989 DstVector[i] = (icFloatNumber)icUFtoD(m_Num[i+nStart]);
4990 }
4991 break;
4992 default:
4993 return false;
4994 }
4995 return true;
4996}
4997
4998
4999/**
5000****************************************************************************
5001* Name: CIccTagFixedNum::Interpolate
5002*
5003* Purpose: Gets values from the num array tag as floating point numbers
5004*
5005* Args:
5006* nSize - number of data entries,
5007* bZeroNew - flag to zero newly formed values
5008*****************************************************************************
5009*/
5010template <class T, icTagTypeSignature Tsig>
5011bool CIccTagFixedNum<T, Tsig>::Interpolate(icFloatNumber *DstVector, icFloatNumber pos,
5012 icUInt32Number nVectorSize, icFloatNumber *zeroVals) const
5013{
5014 icUInt32Number nVector = m_nSize / nVectorSize;
5015
5016 if (!nVector)
5017 return false;
5018
5019 if (zeroVals)
5020 nVector ++;
5021 else if (nVector<=1)
5022 return false;
5023
5024 if (pos<0.0)
5025 pos=0.0;
5026 if (pos>1.0)
5027 pos=1.0;
5028
5029 icFloatNumber fpos = (icFloatNumber)(nVector-1) * pos;
5030 icUInt32Number iPos = (icUInt32Number)fpos;
5031 icFloatNumber x = fpos - iPos;
5032
5033 if (iPos == nVector-1) {
5034 iPos--;
5035 x = (icFloatNumber)1.0;
5036 }
5037
5038 T *lo, *hi;
5039
5040 if (zeroVals) {
5041 if (!iPos) {
5042 lo = NULL__null;
5043 hi = m_Num;
5044 }
5045 else {
5046 lo = &m_Num[(iPos-1)*nVectorSize];
5047 hi = &lo[nVectorSize];
5048 }
5049 }
5050 else {
5051 lo = &m_Num[iPos*nVectorSize];
5052 hi = &lo[nVectorSize];
5053 }
5054
5055 icUInt32Number i;
5056
5057 switch (Tsig) {
5058 case icSigS15Fixed16ArrayType:
5059 if (!lo) {
5060 for (i=0; i<m_nSize; i++) {
5061 DstVector[i] = (icFloatNumber)(zeroVals[i]*(1.0f-x) + icFtoD(hi[i])*x);
5062 }
5063 }
5064 else {
5065 for (i=0; i<m_nSize; i++) {
5066 DstVector[i] = (icFloatNumber)(icFtoD(lo[i])*(1.0-x) + icFtoD(hi[i])*x);
5067 }
5068 }
5069 break;
5070 case icSigU16Fixed16ArrayType:
5071 if (!lo) {
5072 for (i=0; i<m_nSize; i++) {
5073 DstVector[i] = (icFloatNumber)(zeroVals[i]*(1.0-x) + icUFtoD(hi[i])*x);
5074 }
5075 }
5076 else {
5077 for (i=0; i<m_nSize; i++) {
5078 DstVector[i] = (icFloatNumber)(icUFtoD(lo[i])*(1.0-x) + icUFtoD(hi[i])*x);
5079 }
5080 }
5081 break;
5082 default:
5083 return false;
5084 }
5085 return true;
5086}
5087
5088/**
5089****************************************************************************
5090* Name: CIccTagFixedNum::ValuePos
5091*
5092* Purpose: Gets position of a value int the num array tag
5093*
5094* Args:
5095* DstPos - position of val in array
5096* val - value to look for in array.
5097* bNoZero - flag indicating whether first entry is zero
5098*****************************************************************************
5099*/
5100template <class T, icTagTypeSignature Tsig>
5101bool CIccTagFixedNum<T, Tsig>::ValuePos(icFloatNumber &DstPos, icFloatNumber val, bool &bNoZero) const
5102{
5103 if(val<0.0)
5104 return false;
5105
5106 icFloatNumber nv, lv;
5107 switch (Tsig) {
5108 case icSigS15Fixed16ArrayType:
5109 lv = icFtoD(m_Num[0]);
5110 break;
5111 case icSigU16Fixed16ArrayType:
5112 lv = icUFtoD(m_Num[0]);
5113 break;
5114 default:
5115 return false;
5116 }
5117 bNoZero = (lv!=0.0);
5118
5119 if (val<lv) {
5120 DstPos = val/lv - 1.0f;
5121 return true;
5122 }
5123
5124 icUInt32Number i;
5125 for (i=1; i<m_nSize; i++, lv=nv) {
5126 switch (Tsig) {
5127 case icSigS15Fixed16ArrayType:
5128 nv = icFtoD(m_Num[i]);
5129 break;
5130 case icSigU16Fixed16ArrayType:
5131 nv = icUFtoD(m_Num[i]);
5132 break;
5133 default:
5134 return false;
5135 }
5136 if (val<=nv) {
5137 DstPos = (val-lv)/(nv-lv) + i - 1.0f;
5138 return true;
5139 }
5140 }
5141
5142 return false;
5143}
5144
5145
5146//Make sure typedef classes get built
5147template class CIccTagFixedNum<icS15Fixed16Number, icSigS15Fixed16ArrayType>;
5148template class CIccTagFixedNum<icU16Fixed16Number, icSigU16Fixed16ArrayType>;
5149
5150
5151/**
5152 ****************************************************************************
5153 * Name: CIccTagNum::CIccTagNum
5154 *
5155 * Purpose: Constructor
5156 *
5157 * Args:
5158 * nSize = number of data entries
5159 *****************************************************************************
5160 */
5161template <class T, icTagTypeSignature Tsig>
5162CIccTagNum<T, Tsig>::CIccTagNum(int nSize/*=1*/)
5163{
5164 m_nSize = nSize;
5165 if (m_nSize <1)
5166 m_nSize = 1;
5167 m_Num = (T*)calloc(nSize, sizeof(T));
5168}
5169
5170
5171/**
5172 ****************************************************************************
5173 * Name: CIccTagNum::CIccTagNum
5174 *
5175 * Purpose: Copy Constructor
5176 *
5177 * Args:
5178 * ITNum = The CIccTagNum object to be copied
5179 *****************************************************************************
5180 */
5181template <class T, icTagTypeSignature Tsig>
5182CIccTagNum<T, Tsig>::CIccTagNum(const CIccTagNum<T, Tsig> &ITNum)
5183{
5184 m_nSize = ITNum.m_nSize;
5185
5186 m_Num = (T*)calloc(m_nSize, sizeof(T));
5187 memcpy(m_Num, ITNum.m_Num, m_nSize * sizeof(T));
5188}
5189
5190
5191/**
5192 ****************************************************************************
5193 * Name: CIccTagNum::operator=
5194 *
5195 * Purpose: Copy Operator
5196 *
5197 * Args:
5198 * ITNum = The CIccTagNum object to be copied
5199 *****************************************************************************
5200 */
5201template <class T, icTagTypeSignature Tsig>
5202CIccTagNum<T, Tsig> &CIccTagNum<T, Tsig>::operator=(const CIccTagNum<T, Tsig> &ITNum)
5203{
5204 if (&ITNum == this)
5205 return *this;
5206
5207 m_nSize = ITNum.m_nSize;
5208
5209 m_Num = (T*)calloc(m_nSize, sizeof(T));
5210 memcpy(m_Num, ITNum.m_Num, m_nSize * sizeof(T));
5211
5212 return *this;
5213}
5214
5215
5216
5217/**
5218 ****************************************************************************
5219 * Name: CIccTagNum::~CIccTagNum
5220 *
5221 * Purpose: Destructor
5222 *
5223 *****************************************************************************
5224 */
5225template <class T, icTagTypeSignature Tsig>
5226CIccTagNum<T, Tsig>::~CIccTagNum()
5227{
5228 if (m_Num)
5229 free(m_Num);
5230}
5231
5232/**
5233 ****************************************************************************
5234 * Name: CIccTagNum::GetClassName
5235 *
5236 * Purpose: Returns the tag type class name
5237 *
5238 *****************************************************************************
5239 */
5240template <class T, icTagTypeSignature Tsig>
5241const icChar *CIccTagNum<T, Tsig>::GetClassName() const
5242{
5243 if (sizeof(T)==sizeof(icUInt8Number))
5244 return "CIccTagUInt8";
5245 else if (sizeof(T)==sizeof(icUInt16Number))
5246 return "CIccTagUInt16";
5247 else if (sizeof(T)==sizeof(icUInt32Number))
5248 return "CIccTagUInt32";
5249 else if (sizeof(T)==sizeof(icUInt64Number))
5250 return "CIccTagUInt64";
5251 else
5252 return "CIccTagNum<>";
5253}
5254
5255
5256/**
5257 ****************************************************************************
5258 * Name: CIccTagNum::Read
5259 *
5260 * Purpose: Read in the tag contents into a data block
5261 *
5262 * Args:
5263 * size - # of bytes in tag,
5264 * pIO - IO object to read tag from
5265 *
5266 * Return:
5267 * true = successful, false = failure
5268 *****************************************************************************
5269 */
5270template <class T, icTagTypeSignature Tsig>
5271bool CIccTagNum<T, Tsig>::Read(icUInt32Number size, CIccIO *pIO)
5272{
5273 icTagTypeSignature sig;
5274
5275 if (sizeof(icTagTypeSignature) +
5276 sizeof(icUInt32Number) +
5277 sizeof(T) > size)
5278 return false;
5279
5280 if (!pIO) {
5281 return false;
5282 }
5283
5284 if (!pIO->Read32(&sig))
5285 return false;
5286
5287 if (!pIO->Read32(&m_nReserved))
5288 return false;
5289
5290 icUInt32Number nSize=((size-2*sizeof(icUInt32Number)) / sizeof(T));
5291
5292 if (!SetSize(nSize))
5293 return false;
5294
5295 if (sizeof(T)==sizeof(icUInt8Number)) {
5296 if (pIO->Read8(m_Num, nSize) != (icInt32Number)nSize )
5297 return false;
5298 }
5299 else if (sizeof(T)==sizeof(icUInt16Number)) {
5300 if (pIO->Read16(m_Num, nSize) != (icInt32Number)nSize )
5301 return false;
5302 }
5303 else if (sizeof(T)==sizeof(icUInt32Number)) {
5304 if (pIO->Read32(m_Num, nSize) != (icInt32Number)nSize )
5305 return false;
5306 }
5307 else if (sizeof(T)==sizeof(icUInt64Number)) {
5308 if (pIO->Read64(m_Num, nSize) != (icInt32Number)nSize )
5309 return false;
5310 }
5311 else
5312 return false;
5313
5314 return true;
5315}
5316
5317
5318/**
5319 ****************************************************************************
5320 * Name: CIccTagNum::Write
5321 *
5322 * Purpose: Write the tag to a file
5323 *
5324 * Args:
5325 * pIO - The IO object to write tag to.
5326 *
5327 * Return:
5328 * true = succesful, false = failure
5329 *****************************************************************************
5330 */
5331template <class T, icTagTypeSignature Tsig>
5332bool CIccTagNum<T, Tsig>::Write(CIccIO *pIO)
5333{
5334 icTagTypeSignature sig = GetType();
5335
5336 if (!pIO)
5337 return false;
5338
5339 if (!pIO->Write32(&sig))
5340 return false;
5341
5342 if (!pIO->Write32(&m_nReserved))
5343 return false;
5344
5345 if (sizeof(T)==sizeof(icUInt8Number)) {
5346 if (pIO->Write8(m_Num, m_nSize) != (icInt32Number)m_nSize)
5347 return false;
5348 }
5349 else if (sizeof(T)==sizeof(icUInt16Number)) {
5350 if (pIO->Write16(m_Num, m_nSize) != (icInt32Number)m_nSize)
5351 return false;
5352 }
5353 else if (sizeof(T)==sizeof(icUInt32Number)) {
5354 if (pIO->Write32(m_Num, m_nSize) != (icInt32Number)m_nSize)
5355 return false;
5356 }
5357 else if (sizeof(T)==sizeof(icUInt64Number)) {
5358 if (pIO->Write64(m_Num, m_nSize) != (icInt32Number)m_nSize)
5359 return false;
5360 }
5361 else
5362 return false;
5363
5364 return true;
5365}
5366
5367
5368/**
5369 ****************************************************************************
5370 * Name: CIccTagNum::Describe
5371 *
5372 * Purpose: Dump data associated with the tag to a string
5373 *
5374 * Args:
5375 * sDescription - string to concatenate tag dump to
5376 *****************************************************************************
5377 */
5378template <class T, icTagTypeSignature Tsig>
5379void CIccTagNum<T, Tsig>::Describe(std::string &sDescription)
5380{
5381 icChar buf[128];
5382
5383 if (m_nSize == 1 ) {
5384 switch (sizeof(T)) {
5385 case 1:
5386 sprintf(buf, "Value = %u (0x02%x)\r\n", m_Num[0], m_Num[0]);
5387 break;
5388 case 2:
5389 sprintf(buf, "Value = %u (0x04%x)\r\n", m_Num[0], m_Num[0]);
5390 break;
5391 case 4:
5392 sprintf(buf, "Value = %u (0x08%x)\r\n", m_Num[0], m_Num[0]);
5393 break;
5394 case 8:
5395 sprintf(buf, "Value = %u (0x016%x)\r\n", m_Num[0], m_Num[0]);
5396 break;
5397 default:
5398 sprintf(buf, "Value = %u (0x%x)\r\n", m_Num[0], m_Num[0]);
5399 break;
5400 }
5401 sDescription += buf;
5402 }
5403 else {
5404 icUInt32Number i;
5405 sDescription.reserve(sDescription.size() + m_nSize*79);
5406
5407 for (i=0; i<m_nSize; i++) {
5408 switch (sizeof(T)) {
5409 case 1:
5410 sprintf(buf, "Value = %u (0x02%x)\r\n", m_Num[i], m_Num[i]);
5411 break;
5412 case 2:
5413 sprintf(buf, "Value = %u (0x04%x)\r\n", m_Num[i], m_Num[i]);
5414 break;
5415 case 4:
5416 sprintf(buf, "Value = %u (0x08%x)\r\n", m_Num[i], m_Num[i]);
5417 break;
5418 case 8:
5419 sprintf(buf, "Value = %u (0x016%x)\r\n", m_Num[i], m_Num[i]);
5420 break;
5421 default:
5422 sprintf(buf, "Value = %u (0x%x)\r\n", m_Num[i], m_Num[i]);
5423 break;
5424 }
5425 sDescription += buf;
5426 }
5427 }
5428}
5429
5430template <class T, icTagTypeSignature Tsig>
5431icValidateStatus CIccTagNum<T, Tsig>::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile) const
5432{
5433 icValidateStatus rv = icValidateOK;
5434 //Check # of channels
5435 if (icGetFirstSigPathSig(sigPath) == icSigMaterialDefaultValuesTag &&
5436 pProfile &&
5437 m_nSize != icGetMaterialColorSpaceSamples(pProfile->m_Header.mcs)) {
5438 CIccInfo Info;
5439 std::string sSigPathName = Info.GetSigPathName(sigPath);
5440
5441 sReport += icMsgValidateCriticalError;
5442 sReport += sSigPathName;
5443 sReport += " - Number of material default values does not match MCS in header.\r\n";
5444 rv = icMaxStatus(rv, icValidateCriticalError);
5445 }
5446
5447 rv = icMaxStatus(rv, CIccTagNumArray::Validate(sigPath, sReport, pProfile));
5448
5449 return rv;
5450}
5451
5452// template function specialization to handle need for %llu and %llx for 64-bit ints
5453template <>
5454void CIccTagNum<icUInt64Number, icSigUInt64ArrayType>::Describe(std::string &sDescription)
5455{
5456 icChar buf[128];
5457
5458 if (m_nSize == 1 ) {
5459 sprintf(buf, "Value = %llu (0x016%llx)\r\n", m_Num[0], m_Num[0]);
5460 sDescription += buf;
5461 }
5462 else {
5463 icUInt32Number i;
5464 sDescription.reserve(sDescription.size() + m_nSize*79);
5465
5466 for (i=0; i<m_nSize; i++) {
5467 sprintf(buf, "Value = %llu (0x016%llx)\r\n", m_Num[i], m_Num[i]);
5468 sDescription += buf;
5469 }
5470 }
5471}
5472
5473
5474
5475
5476/**
5477 ****************************************************************************
5478 * Name: CIccTagNum::SetSize
5479 *
5480 * Purpose: Sets the size of the data array.
5481 *
5482 * Args:
5483 * nSize - number of data entries,
5484 * bZeroNew - flag to zero newly formed values
5485 *****************************************************************************
5486 */
5487template <class T, icTagTypeSignature Tsig>
5488bool CIccTagNum<T, Tsig>::SetSize(icUInt32Number nSize, bool bZeroNew/*=true*/)
5489{
5490 if (nSize==m_nSize)
5491 return true;
5492
5493 m_Num = (T*)icRealloc(m_Num, nSize*sizeof(T));
5494
5495 if (!m_Num) {
5496 m_nSize = 0;
5497 return false;
5498 }
5499
5500 if (bZeroNew && m_nSize < nSize) {
5501 memset(&m_Num[m_nSize], 0, (nSize-m_nSize)*sizeof(T));
5502 }
5503 m_nSize = nSize;
5504
5505 return true;
5506}
5507
5508/**
5509****************************************************************************
5510* Name: CIccTagNum::GetValues
5511*
5512* Purpose: Gets values from the num array tag as floating point numbers
5513*
5514* Args:
5515* nSize - number of data entries,
5516* bZeroNew - flag to zero newly formed values
5517*****************************************************************************
5518*/
5519template <class T, icTagTypeSignature Tsig>
5520bool CIccTagNum<T, Tsig>::GetValues(icFloatNumber *DstVector, icUInt32Number nStart, icUInt32Number nVectorSize) const
5521{
5522 if (nVectorSize+nStart >m_nSize)
5523 return false;
5524
5525 icUInt32Number i;
5526
5527 switch (Tsig) {
5528 case icSigUInt8ArrayType:
5529 for (i=0; i<m_nSize; i++) {
5530 DstVector[i] = icU8toF((icUInt8Number)(m_Num[i+nStart]));
5531 }
5532 break;
5533 case icSigUInt16ArrayType:
5534 for (i=0; i<m_nSize; i++) {
5535 DstVector[i] = icU16toF((icUInt16Number)(m_Num[i+nStart]));
5536 }
5537 break;
5538 case icSigUInt32ArrayType: //Not Supported
5539 case icSigUInt64ArrayType: //Not Supported
5540 default:
5541 return false;
5542 }
5543 return true;
5544}
5545
5546//Avoid casting warnings for 32 and 64 bit numbers
5547template <>
5548bool CIccTagNum<icUInt32Number, icSigUInt32ArrayType>::GetValues(icFloatNumber *DstVector, icUInt32Number nStart, icUInt32Number nVectorSize) const
5549{
5550 return false;
5551}
5552template <>
5553bool CIccTagNum<icUInt64Number, icSigUInt64ArrayType>::GetValues(icFloatNumber *DstVector, icUInt32Number nStart, icUInt32Number nVectorSize) const
5554{
5555 return false;
5556}
5557
5558/**
5559****************************************************************************
5560* Name: CIccTagNum::Interpolate
5561*
5562* Purpose: Gets values from the num array tag as floating point numbers
5563*
5564* Args:
5565* nSize - number of data entries,
5566* bZeroNew - flag to zero newly formed values
5567*****************************************************************************
5568*/
5569template <class T, icTagTypeSignature Tsig>
5570bool CIccTagNum<T, Tsig>::Interpolate(icFloatNumber *DstVector, icFloatNumber pos,
5571 icUInt32Number nVectorSize, icFloatNumber *zeroVals) const
5572{
5573 icUInt32Number nVector = m_nSize / nVectorSize;
5574
5575 if (!nVector)
5576 return false;
5577
5578 if (zeroVals)
5579 nVector ++;
5580 else if (nVector<=1)
5581 return false;
5582
5583 if (pos<0.0)
5584 pos=0.0;
5585 if (pos>1.0)
5586 pos=1.0;
5587
5588 icFloatNumber fpos = (icFloatNumber)(nVector-1) * pos;
5589 icUInt32Number iPos = (icUInt32Number)fpos;
5590 icFloatNumber x = fpos - iPos;
5591
5592 if (iPos == nVector-1) {
5593 iPos--;
5594 x = (icFloatNumber)1.0;
5595 }
5596
5597 T *lo, *hi;
5598
5599 if (!zeroVals) {
5600 if (!iPos) {
5601 lo = NULL__null;
5602 hi = m_Num;
5603 }
5604 else {
5605 lo = &m_Num[(iPos-1)*nVectorSize];
5606 hi = &lo[nVectorSize];
5607 }
5608 }
5609 else {
5610 lo = &m_Num[iPos*nVectorSize];
5611 hi = &lo[nVectorSize];
5612 }
5613
5614 icUInt32Number i;
5615
5616 switch (Tsig) {
5617 case icSigUInt8ArrayType:
5618 if (!lo) {
5619 for (i=0; i<m_nSize; i++) {
5620 DstVector[i] = zeroVals[i]*(1.0f-x) + icU8toF((icUInt8Number)hi[i])*x;
5621 }
5622 }
5623 else {
5624 for (i=0; i<m_nSize; i++) {
5625 DstVector[i] = icU8toF((icUInt8Number)lo[i])*(1.0f-x) + icU8toF((icUInt8Number)hi[i])*x;
5626 }
5627 }
5628 break;
5629 case icSigUInt16ArrayType:
5630 if (!lo) {
5631 for (i=0; i<m_nSize; i++) {
5632 DstVector[i] = zeroVals[i]*(1.0f-x) + icU16toF((icUInt16Number)hi[i])*x;
5633 }
5634 }
5635 else {
5636 for (i=0; i<m_nSize; i++) {
5637 DstVector[i] = icU16toF((icUInt16Number)lo[i])*(1.0f-x) + icU16toF((icUInt16Number)hi[i])*x;
5638 }
5639 }
5640 break;
5641 case icSigUInt32ArrayType:
5642 case icSigUInt64ArrayType:
5643 default:
5644 return false;
5645 }
5646 return true;
5647}
5648
5649
5650/**
5651****************************************************************************
5652* Name: CIccTagNum::ValuePos
5653*
5654* Purpose: Gets position of a value int the num array tag
5655*
5656* Args:
5657* DstPos - position of val in array
5658* val - value to look for in array.
5659* bNoZero - flag indicating whether first entry is zero
5660*****************************************************************************
5661*/
5662template <class T, icTagTypeSignature Tsig>
5663bool CIccTagNum<T, Tsig>::ValuePos(icFloatNumber &DstPos, icFloatNumber val, bool &bNoZero) const
5664{
5665 if(val<0.0)
5666 return false;
5667
5668 icFloatNumber nv, lv;
5669 switch (Tsig) {
5670 case icSigUInt8ArrayType:
5671 lv = icU8toF((icUInt8Number)m_Num[0]);
5672 break;
5673 case icSigUInt16ArrayType:
5674 lv = icU16toF((icUInt16Number)m_Num[0]);
5675 break;
5676 case icSigUInt32ArrayType:
5677 case icSigUInt64ArrayType:
5678 default:
5679 return false;
5680 }
5681 bNoZero = (lv!=0.0);
5682
5683 if (val<lv) {
5684 DstPos = val/lv - 1.0f;
5685 return true;
5686 }
5687
5688 icUInt32Number i;
5689 for (i=1; i<m_nSize; i++, lv=nv) {
5690 switch (Tsig) {
5691 case icSigUInt8ArrayType:
5692 nv = icU8toF((icUInt8Number)m_Num[i]);
5693 break;
5694 case icSigUInt16ArrayType:
5695 nv = icU16toF((icUInt16Number)m_Num[i]);
5696 break;
5697 case icSigUInt32ArrayType:
5698 case icSigUInt64ArrayType:
5699 default:
5700 return false;
5701 }
5702 if (val<=nv) {
5703 DstPos = (val-lv)/(nv-lv) + i - 1.0f;
5704 return true;
5705 }
5706 }
5707
5708 return false;
5709}
5710
5711//Avoid casting warnings for 32 and 64 bit numbers
5712template <>
5713bool CIccTagNum<icUInt32Number, icSigUInt32ArrayType>::Interpolate(icFloatNumber *DstVector, icFloatNumber pos,
5714 icUInt32Number nVectorSize, icFloatNumber *zeroVals) const
5715{
5716 return false;
5717}
5718template <>
5719bool CIccTagNum<icUInt64Number, icSigUInt64ArrayType>::Interpolate(icFloatNumber *DstVector, icFloatNumber pos,
5720 icUInt32Number nVectorSize, icFloatNumber *zeroVals) const
5721{
5722 return false;
5723}
5724
5725template <>
5726bool CIccTagNum<icUInt32Number, icSigUInt32ArrayType>::ValuePos(icFloatNumber&DstPos, icFloatNumber val, bool &bNoZero) const
5727{
5728 return false;
5729}
5730template <>
5731bool CIccTagNum<icUInt64Number, icSigUInt64ArrayType>::ValuePos(icFloatNumber&DstPos, icFloatNumber val, bool &bNoZero) const
5732{
5733 return false;
5734}
5735
5736//Make sure typedef classes get built
5737template class CIccTagNum<icUInt8Number, icSigUInt8ArrayType>;
5738template class CIccTagNum<icUInt16Number, icSigUInt16ArrayType>;
5739template class CIccTagNum<icUInt32Number, icSigUInt32ArrayType>;
5740template class CIccTagNum<icUInt64Number, icSigUInt64ArrayType>;
5741
5742
5743/**
5744 ****************************************************************************
5745 * Name: CIccTagFloatNum::CIccTagFloatNum
5746 *
5747 * Purpose: Constructor
5748 *
5749 * Args:
5750 * nSize = number of data entries
5751 *****************************************************************************
5752 */
5753template <class T, icTagTypeSignature Tsig>
5754CIccTagFloatNum<T, Tsig>::CIccTagFloatNum(int nSize/*=1*/)
5755{
5756 m_nSize = nSize;
5757 if (m_nSize <1)
5758 m_nSize = 1;
5759 m_Num = (T*)calloc(nSize, sizeof(T));
5760}
5761
5762
5763/**
5764 ****************************************************************************
5765 * Name: CIccTagFloatNum::CIccTagFloatNum
5766 *
5767 * Purpose: Copy Constructor
5768 *
5769 * Args:
5770 * ITNum = The CIccTagNum object to be copied
5771 *****************************************************************************
5772 */
5773template <class T, icTagTypeSignature Tsig>
5774CIccTagFloatNum<T, Tsig>::CIccTagFloatNum(const CIccTagFloatNum<T, Tsig> &ITNum)
5775{
5776 m_nSize = ITNum.m_nSize;
5777
5778 m_Num = (T*)calloc(m_nSize, sizeof(T));
5779 memcpy(m_Num, ITNum.m_Num, m_nSize * sizeof(T));
5780}
5781
5782
5783/**
5784 ****************************************************************************
5785 * Name: CIccTagFloatNum::operator=
5786 *
5787 * Purpose: Copy Operator
5788 *
5789 * Args:
5790 * ITNum = The CIccTagNum object to be copied
5791 *****************************************************************************
5792 */
5793template <class T, icTagTypeSignature Tsig>
5794CIccTagFloatNum<T, Tsig> &CIccTagFloatNum<T, Tsig>::operator=(const CIccTagFloatNum<T, Tsig> &ITNum)
5795{
5796 if (&ITNum == this)
5797 return *this;
5798
5799 m_nSize = ITNum.m_nSize;
5800
5801 m_Num = (T*)calloc(m_nSize, sizeof(T));
5802 memcpy(m_Num, ITNum.m_Num, m_nSize * sizeof(T));
5803
5804 return *this;
5805}
5806
5807
5808
5809/**
5810 ****************************************************************************
5811 * Name: CIccTagFloatNum::~CIccTagFloatNum
5812 *
5813 * Purpose: Destructor
5814 *
5815 *****************************************************************************
5816 */
5817template <class T, icTagTypeSignature Tsig>
5818CIccTagFloatNum<T, Tsig>::~CIccTagFloatNum()
5819{
5820 if (m_Num)
5821 free(m_Num);
5822}
5823
5824/**
5825 ****************************************************************************
5826 * Name: CIccTagFloatNum::GetClassName
5827 *
5828 * Purpose: Returns the tag type class name
5829 *
5830 *****************************************************************************
5831 */
5832template <class T, icTagTypeSignature Tsig>
5833const icChar *CIccTagFloatNum<T, Tsig>::GetClassName() const
5834{
5835 if (Tsig==icSigFloat16ArrayType)
5836 return "CIccFlaot16";
5837 if (Tsig==icSigFloat32ArrayType)
5838 return "CIccFloat32";
5839 else if (Tsig==icSigFloat64ArrayType)
5840 return "CIccFloat64";
5841 else
5842 return "CIccTagFloatNum<>";
5843}
5844
5845
5846/**
5847 ****************************************************************************
5848 * Name: CIccTagFloatNum::Read
5849 *
5850 * Purpose: Read in the tag contents into a data block
5851 *
5852 * Args:
5853 * size - # of bytes in tag,
5854 * pIO - IO object to read tag from
5855 *
5856 * Return:
5857 * true = successful, false = failure
5858 *****************************************************************************
5859 */
5860template <class T, icTagTypeSignature Tsig>
5861bool CIccTagFloatNum<T, Tsig>::Read(icUInt32Number size, CIccIO *pIO)
5862{
5863 icTagTypeSignature sig;
5864
5865 if (Tsig==icSigFloat16ArrayType) {
5866 if (sizeof(icTagTypeSignature) +
5867 sizeof(icUInt32Number) +
5868 sizeof(icFloat16Number) > size)
5869 return false;
5870 }
5871 else {
5872 if (sizeof(icTagTypeSignature) +
5873 sizeof(icUInt32Number) +
5874 sizeof(T) > size)
5875 return false;
5876 }
5877
5878 if (!pIO) {
5879 return false;
5880 }
5881
5882 if (!pIO->Read32(&sig))
5883 return false;
5884
5885 if (!pIO->Read32(&m_nReserved))
5886 return false;
5887
5888 if (Tsig==icSigFloat16ArrayType) {
5889 icUInt32Number nSize=((size-2*sizeof(icUInt32Number)) / sizeof(icFloat16Number));
5890
5891 if (!SetSize(nSize))
5892 return false;
5893
5894 if (pIO->ReadFloat16Float(&m_Num[0], nSize) != (icInt32Number)nSize)
5895 return false;
5896 }
5897 else if (Tsig==icSigFloat32ArrayType) {
5898 icUInt32Number nSize=((size-2*sizeof(icUInt32Number)) / sizeof(icFloat32Number));
5899
5900 if (!SetSize(nSize))
5901 return false;
5902
5903 if (pIO->Read32(m_Num, nSize) != (icInt32Number)nSize )
5904 return false;
5905 }
5906 else if (Tsig==icSigFloat64ArrayType) {
5907 icUInt32Number nSize=((size-2*sizeof(icUInt32Number)) / sizeof(icFloat64Number));
5908
5909 if (!SetSize(nSize))
5910 return false;
5911
5912 if (pIO->Read64(m_Num, nSize) != (icInt32Number)nSize )
5913 return false;
5914 }
5915 else
5916 return false;
5917
5918 return true;
5919}
5920
5921
5922/**
5923 ****************************************************************************
5924 * Name: CIccTagFloatNum::Write
5925 *
5926 * Purpose: Write the tag to a file
5927 *
5928 * Args:
5929 * pIO - The IO object to write tag to.
5930 *
5931 * Return:
5932 * true = succesful, false = failure
5933 *****************************************************************************
5934 */
5935template <class T, icTagTypeSignature Tsig>
5936bool CIccTagFloatNum<T, Tsig>::Write(CIccIO *pIO)
5937{
5938 icTagTypeSignature sig = GetType();
5939
5940 if (!pIO)
5941 return false;
5942
5943 if (!pIO->Write32(&sig))
5944 return false;
5945
5946 if (!pIO->Write32(&m_nReserved))
5947 return false;
5948
5949 if (Tsig==icSigFloat16ArrayType) {
5950 if (pIO->WriteFloat16Float(m_Num, m_nSize) != (icInt32Number)m_nSize)
5951 return false;
5952 }
5953 else if (Tsig == icSigFloat32ArrayType) {
5954 if (pIO->Write32(m_Num, m_nSize) != (icInt32Number)m_nSize)
5955 return false;
5956 }
5957 else if (Tsig == icSigFloat64ArrayType) {
5958 if (pIO->Write64(m_Num, m_nSize) != (icInt32Number)m_nSize)
5959 return false;
5960 }
5961 else
5962 return false;
5963
5964 return true;
5965}
5966
5967
5968/**
5969 ****************************************************************************
5970 * Name: CIccTagFloatNum::Describe
5971 *
5972 * Purpose: Dump data associated with the tag to a string
5973 *
5974 * Args:
5975 * sDescription - string to concatenate tag dump to
5976 *****************************************************************************
5977 */
5978template <class T, icTagTypeSignature Tsig>
5979void CIccTagFloatNum<T, Tsig>::Describe(std::string &sDescription)
5980{
5981 icChar buf[128];
5982
5983 if (m_nSize == 1 ) {
5984 switch (sizeof(T)) {
5985 case 4:
5986 sprintf(buf, "Value = %.8f\r\n", m_Num[0]);
5987 break;
5988 case 8:
5989 sprintf(buf, "Value = %.16f\r\n", m_Num[0]);
5990 break;
5991 default:
5992 sprintf(buf, "Value = %.f\r\n", m_Num[0]);
5993 break;
5994 }
5995 sDescription += buf;
5996 }
5997 else {
5998 icUInt32Number i, n;
5999 sDescription.reserve(sDescription.size() + m_nSize*79);
6000
6001 sprintf(buf, "Begin_Value_Array[%d]\r\n", m_nSize);
6002 sDescription += buf;
6003
6004 if (sizeof(T)!=8)
6005 n=8;
6006 else
6007 n=4;
6008
6009 for (i=0; i<m_nSize; i++) {
6010 if (i&& !(i%n))
6011 sDescription += "\r\n";
6012
6013 switch (sizeof(T)) {
6014 case 4:
6015 sprintf(buf, " %.8f", m_Num[i]);
6016 break;
6017 case 8:
6018 sprintf(buf, " %.16f", m_Num[i]);
6019 break;
6020 default:
6021 sprintf(buf, " %f", m_Num[i]);
6022 }
6023 sDescription += buf;
6024 }
6025 if ((i%n)!=1)
6026 sDescription += "\r\n";
6027 sDescription += "End_Value_Array\r\n";
6028 }
6029}
6030
6031
6032/**
6033 ****************************************************************************
6034 * Name: CIccTagFloatNum::SetSize
6035 *
6036 * Purpose: Sets the size of the data array.
6037 *
6038 * Args:
6039 * nSize - number of data entries,
6040 * bZeroNew - flag to zero newly formed values
6041 *****************************************************************************
6042 */
6043template <class T, icTagTypeSignature Tsig>
6044bool CIccTagFloatNum<T, Tsig>::SetSize(icUInt32Number nSize, bool bZeroNew/*=true*/)
6045{
6046 if (nSize==m_nSize)
6047 return true;
6048
6049 m_Num = (T*)icRealloc(m_Num, nSize*sizeof(T));
6050
6051 if (!m_Num) {
6052 m_nSize = 0;
6053 return false;
6054 }
6055
6056 if (bZeroNew && m_nSize < nSize) {
6057 memset(&m_Num[m_nSize], 0, (nSize-m_nSize)*sizeof(T));
6058 }
6059 m_nSize = nSize;
6060
6061 return true;
6062}
6063
6064/**
6065****************************************************************************
6066* Name: CIccTagFloatNum::GetValues
6067*
6068* Purpose: Gets values from the num array tag as floating point numbers
6069*
6070* Args:
6071* nSize - number of data entries,
6072* bZeroNew - flag to zero newly formed values
6073*****************************************************************************
6074*/
6075template <class T, icTagTypeSignature Tsig>
6076bool CIccTagFloatNum<T, Tsig>::GetValues(icFloatNumber *DstVector, icUInt32Number nStart, icUInt32Number nVectorSize) const
6077{
6078 if (nVectorSize >m_nSize)
6079 return false;
6080
6081 icUInt32Number i;
6082
6083 for (i=0; i<m_nSize; i++) {
6084 DstVector[i] = (icFloatNumber)m_Num[i+nStart];
6085 }
6086 return true;
6087}
6088
6089
6090/**
6091****************************************************************************
6092* Name: CIccTagFloatNum::Interpolate
6093*
6094* Purpose: Gets values from the num array tag as floating point numbers
6095*
6096* Args:
6097* nSize - number of data entries,
6098* bZeroNew - flag to zero newly formed values
6099*****************************************************************************
6100*/
6101template <class T, icTagTypeSignature Tsig>
6102icValidateStatus CIccTagFloatNum<T, Tsig>::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile) const
6103{
6104 icValidateStatus rv = icValidateOK;
6105 //Check # of channels
6106 if (icGetFirstSigPathSig(sigPath) == icSigMaterialDefaultValuesTag &&
6107 pProfile &&
6108 m_nSize != icGetMaterialColorSpaceSamples(pProfile->m_Header.mcs)) {
6109 CIccInfo Info;
6110 std::string sSigPathName = Info.GetSigPathName(sigPath);
6111
6112 sReport += icMsgValidateCriticalError;
6113 sReport += sSigPathName;
6114 sReport += " - Number of material default values does not match MCS in header.\r\n";
6115 rv = icMaxStatus(rv, icValidateCriticalError);
6116 }
6117
6118 rv = icMaxStatus(rv, CIccTagNumArray::Validate(sigPath, sReport, pProfile));
6119
6120 return rv;
6121}
6122
6123
6124
6125/**
6126****************************************************************************
6127* Name: CIccTagFloatNum::Interpolate
6128*
6129* Purpose: Gets values from the num array tag as floating point numbers
6130*
6131* Args:
6132* nSize - number of data entries,
6133* bZeroNew - flag to zero newly formed values
6134*****************************************************************************
6135*/
6136template <class T, icTagTypeSignature Tsig>
6137bool CIccTagFloatNum<T, Tsig>::Interpolate(icFloatNumber *DstVector, icFloatNumber pos,
6138 icUInt32Number nVectorSize, icFloatNumber *zeroVals) const
6139{
6140 icUInt32Number nVector = m_nSize / nVectorSize;
6141
6142 if (!nVector)
6143 return false;
6144
6145 if (zeroVals)
6146 nVector ++;
6147 else if (nVector<=1)
6148 return false;
6149
6150 if (pos<0.0)
6151 pos=0.0;
6152 if (pos>1.0)
6153 pos=1.0;
6154
6155 icFloatNumber fpos = (icFloatNumber)(nVector-1) * pos;
6156 icUInt32Number iPos = (icUInt32Number)fpos;
6157 icFloatNumber x = fpos - iPos;
6158 icFloatNumber invx = (1.0f - x);
6159
6160 if (iPos == nVector-1) {
6161 iPos--;
6162 x = (icFloatNumber)1.0f;
6163 invx = (icFloatNumber)0.0f;
6164 }
6165
6166 T *lo, *hi;
6167
6168 if (zeroVals) {
6169 if (!iPos) {
6170 lo = NULL__null;
6171 hi = m_Num;
6172 }
6173 else {
6174 lo = &m_Num[(iPos-1)*nVectorSize];
6175 hi = &lo[nVectorSize];
6176 }
6177 }
6178 else {
6179 lo = &m_Num[iPos*nVectorSize];
6180 hi = &lo[nVectorSize];
6181 }
6182
6183 icUInt32Number i;
6184
6185 if (!lo) {
6186 for (i=0; i<nVectorSize; i++) {
6187 DstVector[i] = (icFloatNumber)(zeroVals[i]*invx + hi[i]*x);
6188 }
6189 }
6190 else {
6191 for (i=0; i<nVectorSize; i++) {
6192 DstVector[i] = (icFloatNumber)(lo[i]*invx + hi[i]*x);
6193 }
6194 }
6195 return true;
6196}
6197
6198
6199/**
6200****************************************************************************
6201* Name: CIccTagFloatNum::ValuePos
6202*
6203* Purpose: Gets position of a value int the num array tag
6204*
6205* Args:
6206* DstPos - position of val in array
6207* val - value to look for in array.
6208* bNoZero - flag indicating whether first entry is zero
6209*****************************************************************************
6210*/
6211template <class T, icTagTypeSignature Tsig>
6212bool CIccTagFloatNum<T, Tsig>::ValuePos(icFloatNumber &DstPos, icFloatNumber val, bool &bNoZero) const
6213{
6214 if(val<0.0)
6215 return false;
6216
6217 icFloatNumber nv, lv;
6218
6219 lv = (icFloatNumber)m_Num[0];
6220
6221 bNoZero = (lv!=0.0);
6222
6223 if (val<lv) {
6224 DstPos = val/lv - 1.0f;
6225 return true;
6226 }
6227
6228 icUInt32Number i;
6229 for (i=1; i<m_nSize; i++, lv=nv) {
6230 nv = (icFloatNumber)m_Num[i];
6231
6232 if (val<=nv) {
6233 DstPos = (val-lv)/(nv-lv) + i - 1.0f;
6234 return true;
6235 }
6236 }
6237
6238 return false;
6239}
6240
6241
6242//Make sure typedef classes get built
6243template class CIccTagFloatNum<icFloat32Number, icSigFloat16ArrayType>;
6244template class CIccTagFloatNum<icFloat32Number, icSigFloat32ArrayType>;
6245template class CIccTagFloatNum<icFloat64Number, icSigFloat64ArrayType>;
6246
6247/**
6248 ****************************************************************************
6249 * Name: CIccTagMeasurement::CIccTagMeasurement
6250 *
6251 * Purpose: Constructor
6252 *
6253 *****************************************************************************
6254 */
6255CIccTagMeasurement::CIccTagMeasurement()
6256{
6257 memset(&m_Data, 0, sizeof(m_Data));
6258}
6259
6260
6261/**
6262 ****************************************************************************
6263 * Name: CIccTagMeasurement::CIccTagMeasurement
6264 *
6265 * Purpose: Copy Constructor
6266 *
6267 * Args:
6268 * ITM = The CIccTagMeasurement object to be copied
6269 *****************************************************************************
6270 */
6271CIccTagMeasurement::CIccTagMeasurement(const CIccTagMeasurement &ITM)
6272{
6273 memcpy(&m_Data, &ITM.m_Data, sizeof(m_Data));
6274}
6275
6276
6277/**
6278 ****************************************************************************
6279 * Name: CIccTagMeasurement::operator=
6280 *
6281 * Purpose: Copy Operator
6282 *
6283 * Args:
6284 * MeasTag = The CIccTagMeasurement object to be copied
6285 *****************************************************************************
6286 */
6287CIccTagMeasurement &CIccTagMeasurement::operator=(const CIccTagMeasurement &MeasTag)
6288{
6289 if (&MeasTag == this)
6290 return *this;
6291
6292 memcpy(&m_Data, &MeasTag.m_Data, sizeof(m_Data));
6293
6294 return *this;
6295}
6296
6297
6298
6299/**
6300 ****************************************************************************
6301 * Name: CIccTagMeasurement::~CIccTagMeasurement
6302 *
6303 * Purpose: Destructor
6304 *
6305 *****************************************************************************
6306 */
6307CIccTagMeasurement::~CIccTagMeasurement()
6308{
6309}
6310
6311
6312/**
6313 ****************************************************************************
6314 * Name: CIccTagMeasurement::Read
6315 *
6316 * Purpose: Read in the tag contents into a data block
6317 *
6318 * Args:
6319 * size - # of bytes in tag,
6320 * pIO - IO object to read tag from
6321 *
6322 * Return:
6323 * true = successful, false = failure
6324 *****************************************************************************
6325 */
6326bool CIccTagMeasurement::Read(icUInt32Number size, CIccIO *pIO)
6327{
6328 icTagTypeSignature sig;
6329
6330 if (sizeof(icTagTypeSignature) +
6331 sizeof(icUInt32Number) +
6332 sizeof(m_Data) > size)
6333 return false;
6334
6335 if (!pIO) {
6336 return false;
6337 }
6338
6339 if (!pIO->Read32(&sig))
6340 return false;
6341
6342 if (!pIO->Read32(&m_nReserved))
6343 return false;
6344
6345 icUInt32Number nSize=sizeof(m_Data)/sizeof(icUInt32Number);
6346
6347 if (pIO->Read32(&m_Data,nSize) != (icInt32Number)nSize)
6348 return false;
6349
6350 return true;
6351}
6352
6353
6354/**
6355 ****************************************************************************
6356 * Name: CIccTagMeasurement::Write
6357 *
6358 * Purpose: Write the tag to a file
6359 *
6360 * Args:
6361 * pIO - The IO object to write tag to.
6362 *
6363 * Return:
6364 * true = succesful, false = failure
6365 *****************************************************************************
6366 */
6367bool CIccTagMeasurement::Write(CIccIO *pIO)
6368{
6369 icTagTypeSignature sig = GetType();
6370
6371 if (!pIO)
6372 return false;
6373
6374 if (!pIO->Write32(&sig))
6375 return false;
6376
6377 if (!pIO->Write32(&m_nReserved))
6378 return false;
6379
6380 icUInt32Number nSize=sizeof(m_Data)/sizeof(icUInt32Number);
6381
6382 if (pIO->Write32(&m_Data,nSize) != (icInt32Number)nSize)
6383 return false;
6384
6385 return true;
6386}
6387
6388
6389/**
6390 ****************************************************************************
6391 * Name: CIccTagMeasurement::Describe
6392 *
6393 * Purpose: Dump data associated with the tag to a string
6394 *
6395 * Args:
6396 * sDescription - string to concatenate tag dump to
6397 *****************************************************************************
6398 */
6399void CIccTagMeasurement::Describe(std::string &sDescription)
6400{
6401 CIccInfo Fmt;
6402 icChar buf[128];
6403
6404 sDescription += Fmt.GetStandardObserverName(m_Data.stdObserver); sDescription += "\r\n";
6405 sprintf(buf, "Backing measurement: X=%.4lf, Y=%.4lf, Z=%.4lf\r\n",
6406 icFtoD(m_Data.backing.X),
6407 icFtoD(m_Data.backing.Y),
6408 icFtoD(m_Data.backing.Z));
6409 sDescription += buf;
6410 sDescription += Fmt.GetMeasurementGeometryName(m_Data.geometry); sDescription += "\r\n";
6411 sDescription += Fmt.GetMeasurementFlareName(m_Data.flare); sDescription += "\r\n";
6412 sDescription += Fmt.GetIlluminantName(m_Data.illuminant); sDescription += "\r\n";
6413}
6414
6415
6416/**
6417******************************************************************************
6418* Name: CIccTagMeasurement::Validate
6419*
6420* Purpose: Check tag data validity.
6421*
6422* Args:
6423* sig = signature of tag being validated,
6424* sReport = String to add report information to
6425*
6426* Return:
6427* icValidateStatusOK if valid, or other error status.
6428******************************************************************************
6429*/
6430icValidateStatus CIccTagMeasurement::Validate(std::string sigPath, std::string &sReport, const CIccProfile* pProfile/*=NULL*/) const
6431{
6432 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
6433
6434 CIccInfo Info;
6435 std::string sSigPathName = Info.GetSigPathName(sigPath);
6436
6437 switch(m_Data.stdObserver) {
6438 case icStdObsUnknown:
6439 case icStdObs1931TwoDegrees:
6440 case icStdObs1964TenDegrees:
6441 break;
6442
6443 default:
6444 sReport += icMsgValidateNonCompliant;
6445 sReport += sSigPathName;
6446 sReport += " - Invalid standard observer encoding.\r\n";
6447 rv = icMaxStatus(rv, icValidateNonCompliant);
6448 }
6449
6450 switch(m_Data.geometry) {
6451 case icGeometryUnknown:
6452 case icGeometry045or450:
6453 case icGeometry0dord0:
6454 break;
6455
6456 default:
6457 sReport += icMsgValidateNonCompliant;
6458 sReport += sSigPathName;
6459 sReport += " - Invalid measurement geometry encoding.\r\n";
6460 rv = icMaxStatus(rv, icValidateNonCompliant);
6461 }
6462
6463 switch(m_Data.illuminant) {
6464 case icIlluminantUnknown:
6465 case icIlluminantD50:
6466 case icIlluminantD65:
6467 case icIlluminantD93:
6468 case icIlluminantF2:
6469 case icIlluminantD55:
6470 case icIlluminantA:
6471 case icIlluminantEquiPowerE:
6472 case icIlluminantF8:
6473 break;
6474
6475 default:
6476 sReport += icMsgValidateNonCompliant;
6477 sReport += sSigPathName;
6478 sReport += " - Invalid standard illuminant encoding.\r\n";
6479 rv = icMaxStatus(rv, icValidateNonCompliant);
6480 }
6481
6482 return rv;
6483}
6484
6485
6486/**
6487 ****************************************************************************
6488 * Name: CIccLocalizedUnicode::CIccLocalizedUnicode
6489 *
6490 * Purpose: Constructor
6491 *
6492 *****************************************************************************
6493 */
6494CIccLocalizedUnicode::CIccLocalizedUnicode()
6495{
6496 m_pBuf = (icUInt16Number*)malloc(1*sizeof(icUInt16Number));
6497 *m_pBuf = 0;
6498 m_nLength = 0;
6499}
6500
6501
6502/**
6503 ****************************************************************************
6504 * Name: CIccLocalizedUnicode::CIccLocalizedUnicode
6505 *
6506 * Purpose: Copy Constructor
6507 *
6508 * Args:
6509 * ILU = The CIccLocalizedUnicode object to be copied
6510 *****************************************************************************
6511 */
6512CIccLocalizedUnicode::CIccLocalizedUnicode(const CIccLocalizedUnicode& ILU)
6513{
6514 m_nLength = ILU.GetLength();
6515 m_pBuf = (icUInt16Number*)malloc((m_nLength+1) * sizeof(icUInt16Number));
6516 if (m_nLength)
6517 memcpy(m_pBuf, ILU.GetBuf(), m_nLength*sizeof(icUInt16Number));
6518 m_pBuf[m_nLength] = 0;
6519 m_nLanguageCode = ILU.m_nLanguageCode;
6520 m_nCountryCode = ILU.m_nCountryCode;
6521}
6522
6523
6524/**
6525 ****************************************************************************
6526 * Name: CIccLocalizedUnicode::operator=
6527 *
6528 * Purpose: Copy Operator
6529 *
6530 * Args:
6531 * UnicodeText = The CIccLocalizedUnicode object to be copied
6532 *****************************************************************************
6533 */
6534CIccLocalizedUnicode &CIccLocalizedUnicode::operator=(const CIccLocalizedUnicode &UnicodeText)
6535{
6536 if (&UnicodeText == this)
6537 return *this;
6538
6539 if (SetSize(UnicodeText.GetLength())) {
6540 memcpy(m_pBuf, UnicodeText.GetBuf(), m_nLength*sizeof(icUInt16Number));
6541 }
6542 m_nLanguageCode = UnicodeText.m_nLanguageCode;
6543 m_nCountryCode = UnicodeText.m_nCountryCode;
6544
6545 return *this;
6546}
6547
6548
6549/**
6550 ****************************************************************************
6551 * Name: CIccLocalizedUnicode::~CIccLocalizedUnicode
6552 *
6553 * Purpose: Destructor
6554 *
6555 *****************************************************************************
6556 */
6557CIccLocalizedUnicode::~CIccLocalizedUnicode()
6558{
6559 if (m_pBuf)
6560 free(m_pBuf);
6561}
6562
6563/**
6564 ****************************************************************************
6565 * Name: CIccLocalizedUnicode::GetAnsiSize
6566 *
6567 * Purpose: Returns the size of the ANSI data buffer
6568 *
6569 *****************************************************************************
6570 */
6571icUInt32Number CIccLocalizedUnicode::GetAnsiSize()
6572{
6573 icUInt32Number len;
6574#ifdef USE_WINDOWS_MB_SUPPORT
6575 len = WideCharToMultiByte(CP_ACP, 0x00000400, (LPCWSTR)m_pBuf, m_nLength, NULL__null, 0, NULL__null, NULL__null);
6576#else
6577 len = m_nLength;
6578#endif
6579
6580 return len;
6581}
6582
6583/**
6584 ****************************************************************************
6585 * Name: CIccLocalizedUnicode::GetAnsi
6586 *
6587 * Purpose: Extracts the ANSI data buffer
6588 *
6589 * Args:
6590 * szBuf = pointer where the returned string buffer is to be stored
6591 * nBufSize = size of the buffer to be extracted
6592 *
6593 * Return:
6594 * Pointer to the ANSI data string
6595 *****************************************************************************
6596 */
6597const icChar *CIccLocalizedUnicode::GetAnsi(icChar *szBuf, icUInt32Number nBufSize)
6598{
6599 if (!szBuf)
6600 return NULL__null;
6601
6602 if (!m_nLength) {
6603 *szBuf='\0';
6604 }
6605 else {
6606#ifdef USE_WINDOWS_MB_SUPPORT
6607 int len = WideCharToMultiByte(CP_ACP, 0x00000400, (LPCWSTR)m_pBuf, m_nLength, szBuf, nBufSize, NULL__null, NULL__null);
6608 szBuf[len]='\0';
6609#else
6610 icUInt32Number i;
6611
6612 for (i=0; i<m_nLength; i++) {
6613 if (m_pBuf[i]<256) {
6614 szBuf[i] = (icChar)m_pBuf[i];
6615 }
6616 else {
6617 szBuf[i] = '?';
6618 }
6619 }
6620#endif
6621 }
6622
6623 return szBuf;
6624}
6625
6626/**
6627****************************************************************************
6628* Name: CIccLocalizedUnicode::GetText
6629*
6630* Purpose: Sets a standard string with the text
6631