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