1 /** @file
2 File: IccUtilXml.cpp
3
4 Contains: Implementation of XML conversion utilities
5
6 Version: V1
7
8 Copyright: � see ICC Software License
9 */
10
11 /*
12 * The ICC Software License, Version 0.2
13 *
14 *
15 * Copyright (c) 2003-2010 The International Color Consortium. All rights
16 * reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
29 *
30 * 3. In the absence of prior written permission, the names "ICC" and "The
31 * International Color Consortium" must not be used to imply that the
32 * ICC organization endorses or promotes products derived from this
33 * software.
34 *
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
40 * ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This software consists of voluntary contributions made by many
51 * individuals on behalf of the The International Color Consortium.
52 *
53 *
54 * Membership in the ICC is encouraged when this software is used for
55 * commercial purposes.
56 *
57 *
58 * For more information on The International Color Consortium, please
59 * see <http://www.color.org/>.
60 *
61 *
62 */
63
64 #include "IccUtilXml.h"
65 #include "IccConvertUTF.h"
66 #include <time.h>
67
68 #if defined(WIN32) || defined(WIN64)
69 #include <windows.h>
70 #ifdef GetClassName
71 #undef GetClassName
72 #endif
73 #endif
74 #include <cstring> /* C strings strcpy, memcpy ... */
75
76 const icTagSigType tagSignatureMap[] ={
77 { icSigChromaticityType , "chromaticityType"},
78 { icSigColorantOrderType , "colorantOrderType"},
79 { icSigColorantTableType , "colorantTableType"},
80 { icSigCurveType , "curveType"},
81 { icSigDataType , "dataType"},
82 { icSigDateTimeType , "dateTimeType"},
83 { icSigDictType , "dictType"},
84 { icSigLut16Type , "lut16Type"},
85 { icSigLut8Type , "lut8Type"},
86 { icSigLutAtoBType , "lutAtoBType"},
87 { icSigLutBtoAType , "lutBtoAType"},
88 { icSigMeasurementType , "measurementType"},
89 { icSigMultiLocalizedUnicodeType , "multiLocalizedUnicodeType"},
90 { icSigMultiProcessElementType , "multiProcessElementType"},
91 { icSigNamedColor2Type , "namedColor2Type"},
92 { icSigParametricCurveType , "parametricCurveType"},
93 { icSigProfileSequenceDescType , "profileSequenceDescType"},
94 { icSigProfileSequceIdType , "profileSequenceIdentifierType"},
95 { icSigResponseCurveSet16Type , "responseCurveSet16Type"},
96 { icSigS15Fixed16ArrayType , "s15Fixed16ArrayType"},
97 { icSigSignatureType , "signatureType"},
98 { icSigTextType , "textType"},
99 { icSigTextDescriptionType , "textDescriptionType"},
100 { icSigU16Fixed16ArrayType , "uInt16Type"},
101 { icSigUInt16ArrayType , "uInt16Type"},
102 { icSigUInt32ArrayType , "uInt32ArrayType"},
103 { icSigUInt64ArrayType , "uInt64Type"},
104 { icSigUInt8ArrayType , "uInt8Type"},
105 { icSigViewingConditionsType , "viewingConditionsType"},
106 { icSigXYZType , "XYZType"},
107 { icSigXYZArrayType , "XYZType"},
108 { icSigUnknownType , "PrivateType"}
109 };
110 #define tagSignatureMapSize (sizeof(tagSignatureMap)/sizeof(tagSignatureMap[0]))
111
112
113
114
icFixXml(std::string & buf,const char * szStr)115 const char *icFixXml(std::string &buf, const char *szStr)
116 {
117 buf = "";
118 while (*szStr) {
119 switch (*szStr) {
120 case '\'':
121 buf += "'";
122 break;
123 case '&':
124 buf += "&";
125 break;
126 case '\"':
127 buf += """;
128 break;
129 case '<':
130 buf += "<";
131 break;
132 case '>':
133 buf += ">";
134 break;
135 default:
136 buf += *szStr;
137 }
138 szStr++;
139 }
140
141 return buf.c_str();
142 }
143
icFixXml(char * szDest,const char * szStr)144 const char *icFixXml(char *szDest, const char *szStr)
145 {
146 char *ptr = szDest;
147
148 while (*szStr) {
149 switch (*szStr) {
150 case '\'':
151 strcpy(ptr, "'");
152 ptr += 6;
153 break;
154 case '&':
155 strcpy(ptr, "&");
156 ptr += 5;
157 break;
158 case '\"':
159 strcpy(ptr, """);
160 ptr += 6;
161 break;
162 case '<':
163 strcpy(ptr, "<");
164 ptr += 4;
165 break;
166 case '>':
167 strcpy(ptr, ">");
168 ptr += 4;
169 break;
170 default:
171 *ptr++ = *szStr;
172 }
173 szStr++;
174 }
175 *ptr = '\0';
176
177 return szDest;
178 }
179
icAnsiToUtf8(std::string & buf,const char * szSrc)180 const char *icAnsiToUtf8(std::string &buf, const char *szSrc)
181 {
182 #if defined(WIN32) || defined(WIN64)
183 size_t len = strlen(szSrc)+1;
184 wchar_t *szUnicodeBuf = (wchar_t*)malloc(len*sizeof(icUInt16Number)*2);
185 char *szBuf = (char*)malloc(len*2);
186
187 size_t n;
188
189 n=MultiByteToWideChar(CP_ACP, 0, szSrc, (int)len-1, szUnicodeBuf, (int)len*2);
190 szUnicodeBuf[n] = '\0';
191
192 n = WideCharToMultiByte(CP_UTF8, 0, (const wchar_t*)szUnicodeBuf, (int)n, szBuf, (int)len*2, 0, NULL);
193 szBuf[n] = '\0';
194
195 buf = szBuf;
196
197 free(szBuf);
198 free(szUnicodeBuf);
199 #else
200 buf = szSrc;
201 #endif
202 return buf.c_str();
203 }
204
icUtf8ToAnsi(std::string & buf,const char * szSrc)205 const char *icUtf8ToAnsi(std::string &buf, const char *szSrc)
206 {
207 #if defined(WIN32) || defined(WIN64)
208 size_t len = strlen(szSrc)+1;
209 wchar_t *szUnicodeBuf = (wchar_t*)malloc(len*sizeof(icUInt16Number)*2);
210 char *szBuf = (char*)malloc(len*2);
211
212 size_t n;
213
214 n=MultiByteToWideChar(CP_UTF8, 0, szSrc, (int)len-1, szUnicodeBuf, (int)len*2);
215 szUnicodeBuf[n] = '\0';
216
217 n = WideCharToMultiByte(CP_ACP, 0, (const wchar_t*)szUnicodeBuf, (int)n, szBuf, (int)len*2, "?", NULL);
218 szBuf[n] = '\0';
219
220 buf = szBuf;
221
222 free(szBuf);
223 free(szUnicodeBuf);
224 #else
225 buf = szSrc;
226 #endif
227 return buf.c_str();
228 }
229
230 class CIccDumpXmlCLUT : public IIccCLUTExec
231 {
232 public:
CIccDumpXmlCLUT(std::string * xml,icConvertType nType,std::string blanks,icUInt16Number nSamples,icUInt8Number nPixelsPerRow)233 CIccDumpXmlCLUT(std::string *xml, icConvertType nType, std::string blanks, icUInt16Number nSamples, icUInt8Number nPixelsPerRow)
234 {
235 m_xml = xml;
236 m_nType = nType;
237 m_blanks = blanks;
238 m_nSamples = nSamples;
239 m_nPixelsPerRow = nPixelsPerRow;
240 m_nCurPixel = 0;
241 }
242
PixelOp(icFloatNumber * pGridAdr,icFloatNumber * pData)243 virtual void PixelOp(icFloatNumber* pGridAdr, icFloatNumber* pData)
244 {
245 int i;
246 char buf[128];
247
248 if (!(m_nCurPixel % m_nPixelsPerRow))
249 *m_xml += m_blanks;
250
251 switch(m_nType) {
252 case icConvert8Bit:
253 for (i=0; i<m_nSamples; i++) {
254 sprintf(buf, " %3d", (icUInt8Number)(pData[i]*255.0 + 0.5));
255 *m_xml += buf;
256 }
257 break;
258 case icConvert16Bit:
259 for (i=0; i<m_nSamples; i++) {
260 sprintf(buf, " %5d", (icUInt16Number)(pData[i]*65535.0 + 0.5));
261 *m_xml += buf;
262 }
263 break;
264 case icConvertFloat:
265 default:
266 for (i=0; i<m_nSamples; i++) {
267 sprintf(buf, " %13.8f", pData[i]);
268 *m_xml += buf;
269 }
270 break;
271 }
272 m_nCurPixel++;
273 if (!(m_nCurPixel % m_nPixelsPerRow)) {
274 *m_xml += "\n";
275 }
276 }
277
Finish()278 void Finish()
279 {
280 if (m_nCurPixel % m_nPixelsPerRow) {
281 *m_xml += "\n";
282 }
283 }
284
285 std::string *m_xml;
286 icConvertType m_nType;
287 std::string m_blanks;
288 icUInt16Number m_nSamples;
289 icUInt8Number m_nPixelsPerRow;
290 icUInt32Number m_nCurPixel;
291 };
292
293
icCLUTToXml(std::string & xml,CIccCLUT * pCLUT,icConvertType nType,std::string blanks,bool bSaveGridPoints,const char * szExtraAttrs,const char * szName)294 bool icCLUTToXml(std::string &xml, CIccCLUT *pCLUT, icConvertType nType, std::string blanks,
295 bool bSaveGridPoints/*=false*/, const char *szExtraAttrs/*=""*/, const char *szName/*="CLUT"*/)
296 {
297 char buf[128];
298 if (nType == icConvertVariable) {
299 nType = pCLUT->GetPrecision()==1 ? icConvert8Bit : icConvert16Bit;
300 }
301
302 xml += blanks + "<" + szName;
303
304 if (!bSaveGridPoints) {
305 sprintf(buf, " GridGranularity=\"%d\"", pCLUT->GridPoint(0));
306 xml += buf;
307 }
308
309 if (szExtraAttrs && *szExtraAttrs) {
310 xml += szExtraAttrs;
311 }
312 xml += ">\n";
313
314 if (bSaveGridPoints) {
315 xml += blanks + " <GridPoints>";
316 int i;
317
318 for (i=0; i<pCLUT->GetInputDim(); i++) {
319 if (i)
320 sprintf(buf, " %d", pCLUT->GridPoint(i));
321 else
322 sprintf(buf, "%d", pCLUT->GridPoint(i));
323 xml += buf;
324 }
325 xml += "</GridPoints>\n";
326 }
327
328 int nPixelsPerRow = pCLUT->GridPoint(0);
329
330 // if the CLUT has no GridPoints, profile is invalid
331 if (nPixelsPerRow == 0) {
332 printf("\nError! - CLUT Table not found.\n");
333 return false;
334 }
335
336 CIccDumpXmlCLUT dumper(&xml, nType, blanks + " ", pCLUT->GetOutputChannels(), nPixelsPerRow);
337
338 xml += blanks + " <TableData>\n";
339 pCLUT->Iterate(&dumper);
340
341 dumper.Finish();
342
343 xml += blanks + " </TableData>\n";
344
345 xml += blanks + "</" + szName + ">\n";
346 return true;
347 }
348
icXmlStrToFloat(const xmlChar * szStr)349 icFloatNumber icXmlStrToFloat(const xmlChar *szStr)
350 {
351 float f=0.0;
352 sscanf((const char*)szStr, "%f", &f);
353
354 return (icFloatNumber)f;
355 }
356
icXmlStrToSig(const char * szStr)357 icSignature icXmlStrToSig(const char *szStr)
358 {
359 return icGetSigVal(szStr);
360 }
361
icXmlAttrValue(xmlAttr * attr,const char * szDefault)362 const char *icXmlAttrValue(xmlAttr *attr, const char *szDefault)
363 {
364 if (attr && attr->children && attr->children->type == XML_TEXT_NODE && attr->children->content)
365 return (const char*)attr->children->content;
366
367 return szDefault;
368 }
369
icXmlAttrValue(xmlNode * pNode,const char * szName,const char * szDefault)370 const char *icXmlAttrValue(xmlNode *pNode, const char *szName, const char *szDefault)
371 {
372 xmlAttr *attr = icXmlFindAttr(pNode, szName);
373 if (attr) {
374 return icXmlAttrValue(attr, szDefault);
375 }
376 return szDefault;
377 }
378
icXmlGetChildSigVal(xmlNode * pNode)379 icUInt32Number icXmlGetChildSigVal(xmlNode *pNode)
380 {
381 if (!pNode || !pNode->children || !pNode->children->content)
382 return 0;
383
384 return icGetSigVal((const char*)pNode->children->content);
385 }
386
hexValue(char c)387 static int hexValue(char c)
388 {
389 if (c>='0' && c<='9')
390 return c-'0';
391 if (c>='A' && c<='F')
392 return c-'A'+10;
393 if (c>='a' && c<='f')
394 return c-'a'+10;
395 return -1;
396 }
397
398
icXmlGetHexData(void * pBuf,const char * szText,icUInt32Number nBufSize)399 icUInt32Number icXmlGetHexData(void *pBuf, const char *szText, icUInt32Number nBufSize)
400 {
401 unsigned char *pDest = (unsigned char*)pBuf;
402 icUInt32Number rv =0;
403
404 while(*szText && rv<nBufSize) {
405 int c1=hexValue(szText[0]);
406 int c2=hexValue(szText[1]);
407 if (c1>=0 && c2>=0) {
408 *pDest = c1*16+ c2;
409 pDest++;
410 szText +=2;
411 rv++;
412 }
413 else {
414 szText++;
415 }
416 }
417 return rv;
418 }
419
icXmlGetHexDataSize(const char * szText)420 icUInt32Number icXmlGetHexDataSize(const char *szText)
421 {
422 icUInt32Number rv =0;
423
424 while(*szText) {
425 int c1=hexValue(szText[0]);
426 int c2=hexValue(szText[1]);
427 if (c1>=0 && c2>=0) {
428 szText +=2;
429 rv++;
430 }
431 else {
432 szText++;
433 }
434 }
435 return rv;
436 }
437
icXmlDumpHexData(std::string & xml,std::string blanks,void * pBuf,icUInt32Number nBufSize)438 icUInt32Number icXmlDumpHexData(std::string &xml, std::string blanks, void *pBuf, icUInt32Number nBufSize)
439 {
440 icUInt8Number *ptr = (icUInt8Number *)pBuf;
441 char buf[15];
442 icUInt32Number i;
443
444 for (i=0; i<nBufSize; i++, ptr++) {
445 if (!(i%32)) {
446 if (i)
447 xml += "\n";
448 xml += blanks;
449 }
450 sprintf(buf, "%02x", *ptr);
451 xml += buf;
452 }
453 if (i) {
454 xml += "\n";
455 }
456 return i;
457 }
458
icXmlFindAttr(xmlNode * pNode,const char * szAttrName)459 xmlAttr *icXmlFindAttr(xmlNode *pNode, const char *szAttrName)
460 {
461 if (!pNode) return NULL;
462
463 xmlAttr *attr;
464
465 for (attr = pNode->properties; attr; attr = attr->next) {
466 if (attr->type != XML_ATTRIBUTE_NODE)
467 continue;
468
469 if (!icXmlStrCmp(attr->name, szAttrName)) {
470 return attr;
471 }
472 }
473
474 return NULL;
475 }
476
icXmlFindNode(xmlNode * pNode,const char * szNodeName)477 xmlNode *icXmlFindNode(xmlNode *pNode, const char *szNodeName)
478 {
479 if (!pNode) return NULL;
480
481 for (; pNode; pNode = pNode->next) {
482 if (pNode->type != XML_ELEMENT_NODE)
483 continue;
484
485 if (!icXmlStrCmp(pNode->name, szNodeName)) {
486 return pNode;
487 }
488 }
489
490 return NULL;
491 }
492
icXmlNodeCount(xmlNode * pNode,const char * szNodeName)493 icUInt32Number icXmlNodeCount(xmlNode *pNode, const char *szNodeName)
494 {
495 icUInt32Number rv = 0;
496 for (; pNode; pNode = pNode->next) {
497 if (pNode->type == XML_ELEMENT_NODE &&
498 !icXmlStrCmp(pNode->name, szNodeName)) {
499 rv++;
500 }
501 }
502 return rv;
503 }
504
505 template <class T, icTagTypeSignature Tsig>
CIccXmlArrayType()506 CIccXmlArrayType<T, Tsig>::CIccXmlArrayType()
507 {
508 m_pBuf = NULL;
509 m_nSize = 0;
510 }
511
512 template <class T, icTagTypeSignature Tsig>
~CIccXmlArrayType()513 CIccXmlArrayType<T, Tsig>::~CIccXmlArrayType()
514 {
515 if (m_pBuf) {
516 free(m_pBuf);
517 }
518 }
519
520 template <class T, icTagTypeSignature Tsig>
ParseArray(xmlNode * pNode)521 bool CIccXmlArrayType<T, Tsig>::ParseArray(xmlNode *pNode)
522 {
523 const char *scanType = (Tsig == icSigFloatArrayType ? "f" : "n");
524 icUInt32Number n = icXmlNodeCount(pNode, scanType);
525
526 if (n) {
527 if (!SetSize(n))
528 return false;
529 return ParseArray(m_pBuf, m_nSize, pNode);
530 }
531
532 for ( ;pNode && pNode->type!= XML_TEXT_NODE; pNode=pNode->next);
533
534 if (!pNode || !pNode->content)
535 return false;
536
537 n = ParseTextCount((const char*)pNode->content);
538
539 if (!n || !SetSize(n))
540 return false;
541
542 return ParseArray(m_pBuf, m_nSize, pNode);
543 }
544
545 template <class T, icTagTypeSignature Tsig>
ParseTextArray(const char * szText)546 bool CIccXmlArrayType<T, Tsig>::ParseTextArray(const char *szText)
547 {
548 icUInt32Number n = ParseTextCount(szText);
549
550 if (n) {
551 if (!SetSize(n))
552 return false;
553
554 return ParseText(m_pBuf, m_nSize, szText)==m_nSize;
555 }
556
557 return false;
558 }
559
560 template <class T, icTagTypeSignature Tsig>
ParseTextArrayNum(const char * szText,icUInt32Number num,std::string & parseStr)561 bool CIccXmlArrayType<T, Tsig>::ParseTextArrayNum(const char *szText, icUInt32Number num, std::string &parseStr)
562 {
563 icUInt32Number n = ParseTextCountNum(szText, num, parseStr);
564 if (n) {
565 if (!SetSize(n))
566 return false;
567 return ParseText(m_pBuf, m_nSize, szText)==m_nSize;
568 }
569
570 return false;
571 }
572
573 template <class T, icTagTypeSignature Tsig>
DumpArray(std::string & xml,std::string blanks,T * buf,icUInt32Number nBufSize,icConvertType nType,icUInt8Number nColumns)574 bool CIccXmlArrayType<T, Tsig>::DumpArray(std::string &xml, std::string blanks, T *buf, icUInt32Number nBufSize,
575 icConvertType nType, icUInt8Number nColumns)
576 {
577 char str[40];
578
579 if (!nColumns) nColumns = 1;
580 icUInt32Number i;
581
582 for (i=0; i<nBufSize; i++) {
583 if (!(i%nColumns)) {
584 xml += blanks;
585 }
586 else {
587 xml += " ";
588 }
589
590 switch (Tsig) {
591 case icSigUInt8ArrayType:
592 switch (nType) {
593 case icConvert8Bit:
594 default:
595 sprintf(str, "%u", buf[i]);
596 break;
597
598 case icConvert16Bit:
599 sprintf(str, "%u", (icUInt16Number)((icFloatNumber)buf[i] * 65535.0 / 255.0 + 0.5));
600 break;
601
602 case icConvertFloat:
603 sprintf(str, "%.8f", (icFloatNumber)buf[i] / 255.0);
604 break;
605 }
606 break;
607
608 case icSigUInt16ArrayType:
609 switch (nType) {
610 case icConvert8Bit:
611 sprintf(str, "%u", (icUInt16Number)((icFloatNumber)buf[i] * 255.0 / 65535.0 + 0.5));
612 break;
613
614 case icConvert16Bit:
615 default:
616 sprintf(str, "%u", buf[i]);
617 break;
618
619 case icConvertFloat:
620 sprintf(str, "%.8f", (icFloatNumber)buf[i] / 65535.0);
621 break;
622 }
623 break;
624
625 case icSigUInt32ArrayType:
626 sprintf(str, "%u", buf[i]);
627 break;
628
629 case icSigFloatArrayType:
630 switch (nType) {
631 case icConvert8Bit:
632 sprintf(str, "%u", (icUInt8Number)(buf[i] * 255.0 + 0.5));
633 break;
634
635 case icConvert16Bit:
636 sprintf(str, "%u", (icUInt16Number)(buf[i] * 65535.0 + 0.5));
637 break;
638
639 case icConvertFloat:
640 default:
641 sprintf(str, "%.8f", buf[i]);
642 }
643 break;
644 }
645 xml += str;
646 if (i%nColumns == nColumns-1) {
647 xml += "\n";
648 }
649 }
650
651 if (i%nColumns) {
652 xml += "\n";
653 }
654
655 return true;
656 }
657
658 // for multi-platform support
659 // replaced "_inline" with "inline"
icIsNumChar(char c)660 static inline bool icIsNumChar(char c)
661 {
662 if ((c>='0' && c<='9') || c=='.' || c=='+' || c=='-' || c=='e')
663 return true;
664 return false;
665 }
666
667 // function used when checking contents of a file
668 // count the number of entries.
669 template <class T, icTagTypeSignature Tsig>
ParseTextCountNum(const char * szText,icUInt32Number num,std::string & parseStr)670 icUInt32Number CIccXmlArrayType<T, Tsig>::ParseTextCountNum(const char *szText, icUInt32Number num, std::string &parseStr)
671 {
672 icUInt32Number n = 0;
673 bool bInNum = false;
674 //icUInt32Number count = 1;
675
676 //while (*szText) {
677 for (icUInt32Number i=0; i<num; i++) {
678 if (icIsNumChar(*szText)) {
679 if (!bInNum) {
680 bInNum = true;
681 }
682 }
683 // an invalid character is encountered (not digit and not space)
684 else if (!isspace(*szText) && i <= num ){
685 char line[100];
686 sprintf(line, "Data '%c' in position %d is not a number. ", *szText, i);
687 parseStr += line;
688 return false;
689 }
690 else if (bInNum) { //char is a space
691 n++;
692 bInNum = false;
693 }
694 szText++;
695 //count++;
696 }
697 if (bInNum) {
698 n++;
699 }
700
701 return n;
702 }
703
704 template <class T, icTagTypeSignature Tsig>
ParseTextCount(const char * szText)705 icUInt32Number CIccXmlArrayType<T, Tsig>::ParseTextCount(const char *szText)
706 {
707 icUInt32Number n = 0;
708 bool bInNum = false;
709
710 while (*szText) {
711 if (icIsNumChar(*szText)) {
712 if (!bInNum) {
713 bInNum = true;
714 }
715 }
716 else if (bInNum) {
717 n++;
718 bInNum = false;
719 }
720 szText++;
721 }
722 if (bInNum) {
723 n++;
724 }
725
726 return n;
727 }
728
729 template <class T, icTagTypeSignature Tsig>
ParseText(T * pBuf,icUInt32Number nSize,const char * szText)730 icUInt32Number CIccXmlArrayType<T, Tsig>::ParseText(T* pBuf, icUInt32Number nSize, const char *szText)
731 {
732 icUInt32Number n = 0, b;
733 bool bInNum = false;
734 char num[256];
735
736 while (*szText && n<nSize) {
737 if (icIsNumChar(*szText)) {
738 if (!bInNum) {
739 bInNum = true;
740 b=0;
741 }
742 num[b] = *szText;
743
744 if (b+2<sizeof(num))
745 b++;
746 }
747 else if (bInNum) {
748 num[b] = 0;
749 pBuf[n] = (T)atof(num);
750 n++;
751 bInNum = false;
752 }
753 szText++;
754 }
755 if (bInNum) {
756 num[b] = 0;
757 pBuf[n] = (T)atof(num);
758 n++;
759 }
760
761 return n;
762 }
763
764 template <class T, icTagTypeSignature Tsig>
ParseArray(T * pBuf,icUInt32Number nSize,xmlNode * pNode)765 bool CIccXmlArrayType<T, Tsig>::ParseArray(T* pBuf, icUInt32Number nSize, xmlNode *pNode)
766 {
767 icUInt32Number n;
768 if (Tsig==icSigFloatArrayType) {
769 n = icXmlNodeCount(pNode, "f");
770
771 if (!n) {
772 if (pNode->type!=XML_TEXT_NODE || !pNode->content)
773 return false;
774
775 n = ParseTextCount((const char*)pNode->content);
776 if (!n || n>nSize)
777 return false;
778
779 ParseText(pBuf, n, (const char*)pNode->content);
780 }
781 else {
782 if (n>nSize)
783 return false;
784
785 icUInt32Number i;
786 for (i=0; i<nSize && pNode; pNode = pNode->next) {
787 if (pNode->type == XML_ELEMENT_NODE &&
788 !icXmlStrCmp(pNode->name, "f") &&
789 pNode->children &&
790 pNode->children->content) {
791 float f;
792 sscanf((const char *)(pNode->children->content), "%f", &f);
793 pBuf[i] = (T)f;
794 i++;
795 }
796 }
797 }
798 }
799 else {
800 n = icXmlNodeCount(pNode, "n");
801
802 if (!n) {
803 if (pNode->type!=XML_TEXT_NODE || !pNode->content)
804 return false;
805
806 n = ParseTextCount((const char *)pNode->content);
807 if (!n || n>nSize)
808 return false;
809
810 n = ParseText(pBuf, n, (const char *)pNode->content);
811 }
812 else {
813 if (n>nSize)
814 return false;
815
816 icUInt32Number i;
817 for (i=0; i<nSize && pNode; pNode = pNode->next) {
818 if (pNode->type == XML_ELEMENT_NODE &&
819 !icXmlStrCmp(pNode->name, "n") &&
820 pNode->children &&
821 pNode->children->content) {
822 pBuf[i] = (T)atol((const char *)(pNode->children->content));
823 i++;
824 }
825 }
826 }
827 }
828 return nSize==n;
829 }
830
831
832 template <class T, icTagTypeSignature Tsig>
SetSize(icUInt32Number nSize)833 bool CIccXmlArrayType<T, Tsig>::SetSize(icUInt32Number nSize)
834 {
835 if (m_pBuf) {
836 free(m_pBuf);
837 }
838 m_pBuf = (T*)malloc(nSize * sizeof(T));
839 if (!m_pBuf) {
840 m_nSize = 0;
841 return false;
842 }
843 m_nSize = nSize;
844
845 return true;
846 }
847
848 //Make sure typedef classes get built
849 template class CIccXmlArrayType<icUInt8Number, icSigUInt8ArrayType>;
850 template class CIccXmlArrayType<icUInt16Number, icSigUInt16ArrayType>;
851 template class CIccXmlArrayType<icUInt32Number, icSigUInt32ArrayType>;
852 template class CIccXmlArrayType<icFloatNumber, icSigFloatArrayType>;
853
854
icGetRenderingIntentValue(icChar * szRenderingIntent)855 const icRenderingIntent icGetRenderingIntentValue (icChar *szRenderingIntent)
856 {
857 if (szRenderingIntent == "Perceptual")
858 return icPerceptual;
859 else if (szRenderingIntent == "Media-relative colorimetric")
860 return icRelativeColorimetric;
861 else if (szRenderingIntent == "Saturation")
862 return icSaturation;
863 else if (szRenderingIntent == "ICC-absolute colorimetric")
864 return icAbsoluteColorimetric;
865
866 return icPerceptual;
867 }
868
icGetTagSigTypeName(icTagTypeSignature tagSig)869 const icChar* icGetTagSigTypeName(icTagTypeSignature tagSig)
870 {
871 //loop through the list of all tag signatures
872 for (int i=0; i<tagSignatureMapSize; i++) {
873 if ( tagSignatureMap[i].tagSig == tagSig )
874 return tagSignatureMap[i].szTagType;
875 }
876
877 // if the tag signature is not found, it is a custom type.
878 return "PrivateType";
879 }
880
icGetTypeNameTagSig(const icChar * szTagType)881 const icTagTypeSignature icGetTypeNameTagSig(const icChar* szTagType)
882 {
883 //loop through the list of all tag signatures
884 for (int i=0; i<tagSignatureMapSize; i++) {
885 if (!strcmp((const char*)tagSignatureMap[i].szTagType, szTagType))
886 return tagSignatureMap[i].tagSig;
887 }
888
889 // if the tag signature is not found, it is a custom type.
890 return icSigUnknownType;
891 }
892
icGetNamedStandardObserverValue(const icChar * str)893 icStandardObserver icGetNamedStandardObserverValue(const icChar* str)
894 {
895 if (!strcmp(str, "Unknown observer"))
896 return icStdObsUnknown;
897
898 if (!strcmp(str, "CIE 1931 standard colorimetric observer"))
899 return icStdObs1931TwoDegrees;
900
901 if (!strcmp(str, "CIE 1964 standard colorimetric observer"))
902 return icStdObs1964TenDegrees;
903
904 return icStdObsUnknown;
905 }
906
907
icGeNamedtMeasurementGeometryValue(const icChar * str)908 icMeasurementGeometry icGeNamedtMeasurementGeometryValue(const icChar* str)
909 {
910 if (!strcmp(str, "Geometry Unknown"))
911 return icGeometryUnknown;
912
913 if (!strcmp(str, "Geometry 0-45 or 45-0"))
914 return icGeometry045or450;
915
916 if (!strcmp(str, "Geometry 0-d or d-0"))
917 return icGeometry0dord0;
918
919 if (!strcmp(str, "Max Geometry"))
920 return icMaxEnumGeometry;
921
922 return icGeometryUnknown;
923 }
924
icGetNamedMeasurementFlareValue(const icChar * str)925 icMeasurementFlare icGetNamedMeasurementFlareValue(const icChar * str)
926 {
927 if (!strcmp(str, "Flare 0"))
928 return icFlare0;
929
930 if (!strcmp(str, "Flare 100"))
931 return icFlare100;
932
933 if (!strcmp(str, "Max Flare"))
934 return icMaxEnumFlare;
935
936 return icFlare0;
937 }
938
icGetIlluminantValue(const icChar * str)939 icIlluminant icGetIlluminantValue(const icChar* str)
940 {
941 if (!strcmp(str, "Illuminant Unknown"))
942 return icIlluminantUnknown;
943
944 if (!strcmp(str, "Illuminant D50"))
945 return icIlluminantD50;
946
947 if (!strcmp(str, "Illuminant D65"))
948 return icIlluminantD65;
949
950 if (!strcmp(str, "Illuminant D93"))
951 return icIlluminantD93;
952
953 if (!strcmp(str, "Illuminant F2"))
954 return icIlluminantF2;
955
956 if (!strcmp(str, "Illuminant D55"))
957 return icIlluminantD55;
958
959 if (!strcmp(str, "Illuminant A"))
960 return icIlluminantA;
961
962 if (!strcmp(str, "Illuminant EquiPowerE"))
963 return icIlluminantEquiPowerE;
964
965 if (!strcmp(str, "Illuminant F8"))
966 return icIlluminantF8;
967
968 return icIlluminantUnknown;
969 }
970
icGetStandardObserverName(icStandardObserver str)971 const icChar* icGetStandardObserverName(icStandardObserver str)
972 {
973 switch (str) {
974 case icStdObsUnknown:
975 return "Unknown Observer";
976
977 case icStdObs1931TwoDegrees:
978 return "CIE 1931 standard colorimetric observer";
979
980 case icStdObs1964TenDegrees:
981 return "CIE 1964 standard colorimetric observer";
982
983 default:
984 return "Unknown Observer";
985 }
986 }
987
icGetDateTimeValue(const icChar * str)988 icDateTimeNumber icGetDateTimeValue(const icChar* str)
989 {
990 icDateTimeNumber dateTime;
991
992 if (!stricmp(str, "Now")) {
993 struct tm *newtime;
994 time_t long_time;
995
996 time( &long_time ); /* Get time as long integer. */
997 newtime = gmtime( &long_time );
998
999 dateTime.year = newtime->tm_year+1900;
1000 dateTime.month = newtime->tm_mon+1;
1001 dateTime.day = newtime->tm_mday;
1002 dateTime.hours = newtime->tm_hour;
1003 dateTime.minutes = newtime->tm_min;
1004 dateTime.seconds = newtime->tm_sec;
1005
1006 }
1007 else {
1008 unsigned int day=0, month=0, year=0, hours=0, minutes=0, seconds=0;
1009
1010 sscanf(str, "%d-%02d-%02dT%02d:%02d:%02d", &year, &month, &day, &hours, &minutes, &seconds);
1011
1012 dateTime.year = year;
1013 dateTime.month = month;
1014 dateTime.day = day;
1015 dateTime.hours = hours;
1016 dateTime.minutes = minutes;
1017 dateTime.seconds = seconds;
1018 }
1019
1020 return dateTime;
1021 }
1022
icGetChildText(xmlNode * pNode)1023 const icChar *icGetChildText(xmlNode *pNode)
1024 {
1025 if (pNode && pNode->children && pNode->content)
1026 return (const char*)pNode->content;
1027 return "";
1028 }
1029
icGetDeviceAttrValue(xmlNode * pNode)1030 icUInt64Number icGetDeviceAttrValue(xmlNode *pNode)
1031 {
1032 icUInt64Number devAttr = 0;
1033 xmlAttr *attr = icXmlFindAttr(pNode, "ReflectiveOrTransparency");
1034 if (attr && !strcmp(icXmlAttrValue(attr), "transparency")) {
1035 devAttr |= icTransparency;
1036 }
1037
1038 attr = icXmlFindAttr(pNode, "GlossyOrMatte");
1039 if (attr && !strcmp(icXmlAttrValue(attr), "matte")) {
1040 devAttr |= icMatte;
1041 }
1042
1043 attr = icXmlFindAttr(pNode, "MediaPolarity");
1044 if (attr && !strcmp(icXmlAttrValue(attr), "negative")) {
1045 devAttr |= icMediaNegative;
1046 }
1047
1048 attr = icXmlFindAttr(pNode, "MediaColour");
1049 if (attr && !strcmp(icXmlAttrValue(attr), "blackAndWhite")) {
1050 devAttr |= icMediaBlackAndWhite;
1051 }
1052
1053 attr = icXmlFindAttr(pNode, "VendorSpecific");
1054 if (attr) {
1055 icUInt64Number vendor;
1056 sscanf(icXmlAttrValue(attr), "%I64x", &vendor);
1057 devAttr |= vendor;
1058 }
1059
1060 return devAttr;
1061 }
1062
icGetColorantValue(const icChar * str)1063 icColorantEncoding icGetColorantValue(const icChar* str)
1064 {
1065 if (!strcmp(str, "ITU-R BT.709"))
1066 return icColorantITU;
1067
1068 if (!strcmp(str, "SMPTE RP145-1994"))
1069 return icColorantSMPTE;
1070
1071 if (!strcmp(str, "EBU Tech.3213-E"))
1072 return icColorantEBU;
1073
1074 if (!strcmp(str, "P22"))
1075 return icColorantP22;
1076
1077 return icColorantUnknown;
1078 }
1079
icGetMeasurementValue(const icChar * str)1080 icMeasurementUnitSig icGetMeasurementValue(const icChar* str)
1081 {
1082 if (!strcmp(str, "Status A"))
1083 return icSigStatusA;
1084
1085 if (!strcmp(str, "Status E"))
1086 return icSigStatusE;
1087
1088 if (!strcmp(str, "Status I"))
1089 return icSigStatusI;
1090
1091 if (!strcmp(str, "Status T"))
1092 return icSigStatusT;
1093
1094 if (!strcmp(str, "Status M"))
1095 return icSigStatusM;
1096
1097 if (!strcmp(str, "DIN with no polarizing filter"))
1098 return icSigDN;
1099
1100 if (!strcmp(str, "DIN with polarizing filter"))
1101 return icSigDNP;
1102
1103 if (!strcmp(str, "Narrow band DIN with no polarizing filter"))
1104 return icSigDNN;
1105
1106 if (!strcmp(str, "Narrow band DIN with polarizing filter"))
1107 return icSigDNNP;
1108
1109 return icSigStatusA;
1110 }
1111
icGetDeviceAttrName(icUInt64Number devAttr)1112 const std::string icGetDeviceAttrName(icUInt64Number devAttr)
1113 {
1114 char line[256];
1115 std::string xml;
1116
1117 if (devAttr & icTransparency)
1118 sprintf(line, "<DeviceAttributes ReflectiveOrTransparency=\"transparency\"");
1119 else
1120 sprintf(line, "<DeviceAttributes ReflectiveOrTransparency=\"reflective\"");
1121 xml += line;
1122
1123
1124 if (devAttr & icMatte)
1125 sprintf(line, " GlossyOrMatte=\"matte\"");
1126 else
1127 sprintf(line, " GlossyOrMatte=\"glossy\"");
1128 xml += line;
1129
1130
1131 if (devAttr & icMediaNegative)
1132 sprintf(line, " MediaPolarity=\"negative\"");
1133 else
1134 sprintf(line, " MediaPolarity=\"positive\"");
1135 xml += line;
1136
1137 if (devAttr & icMediaBlackAndWhite)
1138 sprintf(line, " MediaColour=\"blackAndwhite\"");
1139 else
1140 sprintf(line, " MediaColour=\"colour\"");
1141 xml += line;
1142
1143 icUInt64Number otherAttr = ~((icUInt64Number)icTransparency|icMatte|icMediaNegative|icMediaBlackAndWhite);
1144
1145 if (devAttr & otherAttr) {
1146 sprintf(line, " VendorSpecific=\"%016I64x\"", devAttr & otherAttr);
1147 xml += line;
1148 }
1149
1150 xml += "/>\n";
1151
1152 return xml;
1153 }
1154
icGetHeaderFlagsName(icUInt32Number flags)1155 const std::string icGetHeaderFlagsName(icUInt32Number flags)
1156 {
1157 char line[256];
1158 std::string xml;
1159
1160 if (flags & icEmbeddedProfileTrue)
1161 sprintf(line, "<ProfileFlags EmbeddedInFile=\"true\" ");
1162 else
1163 sprintf(line, "<ProfileFlags EmbeddedInFile=\"false\" ");
1164 xml += line;
1165
1166 if (flags & icUseWithEmbeddedDataOnly)
1167 sprintf(line, "UseWithEmbeddedDataOnly=\"true\"");
1168 else
1169 sprintf(line, "UseWithEmbeddedDataOnly=\"false\"");
1170 xml += line;
1171
1172 icUInt32Number otherFlags = ~(icEmbeddedProfileTrue|icUseWithEmbeddedDataOnly);
1173
1174 if (flags & otherFlags) {
1175 sprintf(line, " VendorFlags=\"%08x\"", flags & otherFlags);
1176 xml += line;
1177 }
1178
1179 xml += "/>\n";
1180
1181 return xml;
1182 }
1183
icGetPadSpace(double value)1184 const std::string icGetPadSpace(double value)
1185 {
1186 std::string space = "";
1187 if ( value >=0 && value < 10)
1188 space = " ";
1189 if ( value >=10 && value < 100)
1190 space = " ";
1191 if ( value >=100 && value < 1000 )
1192 space = " ";
1193
1194 return space;
1195 }
1196
1197