Hoyt's FORK of DemoIccMAX 2.1.17.hoyt
Documentation for Hoyt's FORK of DemoIccMAX
Loading...
Searching...
No Matches
IccMpeXml.cpp
Go to the documentation of this file.
1/** @file
2 File: IccMpeXml.cpp
3
4 Contains: Implementation of MultiProcessElementType Element XML
5 conversion functionality
6
7 Version: V1
8
9 Copyright: (c) see ICC Software License
10*/
11
12/*
13 * The ICC Software License, Version 0.2
14 *
15 *
16 * Copyright (c) 2003-2012 The International Color Consortium. All rights
17 * reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 *
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 *
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in
28 * the documentation and/or other materials provided with the
29 * distribution.
30 *
31 * 3. In the absence of prior written permission, the names "ICC" and "The
32 * International Color Consortium" must not be used to imply that the
33 * ICC organization endorses or promotes products derived from this
34 * software.
35 *
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
41 * ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the The International Color Consortium.
53 *
54 *
55 * Membership in the ICC is encouraged when this software is used for
56 * commercial purposes.
57 *
58 *
59 * For more information on The International Color Consortium, please
60 * see <http://www.color.org/>.
61 *
62 *
63 */
64#include "IccTagXml.h"
65#include "IccMpeXml.h"
66#include "IccUtilXml.h"
67#include "IccIoXml.h"
68#include "IccCAM.h"
69
70#include <cstring> /* C strings strcpy, memcpy ... */
71
72#ifdef WIN32
73#include <windows.h>
74#ifdef GetClassName
75#undef GetClassName
76#endif
77#endif
78
79#ifdef USEREFICCMAXNAMESPACE
80namespace refIccMAX {
81#endif
82
83bool CIccMpeXmlUnknown::ToXml(std::string &xml, std::string blanks/* = ""*/)
84{
85 icUInt8Number *m_ptr = m_pData;
86
87 char line[256];
88 char buf[256];
89 char fix[256];
90 sprintf(line, "<UnknownElement Type=\"%s\" InputChannels=\"%d\" OutputChannels=\"%d\"",
91 icFixXml(fix, icGetSigStr(buf, GetType())), NumInputChannels(), NumOutputChannels());
92 xml += blanks + line;
93
94 if (m_nReserved) {
95 sprintf(line, " Reserved=\"%u\"", m_nReserved);
96 xml += buf;
97 }
98 xml += ">\n";
99
100 icXmlDumpHexData(xml, blanks + " ", m_pData, m_nSize);
101
102 xml += blanks + "</UnknownElement>\n";
103 return true;
104}
105
106
107bool CIccMpeXmlUnknown::ParseXml(xmlNode *pNode, std::string &parseStr)
108{
109 SetType((icElemTypeSignature)icXmlStrToSig(icXmlAttrValue(pNode, "type")));
110 SetChannels(atoi(icXmlAttrValue(pNode, "InputChannels")), atoi(icXmlAttrValue(pNode, "OutputChannels")));
111
112 if (pNode->children && pNode->children->type == XML_TEXT_NODE && pNode->children->content) {
113 icUInt32Number nSize = icXmlGetHexDataSize((const char *)pNode->children->content);
114
115 if (!SetDataSize(nSize, false))
116 return false;
117
118 icXmlGetHexData(m_pData, (const char *)pNode->children->content, nSize);
119 }
120 else {
121 SetDataSize(0);
122 }
123 return true;
124}
125
126
128{
129public:
131
132 bool ToXml(std::string &xml, std::string blanks/* = ""*/);
133 bool ParseXml(xmlNode *pNode, std::string &parseStr);
134};
135
136static char* icSegPos(char *buf, icFloatNumber pos)
137{
138 if (pos==icMinFloat32Number)
139 strcpy(buf, "-infinity");
140 else if (pos==icMaxFloat32Number)
141 strcpy(buf, "+infinity");
142 else
143 sprintf(buf, "%.8" ICFLOATSFX, pos);
144
145 return buf;
146}
147
149{
150 if (!strncmp(str, "-inf", 4)) {
151 return icMinFloat32Number;
152 }
153 if (!strncmp(str, "+inf", 4)) {
154 return icMaxFloat32Number;
155 }
156
157 return (icFloatNumber)atof(str);
158}
159
160
161bool CIccFormulaCurveSegmentXml::ToXml(std::string &xml, std::string blanks)
162{
163 char buf[256];
164 char line[256];
165
166 sprintf(line, "<FormulaSegment Start=\"%s\"", icSegPos(buf, m_startPoint));
167 xml += blanks + line;
168
169 sprintf(line, " End=\"%s\"",icSegPos(buf, m_endPoint));
170 xml += line;
171
172 sprintf(line, " FunctionType=\"%d\"", m_nFunctionType);
173 xml += line;
174
175 if (m_nReserved) {
176 sprintf(line, " Reserved=\"%d\"", m_nReserved);
177 xml += line;
178 }
179 if (m_nReserved2) {
180 sprintf(line, " Reserved2=\"%d\"", m_nReserved2);
181 xml += line;
182 }
183 xml += ">\n";
184
185 CIccFloatArray::DumpArray(xml, blanks+" ", m_params, m_nParameters, icConvertFloat, 8);
186
187 xml += blanks + "</FormulaSegment>\n";
188
189 return true;
190}
191
192
193bool CIccFormulaCurveSegmentXml::ParseXml(xmlNode *pNode, std::string &parseStr)
194{
195 xmlAttr *funcType = icXmlFindAttr(pNode, "FunctionType");
196
197 if (!funcType) {
198 parseStr += "Bad FunctionType in Formula Segment\n";
199 return false;
200 }
201
202 m_nReserved2 = atoi(icXmlAttrValue(pNode, "Reserved2"));
203 m_nFunctionType = atoi(icXmlAttrValue(funcType));
204
205
206 switch(m_nFunctionType) {
207 case 0x0000:
208 m_nParameters = 4;
209 break;
210
211 case 0x0001:
212 case 0x0002:
213 case 0x0003:
214 case 0x0004:
215 m_nParameters = 5;
216 break;
217
218 case 0x0005:
219 case 0x0007:
220 m_nParameters = 6;
221 break;
222
223 case 0x0006:
224 m_nParameters = 7;
225 break;
226
227 default:
228 parseStr += "Unsupported FunctionType value in Formula Segment\n";
229 return false;
230 }
231
232 CIccFloatArray args;
233
234 if (!args.ParseArray(pNode->children))
235 return false;
236
237 if (args.GetSize()<m_nParameters)
238 return false;
239
240 if (m_params) {
241 free(m_params);
242 }
243
244 if (m_nParameters) {
245 m_params = (icFloatNumber*)malloc(m_nParameters * sizeof(icFloatNumber));
246 if (!m_params)
247 return false;
248
249 memcpy(m_params, args.GetBuf(), m_nParameters * sizeof(icFloatNumber));
250 }
251 else
252 m_params = NULL;
253
254 return true;
255}
256
257
259{
260public:
262
263 bool ToXml(std::string &xml, std::string blanks/* = ""*/);
264 bool ParseXml(xmlNode *pNode, std::string &parseStr);
265};
266
267bool CIccSampledCurveSegmentXml::ToXml(std::string &xml, std::string blanks)
268{
269 char buf[256];
270 char line[256];
271
272 sprintf(line, "<SampledSegment Start=\"%s\"", icSegPos(buf, m_startPoint));
273 xml += blanks + line;
274
275 sprintf(line, " End=\"%s\">\n",icSegPos(buf, m_endPoint));
276 xml += line;
277
278 CIccFloatArray::DumpArray(xml, blanks+" ", m_pSamples, m_nCount, icConvertFloat, 8);
279
280 xml += blanks + "</SampledSegment>\n";
281
282 return true;
283}
284
285
286bool CIccSampledCurveSegmentXml::ParseXml(xmlNode *pNode, std::string &parseStr)
287{
288 const char *filename = icXmlAttrValue(pNode, "Filename");
289
290 // file exists
291 if (filename[0]) {
292 CIccIO *file = IccOpenFileIO(filename, "rb");
293 if (!file){
294 parseStr += "Error! - File '";
295 parseStr += filename;
296 parseStr +="' not found.\n";
297 delete file;
298 return false;
299 }
300
301 const char *format = icXmlAttrValue(pNode, "Format");
302
303 // format is text
304 if (!strcmp(format, "text")) {
305 icUInt32Number num = file->GetLength();
306 char *buf = (char *) new char[num];
307
308 if (!buf) {
309 perror("Memory Error");
310 parseStr += "'";
311 parseStr += filename;
312 parseStr += "' may not be a valid text file.\n";
313 delete buf;
314 delete file;
315 return false;
316 }
317
318 if (file->Read8(buf, num) !=num) {
319 perror("Read-File Error");
320 parseStr += "'";
321 parseStr += filename;
322 parseStr += "' may not be a valid text file.\n";
323 delete buf;
324 delete file;
325 return false;
326 }
327
328 CIccFloatArray data;
329
330 //if (!data.ParseTextArray(buf)) {
331 if (!data.ParseTextArrayNum(buf, num, parseStr)){
332 parseStr += "File '";
333 parseStr += filename;
334 parseStr += "' is not a valid text file.\n";
335 SetSize(0);
336 delete buf;
337 delete file;
338 return false;
339 }
340
341 else {
342 SetSize(data.GetSize());
343 icFloatNumber *src = data.GetBuf();
344 icFloatNumber *dst = m_pSamples;
345
347 for (i=0; i<data.GetSize(); i++) {
348 *dst = *src;
349 dst++;
350 src++;
351 }
352 }
353
354 delete buf;
355 delete file;
356 return true;
357
358 }
359 // format is binary
360 else if (!strcmp(format, "binary")) {
361 const char *order = icXmlAttrValue(pNode, "Endian");
362 bool little_endian = !strcmp(order, "little");
363
365 xmlAttr *attr = icXmlFindAttr(pNode, "StorageType");
366 if (attr) {
367 storageType = (icUInt16Number)atoi(icXmlAttrValue(attr));
368 }
369
370 if (storageType == icValueTypeUInt8){
371 icUInt32Number num = file->GetLength();
372 icUInt8Number value;
373
374 SetSize(num);
375 icFloatNumber *dst = m_pSamples;
377 for (i=0; i<num; i++) {
378 if (!file->Read8(&value)) {
379 perror("Read-File Error");
380 parseStr += "'";
381 parseStr += filename;
382 parseStr += "' may not be a valid binary file.\n";
383 delete file;
384 return false;
385 }
386 *dst++ = (icFloatNumber)value / 255.0f;
387 }
388 delete file;
389 return true;
390 }
391 else if (storageType == icValueTypeUInt16){
392 icUInt32Number num = file->GetLength() / sizeof(icUInt16Number);
393 icUInt16Number value;
394 icUInt8Number *m_ptr = (icUInt8Number*)&value;
395
396 SetSize(num);
397 icFloatNumber *dst = m_pSamples;
399 for (i=0; i<num; i++) {
400 if (!file->Read16(&value)) { //assumes data is big endian
401 perror("Read-File Error");
402 parseStr += "'";
403 parseStr += filename;
404 parseStr += "' may not be a valid binary file.\n";
405 delete file;
406 return false;
407 }
408#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
409 if (little_endian) {
410#else
411 if (!little_endian) {
412#endif
413 icUInt8Number t = m_ptr[0];
414 m_ptr[0] = m_ptr[1];
415 m_ptr[1] = t;
416 }
417 *dst++ = (icFloatNumber)value / 65535.0f;
418 }
419 delete file;
420 return true;
421 }
422 else if (storageType == icValueTypeFloat16){
423 icUInt32Number num = file->GetLength() / sizeof(icFloat16Number);
424 icFloat16Number value;
425 icUInt8Number *m_ptr = (icUInt8Number*)&value;
426
427 SetSize(num);
428 icFloatNumber *dst = m_pSamples;
430 for (i=0; i<num; i++) {
431 if (!file->Read16(&value)) { //assumes data is big endian
432 perror("Read-File Error");
433 parseStr += "'";
434 parseStr += filename;
435 parseStr += "' may not be a valid binary file.\n";
436 delete file;
437 return false;
438 }
439#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
440 if (little_endian) {
441#else
442 if (!little_endian) {
443#endif
444 icUInt8Number t = m_ptr[0];
445 m_ptr[0] = m_ptr[1];
446 m_ptr[1] = t;
447 }
448 *dst++ = icF16toF(value);
449 }
450 delete file;
451 return true;
452 }
453 else if (storageType == icValueTypeFloat32) {
454 icUInt32Number num = file->GetLength()/sizeof(icFloat32Number);
455 icFloat32Number value;
456 icUInt8Number *m_ptr = (icUInt8Number*)&value;
457
458 SetSize(num);
459 icFloatNumber *dst = m_pSamples;
460
462 for (i=0; i<num; i++) {
463 if (!file->ReadFloat32Float(&value)) { //assumes data is big endian
464 perror("Read-File Error");
465 parseStr += "'";
466 parseStr += filename;
467 parseStr += "' may not be a valid binary file.\n";
468 delete file;
469 return false;
470 }
471#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
472 if (little_endian) {
473#else
474 if (!little_endian) {
475#endif
476 icUInt8Number tmp;
477 tmp = m_ptr[0]; m_ptr[0] = m_ptr[3]; m_ptr[3] = tmp;
478 tmp = m_ptr[1]; m_ptr[1] = m_ptr[2]; m_ptr[2] = tmp;
479 }
480 *dst++ = value;
481 }
482 delete file;
483 return true;
484 }
485 else { //not 8bit/16bit/float
486 delete file;
487 return false;
488 }
489 }
490 }
491 else {
492 CIccFloatArray samples;
493
494 if (!samples.ParseArray(pNode->children)) {
495 return false;
496 }
497
498 if (!SetSize(samples.GetSize())) {
499 return false;
500 }
501
502 memcpy(m_pSamples, samples.GetBuf(), samples.GetSize() * sizeof(icFloatNumber));
503 }
504
505 return true;
506}
507
508
510{
511public:
513
514 bool ToXml(std::string &xml, std::string blanks/* = ""*/);
515 bool ParseXml(xmlNode *pNode, std::string &parseStr);
516};
517
518bool CIccSampledCalculatorCurveXml::ToXml(std::string &xml, std::string blanks)
519{
520 char line[256];
521
522 xml += blanks;
523 sprintf(line, "<SampledCalculatorCurve FirstEntry=\"" icXmlFloatFmt "\"", m_firstEntry);
524 xml += line;
525
526 sprintf(line, " LastEntry=\"" icXmlFloatFmt "\"", m_lastEntry);
527 xml += line;
528
529 sprintf(line, " ExtensionType=\"%u\"", m_extensionType);
530 xml += line;
531
532 sprintf(line, " DesiredSize=\"%u\">\n", m_nDesiredSize);
533 xml += line;
534
535 if (m_nReserved2) {
536 sprintf(line, " Reservered2=\"%u\">\n", m_nReserved2);
537 xml += line;
538 }
539
540 if (m_pCalc && !strcmp(m_pCalc->GetClassName(), "CIccMpeXmlCalculator")) {
541 CIccMpeXmlCalculator *pXmlCalc = (CIccMpeXmlCalculator*)m_pCalc;
542 if (!pXmlCalc->ToXml(xml, blanks + " "))
543 return false;
544 }
545 else {
546 return false;
547 }
548
549 xml += blanks + "</SampledCalculatorCurve>\n";
550
551 return true;
552}
553
554
555bool CIccSampledCalculatorCurveXml::ParseXml(xmlNode *pNode, std::string &parseStr)
556{
557 xmlAttr *attr = icXmlFindAttr(pNode, "FirstEntry");
558
559 if (!attr) {
560 parseStr += "Bad FirstEntry in Sampled Calculator Curve\n";
561 return false;
562 }
563
564 m_firstEntry = (icFloatNumber)atof(icXmlAttrValue(attr));
565
566 attr = icXmlFindAttr(pNode, "LastEntry");
567
568 if (!attr) {
569 parseStr += "Bad LastEntry in Sampled Calculator Curve\n";
570 return false;
571 }
572
573 m_lastEntry = (icFloatNumber)atof(icXmlAttrValue(attr));
574
575 attr = icXmlFindAttr(pNode, "DesiredSize");
576
577 if (!attr) {
578 parseStr += "Bad DesiredSize in Sampled Calculator Curve\n";
579 return false;
580 }
581
582 m_nDesiredSize = (icUInt32Number)atoi(icXmlAttrValue(attr));
583
584 xmlNode *pCalcNode = icXmlFindNode(pNode->children, "CalculatorElement");
585 if (pCalcNode) {
587
588 if (!pCalc->ParseXml(pCalcNode, parseStr)) {
589 parseStr += "Unable to parse calculator element in Sampled Calculator Curve\n";
590 return false;
591 }
592 m_pCalc = pCalc;
593 }
594 else {
595 parseStr += "Missing Calculator Element in Sampled Calculator Curve\n";
596 return false;
597 }
598
599 return true;
600}
601
602
604{
605public:
607
608 bool ToXml(std::string &xml, std::string blanks/* = ""*/);
609 bool ParseXml(xmlNode *pNode, std::string &parseStr);
610};
611
612bool CIccSinglSampledeCurveXml::ToXml(std::string &xml, std::string blanks)
613{
614 char line[256];
615
616 xml += blanks;
617 sprintf(line, "<SingleSampledCurve FirstEntry=\"" icXmlFloatFmt "\"", m_firstEntry);
618 xml += line;
619
620 sprintf(line, " LastEntry=\"" icXmlFloatFmt "\"", m_lastEntry);
621 xml += line;
622
623 sprintf(line, " StorageType=\"%u\"", m_storageType);
624 xml += line;
625
626 sprintf(line, " ExtensionType=\"%u\">\n", m_extensionType);
627 xml += line;
628
629 CIccFloatArray::DumpArray(xml, blanks + " ", m_pSamples, m_nCount, icConvertFloat, 8);
630
631 xml += blanks + "</SingleSampledCurve>\n";
632
633 return true;
634}
635
636
637bool CIccSinglSampledeCurveXml::ParseXml(xmlNode *pNode, std::string &parseStr)
638{
639 xmlAttr *attr = icXmlFindAttr(pNode, "FirstEntry");
640
641 if (!attr) {
642 parseStr += "Bad FirstEntry in Simple Sampled Segment\n";
643 return false;
644 }
645
646 m_firstEntry = (icFloatNumber)atof(icXmlAttrValue(attr));
647
648 attr = icXmlFindAttr(pNode, "LastEntry");
649
650 if (!attr) {
651 parseStr += "Bad LastEntry in Simple Sampled Segment\n";
652 return false;
653 }
654
655 m_lastEntry = (icFloatNumber)atof(icXmlAttrValue(attr));
656
657 m_storageType = icValueTypeFloat32;
658 attr = icXmlFindAttr(pNode, "StorageType");
659 if (attr) {
660 m_storageType = (icUInt16Number)atoi(icXmlAttrValue(attr));
661 }
662
663 m_extensionType = icClipSingleSampledCurve;
664 attr = icXmlFindAttr(pNode, "ExtensionType");
665 if (attr) {
666 m_extensionType = (icUInt16Number)atoi(icXmlAttrValue(attr));
667 }
668
669 const char *filename = icXmlAttrValue(pNode, "Filename");
670
671 // file exists
672 if (filename[0]) {
673 CIccIO *file = IccOpenFileIO(filename, "rb");
674 if (!file) {
675 parseStr += "Error! - File '";
676 parseStr += filename;
677 parseStr += "' not found.\n";
678 delete file;
679 return false;
680 }
681
682 const char *format = icXmlAttrValue(pNode, "Format");
683
684 // format is text
685 if (!strcmp(format, "text")) {
686 icUInt32Number num = file->GetLength();
687 char *buf = (char *) new char[num];
688
689 if (!buf) {
690 perror("Memory Error");
691 parseStr += "'";
692 parseStr += filename;
693 parseStr += "' may not be a valid text file.\n";
694 free(buf);
695 delete file;
696 return false;
697 }
698
699 if (file->Read8(buf, num) != num) {
700 perror("Read-File Error");
701 parseStr += "'";
702 parseStr += filename;
703 parseStr += "' may not be a valid text file.\n";
704 free(buf);
705 delete file;
706 return false;
707 }
708
709 // lut8type
710 if (m_storageType == icValueTypeUInt8) {
711 CIccUInt8Array data;
712
713 //if (!data.ParseTextArray(buf)) {
714 if (!data.ParseTextArrayNum(buf, num, parseStr)) {
715 parseStr += "File '";
716 parseStr += filename;
717 parseStr += "' is not a valid text file.\n";
718 SetSize(0);
719 free(buf);
720 delete file;
721 return false;
722 }
723
724 else {
725 SetSize(data.GetSize());
726 icUInt8Number *src = data.GetBuf();
727 icFloatNumber *dst = m_pSamples;
728
730 for (i = 0; i < data.GetSize(); i++) {
731 *dst = (icFloatNumber)(*src) / 255.0f;
732 dst++;
733 src++;
734 }
735
736 //if (i!=256) {
737 //printf("Error! - Input/Output table does not have 256 entries.\n");
738 //SetSize(0);
739 //return false;
740 //}
741 delete file;
742 return true;
743 }
744 }
745
746 //lut16type
747 else if (m_storageType == icValueTypeUInt16) {
748 CIccUInt16Array data;
749
750 //if (!data.ParseTextArray(buf)) {
751 if (!data.ParseTextArrayNum(buf, num, parseStr)) {
752 parseStr += "File '";
753 parseStr += filename;
754 parseStr += "' is not a valid text file.\n";
755 SetSize(0);
756 free(buf);
757 delete file;
758 return false;
759 }
760
761 else {
762 SetSize(data.GetSize());
763
764 icUInt16Number *src = data.GetBuf();
765 icFloatNumber *dst = m_pSamples;
766
768 for (i = 0; i < data.GetSize(); i++) {
769 *dst = (icFloatNumber)(*src) / 65535.0f;
770 dst++;
771 src++;
772 }
773 }
774 delete file;
775 return true;
776 }
777
778 //float type
779 else if (m_storageType == icValueTypeFloat32) {
780 CIccFloatArray data;
781
782 //if (!data.ParseTextArray(buf)) {
783 if (!data.ParseTextArrayNum(buf, num, parseStr)) {
784 parseStr += "File '";
785 parseStr += filename;
786 parseStr += "' is not a valid text file.\n";
787 SetSize(0);
788 free(buf);
789 delete file;
790 return false;
791 }
792
793 else {
794 SetSize(data.GetSize());
795 icFloatNumber *src = data.GetBuf();
796 icFloatNumber *dst = m_pSamples;
797
799 for (i = 0; i < data.GetSize(); i++) {
800 *dst = *src;
801 dst++;
802 src++;
803 }
804 }
805 delete file;
806 return true;
807 }
808 else {
809 delete file;
810 return false;
811 }
812 }
813 // format is binary
814 else if (!strcmp(format, "binary")) {
815 const char *order = icXmlAttrValue(pNode, "Endian");
816 bool little_endian = !strcmp(order, "little");
817
818 if (m_storageType == icValueTypeUInt8) {
819 icUInt32Number num = file->GetLength();
820 icUInt8Number value;
821
822 SetSize(num);
823 icFloatNumber *dst = m_pSamples;
825 for (i = 0; i < num; i++) {
826 if (!file->Read8(&value)) {
827 perror("Read-File Error");
828 parseStr += "'";
829 parseStr += filename;
830 parseStr += "' may not be a valid binary file.\n";
831 delete file;
832 return false;
833 }
834 *dst++ = (icFloatNumber)value / 255.0f;
835 }
836 delete file;
837 return true;
838 }
839 else if (m_storageType == icValueTypeUInt16) {
840 icUInt32Number num = file->GetLength() / sizeof(icUInt16Number);
841 icUInt16Number value;
842 icUInt8Number *m_ptr = (icUInt8Number*)&value;
843
844 SetSize(num);
845 icFloatNumber *dst = m_pSamples;
847 for (i = 0; i < num; i++) {
848 if (!file->Read16(&value)) { //assumes data is big endian
849 perror("Read-File Error");
850 parseStr += "'";
851 parseStr += filename;
852 parseStr += "' may not be a valid binary file.\n";
853 delete file;
854 return false;
855 }
856#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
857 if (little_endian) {
858#else
859 if (!little_endian) {
860#endif
861 icUInt8Number t = m_ptr[0];
862 m_ptr[0] = m_ptr[1];
863 m_ptr[1] = t;
864 }
865 *dst++ = (icFloatNumber)value / 65535.0f;
866 }
867 delete file;
868 return true;
869 }
870 else if (m_storageType == icValueTypeFloat16) {
871 icUInt32Number num = file->GetLength() / sizeof(icFloat16Number);
872 icFloat16Number value;
873 icUInt8Number *m_ptr = (icUInt8Number*)&value;
874
875 SetSize(num);
876 icFloatNumber *dst = m_pSamples;
878 for (i = 0; i < num; i++) {
879 if (!file->Read16(&value)) { //assumes data is big endian
880 perror("Read-File Error");
881 parseStr += "'";
882 parseStr += filename;
883 parseStr += "' may not be a valid binary file.\n";
884 delete file;
885 return false;
886 }
887#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
888 if (little_endian) {
889#else
890 if (!little_endian) {
891#endif
892 icUInt8Number t = m_ptr[0];
893 m_ptr[0] = m_ptr[1];
894 m_ptr[1] = t;
895 }
896 *dst++ = icF16toF(value);
897 }
898 delete file;
899 return true;
900 }
901 else if (m_storageType == icValueTypeFloat32) {
902 icUInt32Number num = file->GetLength() / sizeof(icFloat32Number);
903 icFloat32Number value;
904 icUInt8Number *m_ptr = (icUInt8Number*)&value;
905
906 SetSize(num);
907 icFloatNumber *dst = m_pSamples;
908
910 for (i = 0; i < num; i++) {
911 if (!file->ReadFloat32Float(&value)) {
912 perror("Read-File Error");
913 parseStr += "'";
914 parseStr += filename;
915 parseStr += "' may not be a valid binary file.\n";
916 delete file;
917 return false;
918 }
919#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
920 if (little_endian) {
921#else
922 if (!little_endian) {
923#endif
924 icUInt8Number tmp;
925 tmp = m_ptr[0]; m_ptr[0] = m_ptr[3]; m_ptr[3] = tmp;
926 tmp = m_ptr[1]; m_ptr[1] = m_ptr[2]; m_ptr[2] = tmp;
927 }
928 *dst++ = value;
929 }
930 delete file;
931 return true;
932 }
933 else { //not 8bit/16bit/float
934 delete file;
935 return false;
936 }
937 }
938 else {//not text/binary
939 delete file;
940 return false;
941 }
942 }
943 // no file
944 else {
945 CIccFloatArray samples;
946
947 if (!samples.ParseArray(pNode->children)) {
948 return false;
949 }
950
951 if (!SetSize(samples.GetSize())) {
952 return false;
953 }
954
955 memcpy(m_pSamples, samples.GetBuf(), samples.GetSize() * sizeof(icFloatNumber));
956 }
957
958 return true;
959 }
960
961
962bool CIccSegmentedCurveXml::ToXml(std::string &xml, std::string blanks)
963{
964 CIccCurveSegmentList::iterator seg;
965 xml += blanks + "<SegmentedCurve>\n";
966 for (seg = m_list->begin(); seg!=m_list->end(); seg++) {
967 CIccCurveSegment* pSeg = *seg;
968 if (pSeg && pSeg->GetType() == icSigFormulaCurveSeg) {
969 if (!((CIccFormulaCurveSegmentXml*)pSeg)->ToXml(xml, blanks+" "))
970 return false;
971 }
972 else if (pSeg && pSeg->GetType() == icSigSampledCurveSeg) {
973 if (!((CIccSampledCurveSegmentXml*)pSeg)->ToXml(xml, blanks+" "))
974 return false;
975 }
976 else
977 return false;
978 }
979 xml += blanks + "</SegmentedCurve>\n";
980 return true;
981}
982
983
984bool CIccSegmentedCurveXml::ParseXml(xmlNode *pNode, std::string &parseStr)
985{
986 m_list->clear();
987 for (pNode=pNode->children; pNode; pNode=pNode->next) {
988 if (pNode->type == XML_ELEMENT_NODE) {
989 icFloatNumber start = icGetSegPos(icXmlAttrValue(pNode, "Start"));
990 icFloatNumber end = icGetSegPos(icXmlAttrValue(pNode, "End"));
991
992 if (!icXmlStrCmp(pNode->name, "FormulaSegment")) {
994
995 if (!pSegXml->ParseXml(pNode, parseStr)) {
996 parseStr += "Unable to parse FormulaSegment\n";
997 delete pSegXml;
998 return false;
999 }
1000 m_list->push_back(pSegXml);
1001 }
1002 else if (!icXmlStrCmp(pNode->name, "SampledSegment")) {
1003 CIccSampledCurveSegmentXml *pSegXml = new CIccSampledCurveSegmentXml(start, end);
1004
1005 if (!pSegXml->ParseXml(pNode, parseStr)) {
1006 parseStr += "Unable to parse SampledSegment\n";
1007 delete pSegXml;
1008 return false;
1009 }
1010 m_list->push_back(pSegXml);
1011 }
1012 else {
1013 parseStr += "Bad Segment Type\n";
1014 return false;
1015 }
1016 }
1017 }
1018 return true;
1019}
1020
1021
1022static bool ToXmlCurve(std::string& xml, std::string blanks, icCurveSetCurvePtr pCurve)
1023{
1024 if (pCurve->GetType() == icSigSingleSampledCurve) {
1026
1027 if (!(m_ptr->ToXml(xml, blanks + " ")))
1028 return false;
1029 }
1030 else if (pCurve->GetType() == icSigSegmentedCurve) {
1032
1033 if (!(m_ptr->ToXml(xml, blanks + " ")))
1034 return false;
1035 }
1036 else if (pCurve->GetType() == icSigSampledCalculatorCurve) {
1038
1039 if (!(m_ptr->ToXml(xml, blanks + " ")))
1040 return false;
1041 }
1042 else
1043 return false;
1044
1045 return true;
1046}
1047
1048bool CIccMpeXmlCurveSet::ToXml(std::string &xml, std::string blanks/* = ""*/)
1049{
1050 char line[256];
1051 sprintf(line, "<CurveSetElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1052 xml += blanks + line;
1053
1054 if (m_nReserved) {
1055 sprintf(line, " Reserved=\"%u\"", m_nReserved);
1056 xml += line;
1057 }
1058 xml += ">\n";
1059
1060 int i, j;
1061
1062 for (i=0; i<NumInputChannels(); i++) {
1063 CIccCurveSetCurve* curve = m_curve[i];
1064
1065 //check for duplicate curves
1066 for (j = 0; j < i; j++) {
1067 if (m_curve[i] == m_curve[j])
1068 break;
1069 }
1070
1071 //handle case of duplicate curve
1072 if (j < i) {
1073 sprintf(line, "<DuplicateCurve Index=\"%d\"/>\n", j);
1074 xml += blanks + " ";
1075 xml += line;
1076 }
1077 else if (!ToXmlCurve(xml, blanks, m_curve[i]))
1078 return false;
1079 }
1080
1081 xml += blanks + "</CurveSetElement>\n";
1082 return true;
1083}
1084
1085static icCurveSetCurvePtr ParseXmlCurve(xmlNode* pNode, std::string parseStr)
1086{
1087 icCurveSetCurvePtr rv = NULL;
1088
1089 if (!strcmp((const char*)pNode->name, "SegmentedCurve")) {
1091
1092 if (pCurve->ParseXml(pNode, parseStr)) {
1093 rv = pCurve;
1094 }
1095 else
1096 delete pCurve;
1097 }
1098 else if (!strcmp((const char*)pNode->name, "SingleSampledCurve")) {
1100
1101 if (pCurve->ParseXml(pNode, parseStr)) {
1102 rv = pCurve;
1103 }
1104 else
1105 delete pCurve;
1106 }
1107 else if (!strcmp((const char*)pNode->name, "SampledCalculatorCurve")) {
1109
1110 if (pCurve->ParseXml(pNode, parseStr)) {
1111 rv = pCurve;
1112 }
1113 else
1114 delete pCurve;
1115 }
1116
1117 return rv;
1118}
1119
1120
1121bool CIccMpeXmlCurveSet::ParseXml(xmlNode *pNode, std::string &parseStr)
1122{
1123 icUInt16Number nChannels = (icUInt16Number)atoi(icXmlAttrValue(pNode, "InputChannels"));
1124
1125 if (!nChannels || atoi(icXmlAttrValue(pNode, "OutputChannels")) != nChannels) {
1126 parseStr += "Invalid InputChannels or OutputChannels In CurveSetElement\n";
1127 return false;
1128 }
1129
1130 SetSize(nChannels);
1131 int nIndex = 0;
1132 for (pNode = pNode->children, nIndex = 0;
1133 pNode;
1134 pNode=pNode->next) {
1135 if (pNode->type == XML_ELEMENT_NODE) {
1136 if (nIndex >= nChannels) {
1137 return false;
1138 }
1139 else if (!strcmp((const char*)pNode->name, "DuplicateCurve")) {
1140 const char *attr = icXmlAttrValue(pNode, "Index", NULL);
1141
1142 if (attr) {
1143 int nCopyIndex = atoi(attr);
1144 if (nCopyIndex >= 0 && nCopyIndex < nIndex) {
1145 m_curve[nIndex] = m_curve[nCopyIndex];
1146 nIndex++;
1147 }
1148 else {
1149 parseStr += "Invalid index for duplicate CurveSet Curve\n";
1150 return false;
1151 }
1152 }
1153 else {
1154 parseStr += "Missing index for duplicate CurveSet Curve\n";
1155 return false;
1156 }
1157 }
1158 else {
1159 icCurveSetCurvePtr pCurve = ParseXmlCurve(pNode, parseStr);
1160
1161 if (!pCurve)
1162 return false;
1163
1164 if (!SetCurve(nIndex, pCurve))
1165 return false;
1166 nIndex++;
1167 }
1168 }
1169 }
1170
1171 if (!pNode && nIndex == nChannels)
1172 return true;
1173
1174 return false;
1175}
1176
1177
1178bool CIccMpeXmlMatrix::ToXml(std::string &xml, std::string blanks/* = ""*/)
1179{
1180 char buf[128];
1181 sprintf(buf, "<MatrixElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1182 xml += blanks + buf;
1183
1184 if (m_nReserved) {
1185 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
1186 xml += buf;
1187 }
1188 xml += ">\n";
1189
1190 int i, j, n;
1191
1192 if (m_pMatrix) {
1193 xml += blanks + " <MatrixData>\n";
1194
1195 for (n=0, j=0; j<NumOutputChannels(); j++) {
1196 xml += blanks + " ";
1197 for (i=0; i<NumInputChannels(); i++, n++) {
1198 sprintf(buf, " " icXmlFloatFmt, m_pMatrix[n]);
1199 xml += buf;
1200 }
1201 xml += "\n";
1202 }
1203 xml += blanks + " </MatrixData>\n";
1204 }
1205
1206 if (m_pConstants) {
1207 for (i = 0; i < NumOutputChannels(); i++) {
1208 if (icNotZero(m_pConstants[i]))
1209 break;
1210 }
1211 if (i < NumOutputChannels()) {
1212 xml += blanks + " <ConstantData>\n";
1213
1214 xml += blanks + " ";
1215 for (i = 0; i < NumOutputChannels(); i++) {
1216 sprintf(buf, " " icXmlFloatFmt, m_pConstants[i]);
1217 xml += buf;
1218 }
1219 xml += "\n";
1220
1221 xml += blanks + " </ConstantData>\n";
1222 }
1223 }
1224
1225 xml += blanks + "</MatrixElement>\n";
1226
1227 return true;
1228}
1229
1230
1231bool CIccMpeXmlMatrix::ParseXml(xmlNode *pNode, std::string &parseStr)
1232{
1233 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1234 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1235 if (!nInputChannels || !nOutputChannels) {
1236 parseStr += "Invalid InputChannels or OutputChannels In MatrixElement\n";
1237 return false;
1238 }
1239
1240 xmlNode *pData;
1241
1242 pData = icXmlFindNode(pNode->children, "MatrixData");
1243 if (pData) {
1244 SetSize(nInputChannels, nOutputChannels);
1245
1246 if (!CIccFloatArray::ParseArray(m_pMatrix, m_nInputChannels*m_nOutputChannels, pData->children))
1247 return false;
1248
1249 const char *invert = icXmlAttrValue(pData, "InvertMatrix", "false");
1250 if (!stricmp(invert, "true")) {
1251 if (m_nInputChannels != m_nOutputChannels) {
1252 parseStr += "Inversion of MatrixData requires square matrix\n";
1253 return false;
1254 }
1256 if (!pInverter || !pInverter->Invert(m_pMatrix, m_nOutputChannels, m_nInputChannels)) {
1257 parseStr += "Unable to invert matrix!\n";
1258 return false;
1259 }
1260 }
1261 }
1262 else { //Having no MatrixData implies having a matrix full of zeros which is represented by m_pMatrix set to NULL
1263 SetSize(0, nOutputChannels); //Initialize with m_pMatrix set to NULL
1264 m_nInputChannels = nInputChannels; //Fix m_nInputChannels
1265 }
1266
1267 pData = icXmlFindNode(pNode->children, "ConstantData");
1268 if (pData) {
1269 if (!CIccFloatArray::ParseArray(m_pConstants, m_nOutputChannels, pData->children))
1270 return false;
1271 }
1272 return true;
1273}
1274
1275bool CIccMpeXmlEmissionMatrix::ToXml(std::string &xml, std::string blanks/* = ""*/)
1276{
1277 char buf[128];
1278 sprintf(buf, "<EmissionMatrixElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1279 xml += blanks + buf;
1280
1281 if (m_nReserved) {
1282 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
1283 xml += buf;
1284 }
1285 xml += ">\n";
1286
1287 sprintf(buf, " <Wavelengths start=\"" icXmlHalfFmt "\" end=\"" icXmlHalfFmt "\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
1288 xml += blanks + buf;
1289
1290 int i, j, n;
1291
1292 if (m_pWhite) {
1293 xml += blanks + " <WhiteData>\n";
1294
1295 xml += blanks + " ";
1296 for (i=0; i<(int)m_Range.steps; i++) {
1297 sprintf(buf, " " icXmlFloatFmt, m_pWhite[i]);
1298 xml += buf;
1299 }
1300 xml += "\n";
1301
1302 xml += blanks + " </WhiteData>\n";
1303 }
1304
1305 if (m_pMatrix) {
1306 xml += blanks + " <MatrixData>\n";
1307
1308 for (n=0, j=0; j<numVectors(); j++) {
1309 xml += blanks + " ";
1310 for (i=0; i<(int)m_Range.steps; i++, n++) {
1311 sprintf(buf, " " icXmlFloatFmt, m_pMatrix[n]);
1312 xml += buf;
1313 }
1314 xml += "\n";
1315 }
1316 xml += blanks + " </MatrixData>\n";
1317 }
1318
1319 if (m_pOffset) {
1320 xml += blanks + " <OffsetData>\n";
1321
1322 xml += blanks + " ";
1323 for (i=0; i<(int)m_Range.steps; i++) {
1324 sprintf(buf, " " icXmlFloatFmt, m_pOffset[i]);
1325 xml += buf;
1326 }
1327 xml += "\n";
1328
1329 xml += blanks + " </OffsetData>\n";
1330 }
1331
1332 xml += blanks + "</EmissionMatrixElement>\n";
1333
1334 return true;
1335}
1336
1337
1338bool CIccMpeXmlEmissionMatrix::ParseXml(xmlNode *pNode, std::string &parseStr)
1339{
1340 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1341 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1342
1343 if (!nInputChannels || !nOutputChannels) {
1344 parseStr += "Invalid InputChannels or OutputChannels In MatrixElement\n";
1345 return false;
1346 }
1347
1348 xmlNode *pData;
1349
1350 pData = icXmlFindNode(pNode->children, "Wavelengths");
1351 if (pData) {
1352 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
1353 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
1354 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
1355
1356 if (!nSteps) {
1357 parseStr += "Invalid Spectral Range\n";
1358 return false;
1359 }
1360 m_Range.start = icFtoF16(dStart);
1361 m_Range.end = icFtoF16(dEnd);
1362 m_Range.steps = nSteps;
1363 }
1364
1365 SetSize(nInputChannels, nOutputChannels, m_Range);
1366 if (!m_pWhite || !m_pMatrix || !m_pOffset) {
1367 parseStr += "Unable to SetSize\n";
1368 return false;
1369 }
1370
1371 pData = icXmlFindNode(pNode->children, "WhiteData");
1372 if (pData) {
1373
1374 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
1375 return false;
1376 }
1377 else {
1378 parseStr += "Missing MatrixData";
1379 }
1380
1381 pData = icXmlFindNode(pNode->children, "MatrixData");
1382 if (pData) {
1383
1384 if (!CIccFloatArray::ParseArray(m_pMatrix, numVectors()*(int)m_Range.steps, pData->children))
1385 return false;
1386 }
1387 else {
1388 parseStr += "Missing MatrixData";
1389 }
1390
1391 pData = icXmlFindNode(pNode->children, "OffsetData");
1392 if (pData) {
1393 if (!CIccFloatArray::ParseArray(m_pOffset, m_Range.steps, pData->children))
1394 return false;
1395 }
1396 else {
1397 memset(m_pOffset, 0, (int)m_Range.steps*sizeof(icFloatNumber));
1398 }
1399 return true;
1400}
1401
1402bool CIccMpeXmlInvEmissionMatrix::ToXml(std::string &xml, std::string blanks/* = ""*/)
1403{
1404 char buf[128];
1405 sprintf(buf, "<InvEmissionMatrixElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1406 xml += blanks + buf;
1407
1408 if (m_nReserved) {
1409 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
1410 xml += buf;
1411 }
1412 xml += ">\n";
1413
1414 sprintf(buf, " <Wavelengths start=\"" icXmlHalfFmt "\" end=\"" icXmlHalfFmt "\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
1415 xml += blanks + buf;
1416
1417 int i, j, n;
1418
1419 if (m_pWhite) {
1420 xml += blanks + " <WhiteData>\n";
1421
1422 xml += blanks + " ";
1423 for (i=0; i<(int)m_Range.steps; i++) {
1424 sprintf(buf, " " icXmlFloatFmt, m_pWhite[i]);
1425 xml += buf;
1426 }
1427 xml += "\n";
1428
1429 xml += blanks + " </WhiteData>\n";
1430 }
1431
1432 if (m_pMatrix) {
1433 xml += blanks + " <MatrixData>\n";
1434
1435 for (n=0, j=0; j<numVectors(); j++) {
1436 xml += blanks + " ";
1437 for (i=0; i<(int)m_Range.steps; i++, n++) {
1438 sprintf(buf, " " icXmlFloatFmt, m_pMatrix[n]);
1439 xml += buf;
1440 }
1441 xml += "\n";
1442 }
1443 xml += blanks + " </MatrixData>\n";
1444 }
1445
1446 if (m_pOffset) {
1447 xml += blanks + " <OffsetData>\n";
1448
1449 xml += blanks + " ";
1450 for (i=0; i<(int)m_Range.steps; i++) {
1451 sprintf(buf, " " icXmlFloatFmt, m_pOffset[i]);
1452 xml += buf;
1453 }
1454 xml += "\n";
1455
1456 xml += blanks + " </OffsetData>\n";
1457 }
1458
1459 xml += blanks + "</InvEmissionMatrixElement>\n";
1460
1461 return true;
1462}
1463
1464
1465bool CIccMpeXmlInvEmissionMatrix::ParseXml(xmlNode *pNode, std::string &parseStr)
1466{
1467 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1468 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1469
1470 if (!nInputChannels || !nOutputChannels) {
1471 parseStr += "Invalid InputChannels or OutputChannels In MatrixElement\n";
1472 return false;
1473 }
1474
1475 xmlNode *pData;
1476
1477 pData = icXmlFindNode(pNode->children, "Wavelengths");
1478 if (pData) {
1479 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
1480 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
1481 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
1482
1483 if (!nSteps) {
1484 parseStr += "Invalid Spectral Range\n";
1485 return false;
1486 }
1487 m_Range.start = icFtoF16(dStart);
1488 m_Range.end = icFtoF16(dEnd);
1489 m_Range.steps = nSteps;
1490 }
1491
1492 SetSize(nInputChannels, nOutputChannels, m_Range);
1493 if (!m_pWhite || !m_pMatrix || !m_pOffset) {
1494 parseStr += "Unable to SetSize\n";
1495 return false;
1496 }
1497
1498 pData = icXmlFindNode(pNode->children, "WhiteData");
1499 if (pData) {
1500
1501 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
1502 return false;
1503 }
1504 else {
1505 parseStr += "Missing White Data";
1506 }
1507
1508 pData = icXmlFindNode(pNode->children, "MatrixData");
1509 if (pData) {
1510
1511 if (!CIccFloatArray::ParseArray(m_pMatrix, numVectors()*(int)m_Range.steps, pData->children))
1512 return false;
1513 }
1514 else {
1515 parseStr += "Missing Matrix Data";
1516 }
1517
1518 pData = icXmlFindNode(pNode->children, "OffsetData");
1519 if (pData) {
1520 if (!CIccFloatArray::ParseArray(m_pOffset, m_Range.steps, pData->children))
1521 return false;
1522 }
1523 else {
1524 memset(m_pOffset, 0, (int)m_Range.steps*sizeof(icFloatNumber));
1525 }
1526 return true;
1527}
1528
1529bool CIccMpeXmlTintArray::ToXml(std::string &xml, std::string blanks/* = ""*/)
1530{
1531 char buf[128], line[128];
1532 sprintf(buf, "<TintArrayElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1533 xml += blanks + buf;
1534
1535 if (m_nReserved) {
1536 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
1537 xml += buf;
1538 }
1539 xml += ">\n";
1540
1541 IIccExtensionTag *pTagEx;
1542 if (m_Array && (pTagEx=m_Array->GetExtension()) && !strcmp(pTagEx->GetExtClassName(), "CIccTagXml")) {
1543 CIccTagXml *pTagXml = (CIccTagXml*)pTagEx;
1544 const icChar* tagSig = icGetTagSigTypeName(m_Array->GetType());
1545
1546 sprintf(line, " <%s>\n", tagSig); //parent node is the tag type
1547 xml += line;
1548
1549 //convert the rest of the tag to xml
1550 if (!pTagXml->ToXml(xml, " ")) {
1551 printf("Unable to output tag with type %s\n", icGetSigStr(buf, m_Array->GetType()));
1552 return false;
1553 }
1554 sprintf(line, " </%s>\n", tagSig);
1555 xml += line;
1556 }
1557
1558 xml += blanks + "</TintArrayElement>\n";
1559
1560 return true;
1561}
1562
1563
1564bool CIccMpeXmlTintArray::ParseXml(xmlNode *pNode, std::string &parseStr)
1565{
1566 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1567 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1568 if (!nInputChannels || !nOutputChannels) {
1569 parseStr += "Invalid InputChannels or OutputChannels In TintArrayElement\n";
1570 return false;
1571 }
1572 m_nInputChannels = nInputChannels;
1573 m_nOutputChannels = nOutputChannels;
1574
1575 for (pNode = pNode->children; pNode && pNode->type != XML_ELEMENT_NODE; pNode = pNode->next);
1576 if (pNode) {
1577 CIccTag *pTag = NULL;
1578 icSignature sigTag = (icSignature)0;
1579
1580 // get the tag signature
1581 std::string nodeName = (icChar*) pNode->name;
1582 icTagTypeSignature sigType = icGetTypeNameTagSig (nodeName.c_str());
1583
1584 if (sigType==icSigUnknownType){
1585 xmlAttr *attr = icXmlFindAttr(pNode, "type");
1587 }
1588
1589 CIccInfo info;
1590
1591 // create a tag based on the signature
1592 pTag = CIccTag::Create(sigType);
1593
1594 if (!pTag && !pTag->IsNumArrayType()) {
1595 parseStr+= "Invalid data type for Tint Array!\n";
1596 delete pTag;
1597 return false;
1598 }
1599
1600 IIccExtensionTag *pExt;
1601
1602 if (pTag && (pExt = pTag->GetExtension()) && !strcmp(pExt->GetExtClassName(), "CIccTagXml")) {
1603 CIccTagXml* pXmlTag = (CIccTagXml*)pExt;
1604 xmlAttr *attr;
1605
1606 if (pXmlTag->ParseXml(pNode->children, parseStr)) {
1607 if ((attr=icXmlFindAttr(pNode, "reserved"))) {
1608 sscanf(icXmlAttrValue(attr), "%u", &pTag->m_nReserved);
1609 }
1610 m_Array = (CIccTagNumArray*)pTag;
1611 }
1612 else {
1613 parseStr += "Unable to Parse \"";
1614 parseStr += info.GetTagTypeSigName(sigType);
1615 parseStr += "\" (";
1616 parseStr += nodeName;
1617 parseStr += ") Tint Tag\n";
1618 delete pTag;
1619 return false;
1620 }
1621 }
1622 else {
1623 parseStr += "Invalid tag extension for \"";
1624 parseStr += info.GetTagTypeSigName(sigType);
1625 parseStr += "\" (";
1626 parseStr += nodeName;
1627 parseStr += ") Tint Tag\n";
1628 if (pTag)
1629 delete pTag;
1630 return false;
1631 }
1632 }
1633 else {
1634 parseStr += "Tint Array missing tint values\n";
1635 return false;
1636 }
1637 return true;
1638}
1639
1640
1642{
1644
1645 if (rv)
1646 *rv = *this;
1647
1648 return rv;
1649}
1650
1651bool CIccXmlToneMapFunc::ToXml(std::string& xml, std::string blanks /* = "" */)
1652{
1653 char line[256];
1654
1655 sprintf(line, "<ToneMapFunction FunctionType=\"%d\"", m_nFunctionType);
1656 xml += blanks + line;
1657
1658 if (m_nReserved) {
1659 sprintf(line, " Reserved=\"%d\"", m_nReserved);
1660 xml += line;
1661 }
1662 if (m_nReserved2) {
1663 sprintf(line, " Reserved2=\"%d\"", m_nReserved2);
1664 xml += line;
1665 }
1666 xml += ">\n";
1667
1668 CIccFloatArray::DumpArray(xml, blanks + " ", m_params, m_nParameters, icConvertFloat, 8);
1669
1670 xml += blanks + "</ToneMapFunction>\n";
1671
1672 return true;
1673
1674}
1675
1676bool CIccXmlToneMapFunc::ParseXml(xmlNode* pNode, std::string& parseStr)
1677{
1678 xmlAttr* funcType = icXmlFindAttr(pNode, "FunctionType");
1679
1680 if (!funcType) {
1681 parseStr += "Bad FunctionType in Tone Map Function\n";
1682 return false;
1683 }
1684
1685 m_nReserved2 = atoi(icXmlAttrValue(pNode, "Reserved2"));
1686 m_nFunctionType = atoi(icXmlAttrValue(funcType));
1687
1688 switch (m_nFunctionType) {
1689 case 0x0000:
1690 m_nParameters = 3;
1691 break;
1692
1693 default:
1694 parseStr += "Unsupported FunctionType value in Tone Map Function\n";
1695 return false;
1696 }
1697
1698 CIccFloatArray args;
1699
1700 if (!args.ParseArray(pNode->children))
1701 return false;
1702
1703 if (args.GetSize() < m_nParameters)
1704 return false;
1705
1706 if (m_params) {
1707 free(m_params);
1708 }
1709
1710 if (m_nParameters) {
1711 m_params = (icFloatNumber*)malloc(m_nParameters * sizeof(icFloatNumber));
1712 if (!m_params)
1713 return false;
1714
1715 memcpy(m_params, args.GetBuf(), m_nParameters * sizeof(icFloatNumber));
1716 }
1717 else
1718 m_params = NULL;
1719
1720 return true;
1721}
1722
1723
1724bool CIccMpeXmlToneMap::ToXml(std::string& xml, std::string blanks/* = ""*/)
1725{
1726 char buf[128], line[128];
1727 sprintf(buf, "<ToneMapElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1728 xml += blanks + buf;
1729
1730 if (m_nReserved) {
1731 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
1732 xml += buf;
1733 }
1734 xml += ">\n";
1735
1736 if (m_pLumCurve) {
1737 xml += blanks + " <LuminanceCurve>\n";
1738 if (!ToXmlCurve(xml, blanks + " ", m_pLumCurve))
1739 return false;
1740 xml += blanks + " </LuminanceCurve>\n";
1741 }
1742
1743 if (m_pToneFuncs) {
1744 xml += blanks + " <ToneMapFunctions>\n";
1745 int i, j;
1746 for (i = 0; i < NumOutputChannels(); i++) {
1747 if (m_pToneFuncs[i] && !strcmp(m_pToneFuncs[i]->GetClassName(), "CIccXmlToneMapFunc")) {
1748 CIccXmlToneMapFunc* pFunc = (CIccXmlToneMapFunc*)m_pToneFuncs[i];
1749
1750 //check for duplicate curves
1751 for (j = 0; j < i; j++) {
1752 if (m_pToneFuncs[i] == m_pToneFuncs[j])
1753 break;
1754 }
1755
1756 //handle case of duplicate curve
1757 if (j < i) {
1758 sprintf(line, "<DuplicateFunction Index=\"%d\"/>\n", j);
1759 xml += blanks + " ";
1760 xml += line;
1761 }
1762 else if (!pFunc->ToXml(xml, blanks + " "))
1763 return false;
1764 }
1765 else
1766 return false;
1767 }
1768 xml += blanks + " </ToneMapFunctions>\n";
1769 }
1770
1771 xml += blanks + "</ToneMapElement>\n";
1772
1773 return true;
1774}
1775
1776
1777bool CIccMpeXmlToneMap::ParseXml(xmlNode* pNode, std::string& parseStr)
1778{
1779 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1780 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1781 if (!nInputChannels || !nOutputChannels || nInputChannels!=nOutputChannels+1) {
1782 parseStr += "Invalid InputChannels or OutputChannels In ToneMapElement\n";
1783 return false;
1784 }
1785 m_nInputChannels = nInputChannels;
1786
1787 SetNumOutputChannels(nOutputChannels);
1788
1789 if (!m_pToneFuncs) {
1790 parseStr += "Unable to allocate ToneMapFunctions\n";
1791 return false;
1792 }
1793
1794 xmlNode* pSubNode = icXmlFindNode(pNode->children, "LuminanceCurve");
1795
1796 if (pSubNode) {
1797 xmlNode* pNode;
1798 for (pNode = pSubNode->children; pNode && pNode->type != XML_ELEMENT_NODE; pNode = pNode->next);
1799 m_pLumCurve = ParseXmlCurve(pNode, parseStr);
1800 if (!m_pLumCurve) {
1801 parseStr += "Unable to parse Luminance Curve\n";
1802 return false;
1803 }
1804 }
1805 else {
1806 parseStr += "Missing Luminance Curve";
1807 }
1808
1809 pSubNode = icXmlFindNode(pNode->children, "ToneMapFunctions");
1810
1811 if (pSubNode) {
1812 xmlNode* pNode;
1813 int nIndex = 0;
1814 for (pNode = pSubNode->children, nIndex = 0;
1815 pNode;
1816 pNode = pNode->next) {
1817 if (pNode->type == XML_ELEMENT_NODE) {
1818 if (nIndex >= nOutputChannels) {
1819 parseStr += "Too many ToneFunctions";
1820 return false;
1821 }
1822 else if (!strcmp((const char*)pNode->name, "DuplicateFunction")) {
1823 const char* attr = icXmlAttrValue(pNode, "Index", NULL);
1824
1825 if (attr) {
1826 int nCopyIndex = atoi(attr);
1827 if (nCopyIndex >= 0 && nCopyIndex < nIndex) {
1828 m_pToneFuncs[nIndex] = m_pToneFuncs[nCopyIndex];
1829 nIndex++;
1830 }
1831 else {
1832 parseStr += "Invalid index for duplicate ToneMapFunction\n";
1833 return false;
1834 }
1835 }
1836 else {
1837 parseStr += "Missing index for duplicate ToneMapFunction\n";
1838 return false;
1839 }
1840 }
1841 else if (!strcmp((const char*)pNode->name, "ToneMapFunction")) {
1843
1844 if (!pFunc->ParseXml(pNode, parseStr)) {
1845 delete pFunc;
1846 return false;
1847 }
1848 if (!Insert(pFunc))
1849 return false;
1850 nIndex++;
1851 }
1852 else {
1853 parseStr += std::string("Unknown Tone Map Function '") + (const char*)pNode->name + "'\n";
1854 return false;
1855 }
1856 }
1857 }
1858 if (nIndex < m_nOutputChannels) {
1859 parseStr += "Missing ToneMap Functions\n";
1860 }
1861 }
1862
1863 return true;
1864}
1865
1866extern CIccCLUT *icCLutFromXml(xmlNode *pNode, int nIn, int nOut, icConvertType nType, std::string &parseStr);
1867
1868bool CIccMpeXmlCLUT::ToXml(std::string &xml, std::string blanks/* = ""*/)
1869{
1870 char attrs[256];
1871
1872 if (m_nReserved) {
1873 sprintf(attrs, " InputChannels=\"%d\" OutputChannels=\"%d\" Reserved=\"%u\"", NumInputChannels(), NumOutputChannels(), m_nReserved);
1874 }
1875 else {
1876 sprintf(attrs, " InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1877 }
1878
1879 return icCLUTToXml(xml, m_pCLUT, icConvertFloat, blanks, true, attrs, "CLutElement");
1880}
1881
1882bool CIccMpeXmlCLUT::ParseXml(xmlNode *pNode, std::string &parseStr)
1883{
1884 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1885 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1886
1887 if (!m_nInputChannels || !m_nOutputChannels) {
1888 parseStr += "Invalid InputChannels or OutputChannels In CLutElement\n";
1889 return false;
1890 }
1891
1892 CIccCLUT *pCLut = icCLutFromXml(pNode, m_nInputChannels, m_nOutputChannels, icConvertFloat, parseStr);
1893 if (pCLut) {
1894 SetCLUT(pCLut);
1895 if (m_pCLUT)
1896 return true;
1897 }
1898
1899 return false;
1900}
1901
1902bool CIccMpeXmlExtCLUT::ToXml(std::string &xml, std::string blanks/* = ""*/)
1903{
1904 char attrs[256];
1905 std::string reserved;
1906
1907 if (m_nReserved) {
1908 sprintf(attrs, " Reserved=\"%u\"", m_nReserved);
1909 reserved = attrs;
1910 }
1911
1912 if (m_nReserved2) {
1913 sprintf(attrs, " Reserved2=\"%u\"", m_nReserved2);
1914 reserved += attrs;
1915 }
1916
1917 sprintf(attrs, " InputChannels=\"%d\" OutputChannels=\"%d\"%s StorageType=\"%d\"", NumInputChannels(), NumOutputChannels(), reserved.c_str(), m_storageType);
1918
1919 return icCLUTToXml(xml, m_pCLUT, icConvertFloat, blanks, true, attrs, "ExtCLutElement");
1920}
1921
1922bool CIccMpeXmlExtCLUT::ParseXml(xmlNode *pNode, std::string &parseStr)
1923{
1924 m_storageType = (icUInt16Number)atoi(icXmlAttrValue(pNode, "StorageType", "0"));
1925 m_nReserved2 = atoi(icXmlAttrValue(pNode, "Reserved2", "0"));
1926
1927 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1928 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1929
1930 if (!m_nInputChannels || !m_nOutputChannels) {
1931 parseStr += "Invalid InputChannels or OutputChannels In ExtCLutElement\n";
1932 return false;
1933 }
1934
1935 CIccCLUT *pCLut = icCLutFromXml(pNode, m_nInputChannels, m_nOutputChannels, icConvertFloat, parseStr);
1936 if (pCLut) {
1937 SetCLUT(pCLut);
1938 if (m_pCLUT)
1939 return true;
1940 }
1941
1942 return false;
1943}
1944
1945bool CIccMpeXmlBAcs::ToXml(std::string &xml, std::string blanks/* = ""*/)
1946{
1947 char line[256];
1948 char buf[256], fix[256];
1949
1950 sprintf(line, "<BAcsElement InputChannels=\"%d\" OutputChannels=\"%d\" Signature=\"%s\"", NumInputChannels(), NumOutputChannels(),
1951 icFixXml(fix, icGetSigStr(buf, m_signature)));
1952 xml += blanks + line;
1953
1954 if (m_nReserved) {
1955 sprintf(line, " Reserved=\"%u\"", m_nReserved);
1956 xml += line;
1957 }
1958
1959 if (m_pData && m_nDataSize) {
1960 icUInt8Number *m_ptr = m_pData;
1961
1962 xml += ">\n";
1963
1964 icXmlDumpHexData(xml, blanks+" ", m_pData, m_nDataSize);
1965
1966 xml += blanks + "</BAcsElement>\n";
1967 }
1968 else {
1969 xml += "/>\n";
1970 }
1971
1972 return true;
1973}
1974
1975
1976bool CIccMpeXmlBAcs::ParseXml(xmlNode *pNode, std::string &parseStr)
1977{
1978 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1979 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1980
1981 if (!m_nInputChannels || !m_nOutputChannels) {
1982 parseStr += "Invalid InputChannels or OutputChannels In BAcsElement\n";
1983 return false;
1984 }
1985
1986 m_signature = icXmlStrToSig(icXmlAttrValue(pNode, "Signature"));
1987
1988 if (pNode->children && pNode->children->type == XML_TEXT_NODE && pNode->children->content) {
1989 icUInt32Number nSize = icXmlGetHexDataSize((const char*)pNode->children->content);
1990
1991 if (nSize) {
1992 if (!AllocData(nSize))
1993 return false;
1994 icXmlGetHexData(m_pData, (const char *)pNode->children->content, nSize);
1995 }
1996 }
1997 return true;
1998}
1999
2000
2001bool CIccMpeXmlEAcs::ToXml(std::string &xml, std::string blanks/* = ""*/)
2002{
2003 char line[256];
2004 char buf[256], fix[256];
2005
2006 sprintf(line, "<EAcsElement InputChannels=\"%d\" OutputChannels=\"%d\" Signature=\"%s\"", NumInputChannels(), NumOutputChannels(),
2007 icFixXml(fix, icGetSigStr(buf, m_signature)));
2008 xml += blanks + line;
2009
2010 if (m_nReserved) {
2011 sprintf(line, " Reserved=\"%u\"", m_nReserved);
2012 xml += line;
2013 }
2014
2015 if (m_pData && m_nDataSize) {
2016 icUInt8Number *m_ptr = m_pData;
2017
2018 xml += ">\n";
2019 icXmlDumpHexData(xml, blanks+" ", m_pData, m_nDataSize);
2020 xml += blanks + "</EAcsElement>\n";
2021 }
2022 else {
2023 xml += "/>\n";
2024 }
2025
2026 return true;
2027}
2028
2029
2030bool CIccMpeXmlEAcs::ParseXml(xmlNode *pNode, std::string &parseStr)
2031{
2032 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
2033 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
2034
2035 if (!m_nInputChannels || !m_nOutputChannels) {
2036 parseStr += "Invalid InputChannels or OutputChannels In EAcsElement\n";
2037 return false;
2038 }
2039
2040 m_signature = icXmlStrToSig(icXmlAttrValue(pNode, "Signature"));
2041
2042 if (pNode->children && pNode->children->type == XML_TEXT_NODE && pNode->children->content) {
2043 icUInt32Number nSize = icXmlGetHexDataSize((const char*)pNode->children->content);
2044
2045 if (nSize) {
2046 if (!AllocData(nSize))
2047 return false;
2048 icXmlGetHexData(m_pData, (const char *)pNode->children->content, nSize);
2049 }
2050 }
2051 return true;
2052}
2053
2054static bool icXmlDumpColorAppearanceParams(std::string &xml, std::string blanks, CIccCamConverter *pCam)
2055{
2056 char line[256];
2057 icFloatNumber xyz[3];
2058
2059 xml += blanks + "<ColorAppearanceParams>\n";
2060
2061 pCam->GetParameter_WhitePoint(&xyz[0]);
2062 sprintf(line, " <XYZNumber X=\"" icXmlFloatFmt "\" Y=\"" icXmlFloatFmt "\" Z=\"" icXmlFloatFmt "\"/>", xyz[0], xyz[1], xyz[2]);
2063
2064 xml += blanks + " <WhitePoint>\n";
2065 xml += blanks + line;
2066 xml += blanks + " </WhitePoint>\n";
2067
2068 sprintf(line, " <Luminance>" icXmlFloatFmt "</Luminance>\n", pCam->GetParameter_La());
2069 xml += blanks + line;
2070
2071 sprintf(line, " <BackgroundLuminance>" icXmlFloatFmt "</BackgroundLuminance>\n", pCam->GetParameter_Yb());
2072 xml += blanks + line;
2073
2074 sprintf(line, " <ImpactSurround>" icXmlFloatFmt "</ImpactSurround>\n", pCam->GetParameter_C());
2075 xml += blanks + line;
2076
2077 sprintf(line, " <ChromaticInductionFactor>" icXmlFloatFmt "</ChromaticInductionFactor>\n", pCam->GetParameter_Nc());
2078 xml += blanks + line;
2079
2080 sprintf(line, " <AdaptationFactor>" icXmlFloatFmt "</AdaptationFactor>\n", pCam->GetParameter_F());
2081 xml += blanks + line;
2082
2083 xml += "</ColorAppearanceParams>\n";
2084
2085 return true;
2086}
2087
2088static bool icXmlParseColorAppearanceParams(xmlNode *pNode, std::string &parseStr, CIccCamConverter *pCam)
2089{
2090 xmlNode *pChild = icXmlFindNode(pNode, "WhitePoint");
2091 if (!pChild) {
2092 parseStr += "Unable to find CAM Whitepoint\n";
2093 return false;
2094 }
2095
2096 xmlNode *xyzNode = icXmlFindNode(pChild->children, "XYZNumber");
2097
2098 if (!xyzNode) {
2099 parseStr += "Unable to find valid CAM WhitePoint XYZ\n";
2100 return false;
2101 }
2102
2103 xmlAttr *x = icXmlFindAttr(xyzNode, "X");
2104 xmlAttr *y = icXmlFindAttr(xyzNode, "Y");
2105 xmlAttr *z = icXmlFindAttr(xyzNode, "Z");
2106
2107 icFloatNumber xyz[3];
2108 if (x && y && z) {
2109 xyz[0] = (icFloatNumber)atof(icXmlAttrValue(x));
2110 xyz[1] = (icFloatNumber)atof(icXmlAttrValue(y));
2111 xyz[2] = (icFloatNumber)atof(icXmlAttrValue(z));
2112 }
2113 else {
2114 parseStr += "Invalid CAM WhitePoint XYZNumber\n";
2115 return false;
2116 }
2117 pCam->SetParameter_WhitePoint(&xyz[0]);
2118
2119 pChild = icXmlFindNode(pNode, "Luminance");
2120 if (!pChild || !pChild->children || !pChild->children->content) {
2121 parseStr += "Invalid CAM Luminance\n";
2122 return false;
2123 }
2124 pCam->SetParameter_La((icFloatNumber)atof((const char*)pChild->children->content));
2125
2126 pChild = icXmlFindNode(pNode, "BackgroundLuminance");
2127 if (!pChild || !pChild->children || !pChild->children->content) {
2128 parseStr += "Invalid CAM Luminance\n";
2129 return false;
2130 }
2131 pCam->SetParameter_Yb((icFloatNumber)atof((const char*)pChild->children->content));
2132
2133 pChild = icXmlFindNode(pNode, "ImpactSurround");
2134 if (!pChild || !pChild->children || !pChild->children->content) {
2135 parseStr += "Invalid CAM ImpactSurround\n";
2136 return false;
2137 }
2138 pCam->SetParameter_C((icFloatNumber)atof((const char*)pChild->children->content));
2139
2140 pChild = icXmlFindNode(pNode, "ChromaticInductionFactor");
2141 if (!pChild || !pChild->children || !pChild->children->content) {
2142 parseStr += "Invalid CAM ChromaticInductionFactor\n";
2143 return false;
2144 }
2145 pCam->SetParameter_Nc((icFloatNumber)atof((const char*)pChild->children->content));
2146
2147 pChild = icXmlFindNode(pNode, "AdaptationFactor");
2148 if (!pChild || !pChild->children || !pChild->children->content) {
2149 parseStr += "Invalid CAM AdaptationFactor\n";
2150 return false;
2151 }
2152 pCam->SetParameter_F((icFloatNumber)atof((const char*)pChild->children->content));
2153
2154 return true;
2155}
2156
2157bool CIccMpeXmlJabToXYZ::ToXml(std::string &xml, std::string blanks/* = ""*/)
2158{
2159 char line[256];
2160
2161 sprintf(line, "<JabToXYZElement InputChannels=\"%d\" OutputChannels=\"%d\"" , NumInputChannels(), NumOutputChannels());
2162 xml += blanks + line;
2163
2164 if (m_nReserved) {
2165 sprintf(line, " Reserved=\"%u\"", m_nReserved);
2166 xml += line;
2167 }
2168 xml += ">\n";
2169
2170 if (m_pCAM) {
2171 icXmlDumpColorAppearanceParams(xml, blanks+" ", m_pCAM);
2172 xml += blanks + "</JabToXYZElement>\n";
2173 }
2174
2175 return true;
2176}
2177
2178
2179bool CIccMpeXmlJabToXYZ::ParseXml(xmlNode *pNode, std::string &parseStr)
2180{
2181 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
2182 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
2183
2184 if (m_nInputChannels!=3 || m_nOutputChannels!=3) {
2185 parseStr += "Invalid InputChannels or OutputChannels In JabToXYZElement\n";
2186 return false;
2187 }
2188 xmlNode *pChild = icXmlFindNode(pNode->children, "ColorAppearanceParams");
2189
2190 if (pChild) {
2191 CIccCamConverter *pCAM = new CIccCamConverter();
2192
2193 if (!icXmlParseColorAppearanceParams(pChild->children, parseStr, pCAM)) {
2194 delete pCAM;
2195 return false;
2196 }
2197
2198 SetCAM(pCAM);
2199 }
2200 else {
2201 parseStr += "Unable to find ColorAppearanceParams\n";
2202 return false;
2203 }
2204
2205 return true;
2206}
2207
2208bool CIccMpeXmlXYZToJab::ToXml(std::string &xml, std::string blanks/* = ""*/)
2209{
2210 char line[256];
2211
2212 sprintf(line, "<XYZToJabElement InputChannels=\"%d\" OutputChannels=\"%d\"" , NumInputChannels(), NumOutputChannels());
2213 xml += blanks + line;
2214
2215 if (m_nReserved) {
2216 sprintf(line, " Reserved=\"%u\"", m_nReserved);
2217 xml += line;
2218 }
2219 xml += ">\n";
2220
2221 if (m_pCAM) {
2222 icXmlDumpColorAppearanceParams(xml, blanks+" ", m_pCAM);
2223 xml += blanks + "</XYZToJabElement>\n";
2224 }
2225
2226 return true;
2227}
2228
2229
2230bool CIccMpeXmlXYZToJab::ParseXml(xmlNode *pNode, std::string &parseStr)
2231{
2232 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
2233 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
2234
2235 if (m_nInputChannels!=3 || m_nOutputChannels!=3) {
2236 parseStr += "Invalid InputChannels or OutputChannels In XYZToJabElement\n";
2237 return false;
2238 }
2239 xmlNode *pChild = icXmlFindNode(pNode->children, "ColorAppearanceParams");
2240
2241 if (pChild) {
2242 CIccCamConverter *pCAM = new CIccCamConverter();
2243
2244 if (!icXmlParseColorAppearanceParams(pChild->children, parseStr, pCAM)) {
2245 delete pCAM;
2246 return false;
2247 }
2248
2249 SetCAM(pCAM);
2250 }
2251 else {
2252 parseStr += "Unable to find ColorAppearanceParams\n";
2253 return false;
2254 }
2255
2256 return true;
2257}
2258
2259
2260bool CIccMpeXmlCalculator::ToXml(std::string &xml, std::string blanks/* = ""*/)
2261{
2262 char line[256];
2263 std::string blanks2 = blanks + " ";
2264
2265 sprintf(line, "<CalculatorElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
2266 xml += blanks + line;
2267
2268 if (m_nReserved) {
2269 sprintf(line, " Reserved=\"%u\"", m_nReserved);
2270 xml += line;
2271 }
2272 xml += ">\n";
2273
2274 int i;
2275
2276 if (m_SubElem && m_nSubElem) {
2277 xml += blanks2 + "<SubElements>\n";
2278 for (i=0; i<(int)m_nSubElem; i++) {
2279 if (m_SubElem[i]) {
2280 IIccExtensionMpe *pExt = m_SubElem[i]->GetExtension();
2281 if (pExt && !strcmp(pExt->GetExtClassName(), "CIccMpeXml")) {
2282 CIccMpeXml *pMpe = (CIccMpeXml*)pExt;
2283 pMpe->ToXml(xml, blanks2+" ");
2284 }
2285 else {
2286 return false;
2287 }
2288 }
2289 else {
2290 return false;
2291 }
2292 }
2293 xml += blanks2 + "</SubElements>\n";
2294 }
2295
2296 if (m_calcFunc) {
2297 std::string desc;
2298
2299 xml += blanks2 + "<MainFunction>\n";
2300
2301 m_calcFunc->Describe(desc, 100, (int)blanks2.size()+2);
2302 xml += desc;
2303
2304 xml+= blanks2 + "</MainFunction>\n";
2305 }
2306
2307 xml += blanks + "</CalculatorElement>\n";
2308 return true;
2309}
2310
2312{
2313 if (bFirst && !((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_')))
2314 return false;
2315 else if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '_')))
2316 return false;
2317
2318 return true;
2319}
2320
2322{
2323 const char *ptr;
2324 if (!szName || !*szName) {
2325 return false;
2326 }
2327
2328 for (ptr = szName; *ptr; ptr++) {
2329 if (!validNameChar(*ptr, ptr == szName))
2330 return false;
2331 }
2332
2333 return true;
2334}
2335
2336bool CIccMpeXmlCalculator::ParseImport(xmlNode *pNode, std::string importPath, std::string &parseStr)
2337{
2338 xmlNode *pChild, *pNext;
2339 xmlAttr *attr;
2340
2341 pChild = icXmlFindNode(pNode->children, "Imports");
2342 if (pChild) {
2343 for (pNext = pChild->children; pNext; pNext = pNext->next) {
2344 if (pNext->type == XML_ELEMENT_NODE) {
2345 if (!strcmp((icChar*)pNext->name, "Import")) {
2346 if ((attr = icXmlFindAttr(pNext, "Filename"))) {
2347 std::string file = icXmlAttrValue(attr);
2348 xmlDoc *doc = NULL;
2349 xmlNode *root_element = NULL;
2350
2351 std::string look = "*";
2352 look += file;
2353 look += "*";
2354
2355 if (strstr(importPath.c_str(), look.c_str())) {
2356 //Already imported this file
2357 continue;
2358 }
2359
2360 /*parse the file and get the DOM */
2361 doc = xmlReadFile(file.c_str(), NULL, 0);
2362
2363 if (doc == NULL) {
2364 parseStr += "Unable to import '";
2365 parseStr += file;
2366 parseStr += '\n';
2367 return false;
2368 }
2369
2370 /*Get the root element node */
2371 root_element = xmlDocGetRootElement(doc);
2372 if (strcmp((icChar*)root_element->name, "IccCalcImport")) {
2373 parseStr += "Invalid calc element import file '" + file + "'\n";
2374 return false;
2375 }
2376
2377 bool rv = ParseImport(root_element, importPath+file+"*", parseStr);
2378
2379 xmlFreeDoc(doc);
2380 }
2381 else {
2382 parseStr += "Missing import file specifier\n";
2383 return false;
2384 }
2385 }
2386 else {
2387 parseStr += "Invalid import specifier\n";
2388 return false;
2389 }
2390 }
2391 }
2392 }
2393
2394 pChild = icXmlFindNode(pNode->children, "Variables");
2395 if (pChild) {
2396 for (pNext = pChild->children; pNext; pNext = pNext->next) {
2397 if (pNext->type == XML_ELEMENT_NODE) {
2398 if (!strcmp((icChar*)pNext->name, "Declare")) {
2399 if ((attr = icXmlFindAttr(pNext, "Name"))) {
2400 std::string name = icXmlAttrValue(attr);
2401 if (!validName(name.c_str())) {
2402 parseStr += "Invalid calc element variable name '" + name + "'\n'";
2403 return false;
2404 }
2405
2406 TempDeclVarMap::iterator v = m_declVarMap.find(name);
2407 if (v != m_declVarMap.end()) {
2408 parseStr += "Calc element variable '" + name + "' was previously declared\n";
2409 return false;
2410 }
2411 int offset = -1;
2412 icUInt16Number size = 1;
2413
2414 if ((attr = icXmlFindAttr(pNext, "Position"))) {
2415 offset = atoi(icXmlAttrValue(attr));
2416 if (offset && importPath != "*") {
2417 parseStr += "Position cannot be specified for imported variables";
2418 return false;
2419 }
2420 }
2421 if ((attr = icXmlFindAttr(pNext, "Size"))) {
2422 size = (icUInt16Number)atoi(icXmlAttrValue(attr));
2423 }
2424 if (size < 1) size = 1;
2425
2426 CIccTempDeclVar var = CIccTempDeclVar(name, offset, size);
2427 if (pNext->children && pNext->children->content) {
2428 CIccFuncTokenizer parse((icChar*)pNext->children->content);
2429 offset = 0;
2430
2431 while (parse.GetNext()) {
2432 icUInt16Number extra = 0;
2433 std::string member = parse.GetName();
2434 if (!validName(member.c_str())) {
2435 parseStr += "Invalid member name '" + member + "' for calc element variable '" + name + "'\n";
2436 return false;
2437 }
2438 size = 0; extra = 0;
2439 parse.GetIndex(size, extra, 1, 0);
2440 size++;
2441 if (size < 1)
2442 size = 1;
2443
2444 var.m_members.push_back(CIccTempVar(member, offset, size));
2445 offset += size;
2446 }
2447 if (var.m_size < offset)
2448 var.m_size = offset;
2449 }
2450 m_declVarMap[name] = var;
2451 }
2452 else {
2453 parseStr += "Missing calc element variable name definition\n";
2454 return false;
2455 }
2456 }
2457 else {
2458 parseStr += "Invalid calc element variable declaration\n";
2459 return false;
2460 }
2461 }
2462 }
2463 }
2464
2465 pChild = icXmlFindNode(pNode->children, "Macros");
2466 if (pChild) {
2467 for (pNext = pChild->children; pNext; pNext = pNext->next) {
2468 if (pNext->type == XML_ELEMENT_NODE) {
2469 if (!strcmp((icChar*)pNext->name, "Macro")) {
2470 if ((attr = icXmlFindAttr(pNext, "Name"))) {
2471 std::string name = icXmlAttrValue(attr);
2472 if (!validName(name.c_str())) {
2473 parseStr += "Invalid Macro name '" + name + "'\n'";
2474 return false;
2475 }
2476 if (!pNext->children || !pNext->children->content || !pNext->children->content[0]) {
2477 parseStr += "Missing content for macro '" + name + "'\n'";
2478 return false;
2479 }
2480 MacroMap::iterator m = m_macroMap.find(name);
2481 if (m != m_macroMap.end()) {
2482 if (!strcmp(m->second.c_str(), (icChar*)pNext->children->content))
2483 continue;
2484 parseStr += "Calc Element macro '" + name + "' was previously defined differently\n";
2485 return false;
2486 }
2487 m_macroMap[name] = (icChar*)(pNext->children->content);
2488
2489 if ((attr = icXmlFindAttr(pNext, "Local"))) {
2490 icUInt16Number offset, size;
2491 CIccTempDeclVar var = CIccTempDeclVar(name, 0, 0);
2492 std::string locals = icXmlAttrValue(attr);
2493 CIccFuncTokenizer parse(locals.c_str());
2494 offset = 0;
2495
2496 while (parse.GetNext()) {
2497 icUInt16Number extra = 0;
2498 std::string member = parse.GetName();
2499 if (!validName(member.c_str())) {
2500 parseStr += "Invalid local name '" + member + "' for calc element macro '" + name + "'\n";
2501 return false;
2502 }
2503 size = 0; extra = 0;
2504 parse.GetIndex(size, extra, 1, 0);
2505 size++;
2506 if (size < 1)
2507 size = 1;
2508
2509 var.m_members.push_back(CIccTempVar(member, offset, size));
2510 offset += size;
2511 }
2512 if (var.m_size < offset)
2513 var.m_size = offset;
2514
2515 m_macroLocalMap[name] = var;
2516 }
2517 }
2518 else {
2519 parseStr += "Missing macro name\n";
2520 return false;
2521 }
2522 }
2523 else {
2524 parseStr += "Invalid macro declaration\n";
2525 return false;
2526 }
2527 }
2528 }
2529 }
2530
2531 pChild = icXmlFindNode(pNode->children, "SubElements");
2532 if (pChild) {
2533 for (pNext = pChild->children; pNext; pNext = pNext->next) {
2534 if (pNext->type == XML_ELEMENT_NODE) {
2535 std::string name;
2536
2537 if ((attr = icXmlFindAttr(pNext, "Name"))) {
2538 name = icXmlAttrValue(attr);
2539 if (!validName(name.c_str())) {
2540 parseStr += "Invalid SubElement name '" + name + "'\n'";
2541 return false;
2542 }
2543 }
2544 if (name.empty()) {
2545 if (importPath != "*") {
2546 parseStr += "Imported Calc SubElments must be named.";
2547 return false;
2548 }
2549 }
2550 else {
2551 MpePtrMap::iterator se = m_mpeMap.find(name);
2552 if (se != m_mpeMap.end()) {
2553 parseStr += "Duplicate declaration of SubElement '" + name + "'\n";
2554 return false;
2555 }
2556 }
2557
2559
2560 if (!pMpe) {
2561 parseStr += std::string("Unknown Sub-Element Type (") + (const icChar*)pNext->name + ")\n";
2562 return false;
2563 }
2564
2565 if (!strcmp(pMpe->GetClassName(), "CIccMpeXmlCalculator")) {
2566 CIccMpeXmlCalculator *pSubCalc = (CIccMpeXmlCalculator*)pMpe;
2567 pSubCalc->m_sImport = importPath;
2568 }
2569
2570 xmlAttr *attr;
2571 IIccExtensionMpe *pExt = pMpe->GetExtension();
2572
2573 if (pExt) {
2574 if (!strcmp(pExt->GetExtClassName(), "CIccMpeXml")) {
2575 CIccMpeXml* pXmlMpe = (CIccMpeXml*)pExt;
2576
2577 if (pXmlMpe->ParseXml(pNext, parseStr)) {
2578 if ((attr = icXmlFindAttr(pNode, "Reserved"))) {
2579 sscanf(icXmlAttrValue(attr), "%u", &pMpe->m_nReserved);
2580 }
2581
2582 if (name.empty()) {
2583 m_mpeList.push_back(CIccMpePtr(pMpe, m_nNextMpe));
2584 m_nNextMpe++;
2585 }
2586 else {
2587 m_mpeMap[name] = CIccMpePtr(pMpe);
2588 }
2589 }
2590 else {
2591 char str[100];
2592 sprintf(str, " starting on line %d", pNext->line);
2593 parseStr += std::string("Unable to parse element of type ") + pMpe->GetClassName() + str + "\n";
2594 delete pMpe;
2595 return false;
2596 }
2597 }
2598 else {
2599 parseStr += std::string("Element ") + pMpe->GetClassName() + "isn't of type CIccMpeXml\n";
2600 delete pMpe;
2601 return false;
2602 }
2603 }
2604 else {
2605 parseStr += std::string("Element ") + pMpe->GetClassName() + "isn't of type CIccMpeXml\n";
2606 delete pMpe;
2607 return false;
2608 }
2609 }
2610 }
2611 }
2612 return true;
2613}
2614
2615bool CIccMpeXmlCalculator::ValidMacroCalls(const char *szMacroText, std::string macroStack, std::string &parseStr) const
2616{
2617 const char *ptr;
2618 for (ptr = strstr(szMacroText, "call{"); ptr; ptr = strstr(ptr, "call{")) {
2619 CIccFuncTokenizer parse(ptr, true);
2620 parse.GetNext();
2621
2622 std::string name = parse.GetReference();
2623 MacroMap::const_iterator m = m_macroMap.find(name);
2624 if (m == m_macroMap.end()) {
2625 parseStr += "Call to undefined macro '" + name + "'\n";
2626 return false;
2627 }
2628 std::string sm = "*";
2629 sm += name + "*";
2630 if (strstr(macroStack.c_str(), sm.c_str())) {
2631 parseStr += "Macro recursion detected in call to '" + name + "'\n";
2632 return false;
2633 }
2634 if (!ValidMacroCalls(m->second.c_str(), macroStack + name + "*", parseStr)) {
2635 return false;
2636 }
2637 ptr++;
2638 }
2639 return true;
2640}
2641
2642bool CIccMpeXmlCalculator::ValidateMacroCalls(std::string &parseStr) const
2643{
2644 MacroMap::const_iterator m;
2645
2646 for (m = m_macroMap.begin(); m != m_macroMap.end(); m++) {
2647 if (!ValidMacroCalls(m->second.c_str(), "*", parseStr)) {
2648 return false;
2649 }
2650 }
2651 return true;
2652}
2653
2654bool CIccMpeXmlCalculator::Flatten(std::string &flatStr, std::string macroName, const char *szFunc, std::string &parseStr, icUInt32Number nLocalsOffset)
2655{
2656 CIccFuncTokenizer parse(szFunc, true);
2657
2658 while (parse.GetNext()) {
2659 std::string token = parse.GetLast();
2660 const char *tok = token.c_str();
2661 if (!strncmp(tok, "call{", 5) ||
2662 tok[0] == '#') {
2663 std::string nameiter;
2664 std::string name;
2665
2666 if (tok[0] == '#')
2667 nameiter = token.substr(1);
2668 else
2669 nameiter = parse.GetReference();
2670
2671 const char *ptr;
2672 for (ptr = nameiter.c_str(); *ptr && *ptr != '[' && *ptr != '('; ptr++) name += *ptr;
2673 int iter = 1;
2674// if (*ptr) {
2675// iter = atoi(ptr + 1);
2676// if (iter < 1)
2677// iter = 1;
2678// else if (iter>1024)
2679// iter = 1024;
2680// }
2681
2682 MacroMap::iterator m = m_macroMap.find(name.c_str());
2683 if (m != m_macroMap.end()) {
2684 icUInt16Number nLocalsSize = 0;
2685 TempDeclVarMap::iterator locals = m_macroLocalMap.find(macroName);
2686 if (locals != m_macroLocalMap.end()) {
2687 nLocalsSize = locals->second.m_size;
2688 }
2689
2690 int i;
2691 for (i = 0; i < iter; i++) {
2692 Flatten(flatStr, name, m->second.c_str(), parseStr, nLocalsOffset+nLocalsSize);
2693 }
2694 }
2695 else {
2696 parseStr += "Call to undefined macro '" + name + "'\n";
2697 return false;
2698 }
2699 }
2700 else if (!strncmp(tok, "in{", 3) ||
2701 !strncmp(tok, "out{", 4)) {
2702 std::string op = parse.GetName();
2703 std::string ref = parse.GetReference();
2704 std::string refroot;
2705 for (const char *ptr = ref.c_str(); *ptr && *ptr != ',' && *ptr != '(' && *ptr != '['; ptr++) refroot += *ptr;
2706
2707 ChanVarMap *pMap;
2708 int nChan;
2709 if (op == "in") {
2710 pMap = &m_inputMap;
2711 nChan = m_nInputChannels;
2712 }
2713 else {
2714 pMap = &m_outputMap;
2715 nChan = m_nOutputChannels;
2716 }
2717
2718 ChanVarMap::iterator ci = pMap->find(refroot);
2719 if (ci == pMap->end()) {
2720 parseStr += "Invalid '" + op + "' operation channel reference '" + refroot + "'\n";
2721 return false;
2722 }
2723 if (refroot != ref) {
2724 std::string select = ref.substr(refroot.size());
2725 int offset = 0;
2726 int size = 1;
2727
2728 if (select[0] == '[' || select[1] == '(') {
2729 const char *ptr;
2730 offset = atoi(select.c_str() + 1);
2731 for (ptr = select.c_str() + 1; *ptr && *ptr != ')' && *ptr != ']'; ptr++);
2732 select = ptr + 1;
2733 }
2734
2735 if (select[0]==',')
2736 size = atoi(select.c_str() + 1);
2737
2738 if (size < 0 || offset<0 || ci->second.first + offset + size > m_nInputChannels) {
2739 parseStr += "Invalid '" + op + "' operation channel offset or size '" + refroot + "'\n";
2740 return false;
2741 }
2742 char index[80];
2743 sprintf(index, "(%d,%d)", ci->second.first+offset, size);
2744 flatStr += op + index + " ";
2745 }
2746 else if (ci->second.second>1) {
2747 char index[80];
2748 sprintf(index, "(%d,%d)", ci->second.first, ci->second.second);
2749 flatStr += op + index + " ";
2750 }
2751 else {
2752 char index[80];
2753 sprintf(index, "(%d)", ci->second.first);
2754 flatStr += op + index + " ";
2755 }
2756 }
2757 else if (!strncmp(tok, "tget{", 5) ||
2758 !strncmp(tok, "tput{", 5) ||
2759 !strncmp(tok, "tsav{", 5)) {
2760 std::string op = parse.GetName();
2761 std::string ref = parse.GetReference();
2762 std::string refroot;
2763 for (const char *ptr = ref.c_str(); *ptr && *ptr != '[' && *ptr != '('; ptr++) refroot += *ptr;
2764
2765 if (macroName.size() && refroot.size() && refroot[0] == '@') {
2766 std::string localName = refroot.substr(1);
2767 TempDeclVarMap::iterator locals = m_macroLocalMap.find(macroName);
2768 if (locals == m_macroLocalMap.end()) {
2769 parseStr += "Reference to undeclared local variable '" + localName + "' in macro '" + macroName + "'\n";
2770 return false;
2771 }
2772
2773 unsigned long nLocalOffset = 0;
2774 unsigned long nLocalSize = 0;
2775 TempVarList::iterator m = locals->second.m_members.begin();
2776 for (; m != locals->second.m_members.end(); m++) {
2777 if (localName == m->m_name) {
2778 nLocalOffset = m->m_pos;
2779 nLocalSize = m->m_size;
2780 break;
2781 }
2782 }
2783 if (m == locals->second.m_members.end()) {
2784 parseStr += "Reference to undeclared local variable '" + localName + "' in macro '" + macroName + "'\n";
2785 return false;
2786 }
2787 int voffset, vsize;
2788
2789 if (ref != refroot) {
2790 CIccFuncTokenizer p2(ref.c_str());
2791 p2.GetNext();
2792 icUInt16Number _voffset = 0, _vsize = 1;
2793 p2.GetIndex(_voffset, _vsize, 0, 1);
2794 voffset = _voffset;
2795 vsize = _vsize + 1;
2796 }
2797 else {
2798 voffset = 0;
2799 vsize = (int)nLocalSize;
2800 }
2801
2802 if (voffset + vsize > (int)nLocalSize) {
2803 parseStr += "Out of bounds indexing of local '" + refroot + "' in macro '" + macroName + "'\n";
2804 return false;
2805 }
2806
2807 if (nLocalsOffset + nLocalOffset + voffset + vsize > 65536) {
2808 parseStr += "Temporary variable addressing out of bounds\n";
2809 return false;
2810 }
2811 char idx[80];
2812 if (vsize == 1) {
2813 sprintf(idx, "[%lu]", nLocalsOffset + nLocalOffset + voffset);
2814 }
2815 else {
2816 sprintf(idx, "[%lu,%d]", nLocalsOffset + nLocalOffset + voffset, vsize);
2817 }
2818 flatStr += "l";
2819 flatStr += op.substr(1);
2820 flatStr += idx;
2821 flatStr += " ";
2822 }
2823 else {
2824 TempVarMap::iterator var = m_varMap.find(refroot);
2825 if (var == m_varMap.end()) {
2826 std::string root;
2827 for (const char *ptr = refroot.c_str(); *ptr && *ptr != '.'; ptr++) root += *ptr;
2828
2829 TempVarMap::iterator rootVar = m_varMap.find(root);
2830 if (refroot != root && rootVar == m_varMap.end()) {
2831 parseStr += "Reference to undeclared variable '" + ref + "'\n";
2832 return false;
2833 }
2834
2835 TempDeclVarMap::iterator decl = m_declVarMap.find(root);
2836 if (decl == m_declVarMap.end()) {
2837 parseStr += "Reference to undeclared variable '" + ref + "'\n";
2838 return false;
2839 }
2840
2841 if (decl->second.m_pos < 0) {
2842 m_varMap[root] = CIccTempVar(root, m_nNextVar, decl->second.m_size);
2843 decl->second.m_pos = m_nNextVar;
2844
2845 if (strchr(refroot.c_str(), '.')) {
2846 TempVarList::iterator m = decl->second.m_members.begin();
2847 for (; m != decl->second.m_members.end(); m++) {
2848 std::string vm = root + "." + m->m_name;
2849 m_varMap[vm] = CIccTempVar(vm, m_nNextVar + m->m_pos, m->m_size);
2850 }
2851 }
2852
2853 if (m_nNextVar + decl->second.m_size > 65536) {
2854 parseStr += "Temporary variable addressing out of bounds\n";
2855 return false;
2856 }
2857 m_nNextVar += decl->second.m_size;
2858 }
2859 else {
2860 m_varMap[root] = CIccTempVar(root, decl->second.m_pos, decl->second.m_size);
2861
2862 if (strchr(refroot.c_str(), '.')) {
2863 TempVarList::iterator m = decl->second.m_members.begin();
2864 for (; m != decl->second.m_members.end(); m++) {
2865 std::string vm = root + "." + m->m_name;
2866 m_varMap[vm] = CIccTempVar(vm, decl->second.m_pos + m->m_pos, m->m_size);
2867 }
2868 }
2869 if (decl->second.m_pos + decl->second.m_size > 65536) {
2870 parseStr += "Temporary variable addressing out of bounds\n";
2871 return false;
2872 }
2873 }
2874
2875 var = m_varMap.find(refroot);
2876 if (var == m_varMap.end()) {
2877 parseStr += "Reference to undeclared variable '" + refroot + "'\n";
2878 return false;
2879 }
2880 }
2881 int voffset, vsize;
2882
2883 if (ref != refroot) {
2884 CIccFuncTokenizer p2(ref.c_str());
2885 p2.GetNext();
2886 icUInt16Number _voffset = 0, _vsize = 1;
2887 p2.GetIndex(_voffset, _vsize, 0, 1);
2888 voffset = _voffset;
2889 vsize = _vsize + 1;
2890 }
2891 else {
2892 voffset = 0;
2893 vsize = var->second.m_size;
2894 }
2895
2896 if (voffset + vsize > var->second.m_size) {
2897 parseStr += "Out of bounds indexing of '" + refroot + "'\n";
2898 return false;
2899 }
2900 if (var->second.m_pos + voffset + vsize > 65536) {
2901 parseStr += "Temporary variable addressing out of bounds\n";
2902 return false;
2903 }
2904 char idx[80];
2905 if (vsize == 1) {
2906 sprintf(idx, "[%d]", var->second.m_pos + voffset);
2907 }
2908 else {
2909 sprintf(idx, "[%d,%d]", var->second.m_pos + voffset, vsize);
2910 }
2911 flatStr += op + idx + " ";
2912 }
2913 }
2914 else if (!strncmp(tok, "elem{", 5) ||
2915 !strncmp(tok, "curv{", 5) ||
2916 !strncmp(tok, "clut{", 5) ||
2917 !strncmp(tok, "mtx{", 4) ||
2918 !strncmp(tok, "fJab{", 5) ||
2919 !strncmp(tok, "tJab{", 5) ||
2920 !strncmp(tok, "calc{", 5) ||
2921 !strncmp(tok, "tint{", 5)) {
2922 std::string op = parse.GetName();
2923 std::string ref = parse.GetReference();
2924 MpePtrMap::iterator e = m_mpeMap.find(ref);
2925 if (e == m_mpeMap.end()) {
2926 parseStr += "Unknown sub element reference to " + token + "\n";
2927 return false;
2928 }
2929 if (e->second.m_nIndex<0) {
2930 if (e->second.m_ptr) {
2931 m_mpeList.push_back(CIccMpePtr(e->second.m_ptr, m_nNextMpe));
2932 e->second.m_ptr = NULL;
2933 e->second.m_nIndex = m_nNextMpe;
2934 m_nNextMpe++;
2935 }
2936 else {
2937 parseStr += "Invalid sub-element reference: " + token + "\n";
2938 return false;
2939 }
2940 }
2941 char idx[80];
2942 sprintf(idx, "(%d)", e->second.m_nIndex);
2943 flatStr += op + idx + " ";
2944 }
2945 else {
2946 flatStr += tok;
2947 flatStr += " ";
2948 }
2949 }
2950
2951 return true;
2952}
2953
2954bool CIccMpeXmlCalculator::UpdateLocals(std::string &func, std::string sFunc, std::string &parseStr, int nLocalsOffset)
2955{
2956 func.clear();
2957 CIccFuncTokenizer parse(sFunc.c_str(), true);
2958
2959 while (parse.GetNext()) {
2960 std::string token = parse.GetLast();
2961 const char *tok = token.c_str();
2962
2963 if (!strncmp(tok, "lget[", 5) ||
2964 !strncmp(tok, "lput[", 5) ||
2965 !strncmp(tok, "lsav[", 5)) {
2966 std::string op = parse.GetName();
2967 int voffset, vsize;
2968
2969 CIccFuncTokenizer p2(tok+4);
2970 icUInt16Number _voffset = 0, _vsize = 1;
2971 p2.GetIndex(_voffset, _vsize, 0, 1);
2972 voffset = _voffset + nLocalsOffset;
2973 vsize = _vsize + 1;
2974
2975 if (voffset + vsize > 65535) {
2976 parseStr += "Local variable out of bounds - too many variables.\n";
2977 return false;
2978 }
2979
2980 char idx[80];
2981 if (vsize == 1) {
2982 sprintf(idx, "[%d]", voffset);
2983 }
2984 else {
2985 sprintf(idx, "[%d,%d]", voffset, vsize);
2986 }
2987 func +="t";
2988 func += op.substr(1);
2989 func += idx;
2990 func += " ";
2991 }
2992 else {
2993 func += tok;
2994 func += " ";
2995 }
2996 }
2997
2998 return true;
2999}
3001{
3002 m_sImport = "*";
3003 m_declVarMap.clear();
3004 m_varMap.clear();
3005 m_macroMap.clear();
3006
3007 MpePtrList::iterator ml;
3008 for (ml = m_mpeList.begin(); ml != m_mpeList.end(); ml++) {
3009 if (ml->m_ptr)
3010 delete ml->m_ptr;
3011 }
3012 m_mpeList.clear();
3013
3014 MpePtrMap::iterator mm;
3015 for (mm = m_mpeMap.begin(); mm != m_mpeMap.end(); mm++) {
3016 if (mm->second.m_ptr)
3017 delete mm->second.m_ptr;
3018 }
3019 m_mpeMap.clear();
3020 m_nNextVar = 0;
3021 m_nNextMpe = 0;
3022}
3023
3024bool CIccMpeXmlCalculator::ParseChanMap(ChanVarMap& chanMap, const char *szNames, int nChannels)
3025{
3026 chanMap.clear();
3027
3028 if (!szNames)
3029 return false;
3030
3031 int i;
3032 const char *ptr;
3033 std::string name;
3034 IndexSizePair isp;
3035 int size = 1;
3036
3037 for (i = 0, ptr = szNames; *ptr && i < nChannels; ptr++) {
3038 bool bFirst = name.empty();
3039 if (*ptr == ' ') {
3040 if (!bFirst) {
3041 isp.first = i;
3042 isp.second = size;
3043 chanMap[name] = isp;
3044 name.clear();
3045 i += size;
3046 size = 1;
3047 }
3048 }
3049 else if (*ptr == '[' || *ptr == '(') {
3050 size = atoi(ptr + 1);
3051 if (size<0 || i + size>nChannels)
3052 return 0;
3053
3054 for (; *ptr && *ptr != ']' && *ptr != ')'; ptr++);
3055 if (!*ptr)
3056 ptr--;
3057 }
3058 else if (validNameChar(*ptr, bFirst)) {
3059 name += *ptr;
3060 }
3061 else {
3062 return false;
3063 }
3064 }
3065
3066 if (!name.empty() && i < nChannels) {
3067 isp.first = i;
3068 isp.second = size;
3069 chanMap[name] = isp;
3070 }
3071
3072 return true;
3073}
3074
3075bool CIccMpeXmlCalculator::ParseXml(xmlNode *pNode, std::string &parseStr)
3076{
3077 xmlNode *pChild;
3078
3079 SetSize(atoi(icXmlAttrValue(pNode, "InputChannels")),
3080 atoi(icXmlAttrValue(pNode, "OutputChannels")));
3081
3082 clean();
3083
3084 if (!ParseChanMap(m_inputMap, icXmlAttrValue(pNode, "InputNames"), m_nInputChannels)) {
3085 parseStr += "Invalid name for InputChannels";
3086 return false;
3087 }
3088
3089 if (!ParseChanMap(m_outputMap, icXmlAttrValue(pNode, "OutputNames"), m_nOutputChannels)) {
3090 parseStr += "Invalid name for InputChannels";
3091 return false;
3092 }
3093
3094 if (!ParseImport(pNode, "*", parseStr))
3095 return false;
3096
3097 if (!ValidateMacroCalls(parseStr)) {
3098 return false;
3099 }
3100
3101 pChild = icXmlFindNode(pNode->children, "MainFunction");
3102 if (pChild && pNode->children && pChild->children->content) {
3103 char *content = (char*)pChild->children->content;
3104 std::string flatFunc;
3105
3106 //Move new variables to after allocated variables
3107 TempDeclVarMap::iterator declVar;
3108 for (declVar = m_declVarMap.begin(); declVar != m_declVarMap.end(); declVar++) {
3109 if (declVar->second.m_pos >= 0) {
3110 int next = declVar->second.m_pos + declVar->second.m_size;
3111 if (next > m_nNextVar)
3112 m_nNextVar = next;
3113 }
3114 }
3115
3116 if (!Flatten(flatFunc, "", content, parseStr, 0)) {
3117 return false;
3118 }
3119
3120 if (m_macroLocalMap.size()) {
3121 std::string localFunc;
3122 if (!UpdateLocals(localFunc, flatFunc, parseStr, m_nNextVar)) {
3123 return false;
3124 }
3125 flatFunc = localFunc;
3126 }
3127 //copy MPE subelmeents used by Main Function to returned object
3128 int n;
3129 MpePtrList::iterator m;
3130 for (m = m_mpeList.begin(), n = 0; m != m_mpeList.end(); m++, n++) {
3131 this->SetSubElem(n, m->m_ptr);
3132 m->m_ptr = NULL;
3133 }
3134
3135#if 0
3136 FILE *ff = fopen("flatfunc.txt", "wb");
3137 fwrite(flatFunc.c_str(), flatFunc.size(), 1, ff);
3138 fclose(ff);
3139#endif
3140
3141 icFuncParseStatus stat = SetCalcFunc(flatFunc.c_str(), parseStr);
3142 if (stat!=icFuncParseNoError) {
3143 char buf[65];
3144 int len = icIntMin(64, (int)strlen(flatFunc.c_str()));
3145 strncpy(buf, flatFunc.c_str(), len);
3146 buf[len]=0;
3147
3148 switch(stat) {
3150 parseStr += "Syntax Error occurred while parsing Main Calculator Function from \"";
3151 break;
3153 parseStr += "Invalid Operation found while parsing Main Calculator Function from \"";
3154 break;
3156 parseStr += "Stack underflow detected while parsing Main Calculator Function from \"";
3157 break;
3159 parseStr += "Invalid Channel detected while parsing Main Calculator Function from \"";
3160 break;
3161 default:
3162 parseStr += "Unable to parse Main Calculator Function from \"";
3163 }
3164 parseStr += buf;
3165 parseStr += "\"\n";
3166 return false;
3167 }
3168 }
3169 clean();
3170
3171 return true;
3172}
3173
3174
3175bool CIccMpeXmlEmissionCLUT::ToXml(std::string &xml, std::string blanks/* = ""*/)
3176{
3177 char buf[256];
3178 std::string reserved;
3179
3180 xml += blanks + "<EmissionCLutElement";
3181
3182 if (m_nReserved) {
3183 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
3184 xml += buf;
3185 }
3186
3187 sprintf(buf, " InputChannels=\"%d\" OutputChannels=\"%d\" Flags=\"%d\" StorageType=\"%d\">\n", NumInputChannels(), NumOutputChannels(), m_flags, m_nStorageType);
3188 xml += buf;
3189
3190 sprintf(buf, " <Wavelengths start=\"" icXmlHalfFmt "\" end=\"" icXmlHalfFmt "\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
3191 xml += blanks + buf;
3192
3193 int i;
3194
3195 if (m_pWhite) {
3196 xml += blanks + " <WhiteData>\n";
3197
3198 xml += blanks + " ";
3199 for (i=0; i<(int)m_Range.steps; i++) {
3200 sprintf(buf, " " icXmlFloatFmt, m_pWhite[i]);
3201 xml += buf;
3202 }
3203 xml += "\n";
3204
3205 xml += blanks + " </WhiteData>\n";
3206 }
3207
3208 if (!icCLUTDataToXml(xml, m_pCLUT, icConvertFloat, blanks, true))
3209 return false;
3210
3211 xml += blanks + "</EmissionCLutElement>\n";
3212
3213 return true;
3214}
3215
3216bool CIccMpeXmlEmissionCLUT::ParseXml(xmlNode *pNode, std::string &parseStr)
3217{
3218 m_nStorageType = (icUInt16Number)atoi(icXmlAttrValue(pNode, "StorageType", "0"));
3219
3220 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
3221 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
3222 m_flags = atoi(icXmlAttrValue(pNode, "Flags", 0));
3223
3224 if (!m_nInputChannels || !m_nOutputChannels) {
3225 parseStr += "Invalid InputChannels or OutputChannels In CLutElement\n";
3226 return false;
3227 }
3228
3229 xmlNode *pData;
3230
3231 pData = icXmlFindNode(pNode->children, "Wavelengths");
3232 if (pData) {
3233 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
3234 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
3235 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
3236
3237 if (dStart >= dEnd ||!nSteps) {
3238 parseStr += "Invalid Spectral Range\n";
3239 return false;
3240 }
3241 m_Range.start = icFtoF16(dStart);
3242 m_Range.end = icFtoF16(dEnd);
3243 m_Range.steps = nSteps;
3244 }
3245 else {
3246 parseStr += "Missing Spectral Range\n";
3247 return false;
3248 }
3249
3250 if (m_pWhite)
3251 free(m_pWhite);
3252
3253 m_pWhite = (icFloatNumber *)malloc(m_Range.steps*sizeof(icFloatNumber));
3254 if (!m_pWhite) {
3255 parseStr += "White buffer memory error\n";
3256 return false;
3257 }
3258
3259 pData = icXmlFindNode(pNode->children, "WhiteData");
3260 if (pData) {
3261
3262 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
3263 return false;
3264 }
3265 else {
3266 parseStr += "Missing White Data";
3267 }
3268
3269 if (m_pCLUT) {
3270 delete m_pCLUT;
3271 m_pCLUT = NULL;
3272 }
3273
3274 if (m_pApplyCLUT) {
3275 delete m_pApplyCLUT;
3276 m_pApplyCLUT = NULL;
3277 }
3278
3279 CIccCLUT *pCLut = icCLutFromXml(pNode, m_nInputChannels, m_Range.steps, icConvertFloat, parseStr);
3280 if (pCLut) {
3281 m_pCLUT = pCLut;
3282 return true;
3283 }
3284
3285 return false;
3286}
3287
3288bool CIccMpeXmlReflectanceCLUT::ToXml(std::string &xml, std::string blanks/* = ""*/)
3289{
3290 char buf[256];
3291 std::string reserved;
3292
3293 xml += blanks + "<ReflectanceCLutElem";
3294
3295 if (m_nReserved) {
3296 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
3297 xml += buf;
3298 }
3299
3300 sprintf(buf, " InputChannels=\"%d\" OutputChannels=\"%d\" Flags=\"%d\">\n", NumInputChannels(), NumOutputChannels(), m_flags);
3301 xml += buf;
3302
3303 sprintf(buf, " <Wavelengths start=\"" icXmlHalfFmt "\" end=\"" icXmlHalfFmt "\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
3304 xml += buf;
3305
3306 int i;
3307
3308 if (m_pWhite) {
3309 xml += blanks + " <WhiteData>\n";
3310
3311 xml += blanks + " ";
3312 for (i=0; i<(int)m_Range.steps; i++) {
3313 sprintf(buf, " " icXmlFloatFmt, m_pWhite[i]);
3314 xml += buf;
3315 }
3316 xml += "\n";
3317
3318 xml += blanks + " </WhiteData>\n";
3319 }
3320
3321 if (!icCLUTDataToXml(xml, m_pCLUT, icConvertFloat, blanks, true))
3322 return false;
3323
3324 xml += blanks + "</ReflectanceCLutElem>\n";
3325
3326 return true;
3327}
3328
3329bool CIccMpeXmlReflectanceCLUT::ParseXml(xmlNode *pNode, std::string &parseStr)
3330{
3331 m_nStorageType = (icUInt16Number)atoi(icXmlAttrValue(pNode, "StorageType", "0"));
3332
3333 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
3334 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
3335 m_flags = atoi(icXmlAttrValue(pNode, "Flags", 0));
3336
3337 if (!m_nInputChannels || !m_nOutputChannels) {
3338 parseStr += "Invalid InputChannels or OutputChannels In CLutElement\n";
3339 return false;
3340 }
3341
3342 xmlNode *pData;
3343
3344 pData = icXmlFindNode(pNode->children, "Wavelengths");
3345 if (pData) {
3346 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
3347 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
3348 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
3349
3350 if (dStart >= dEnd ||!nSteps) {
3351 parseStr += "Invalid Spectral Range\n";
3352 return false;
3353 }
3354 m_Range.start = icFtoF16(dStart);
3355 m_Range.end = icFtoF16(dEnd);
3356 m_Range.steps = nSteps;
3357 }
3358 else {
3359 parseStr += "Missing Spectral Range\n";
3360 return false;
3361 }
3362
3363 if (m_pWhite)
3364 free(m_pWhite);
3365
3366 m_pWhite = (icFloatNumber *)malloc(m_Range.steps*sizeof(icFloatNumber));
3367 if (!m_pWhite) {
3368 parseStr += "White buffer memory error\n";
3369 return false;
3370 }
3371
3372 pData = icXmlFindNode(pNode->children, "WhiteData");
3373 if (pData) {
3374
3375 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
3376 return false;
3377 }
3378 else {
3379 parseStr += "Missing WhiteData";
3380 }
3381
3382 if (m_pCLUT) {
3383 delete m_pCLUT;
3384 m_pCLUT = NULL;
3385 }
3386
3387 if (m_pApplyCLUT) {
3388 delete m_pApplyCLUT;
3389 m_pApplyCLUT = NULL;
3390 }
3391
3392 CIccCLUT *pCLut = icCLutFromXml(pNode, m_nInputChannels, m_Range.steps, icConvertFloat, parseStr);
3393 if (pCLut) {
3394 m_pCLUT = pCLut;
3395 return true;
3396 }
3397
3398 return false;
3399}
3400
3401bool CIccMpeXmlEmissionObserver::ParseXml(xmlNode *pNode, std::string &parseStr)
3402{
3403 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
3404 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
3405 m_flags = atoi(icXmlAttrValue(pNode, "Flags"));
3406
3407 if (!nInputChannels || !nOutputChannels) {
3408 parseStr += "Invalid InputChannels or OutputChannels In EmissionObserverElement\n";
3409 return false;
3410 }
3411
3412 xmlNode *pData;
3413
3414 pData = icXmlFindNode(pNode->children, "Wavelengths");
3415 if (pData) {
3416 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
3417 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
3418 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
3419
3420 if (dStart >= dEnd || nSteps != nInputChannels) {
3421 parseStr += "Invalid Spectral Range\n";
3422 return false;
3423 }
3424 m_Range.start = icFtoF16(dStart);
3425 m_Range.end = icFtoF16(dEnd);
3426 m_Range.steps = nSteps;
3427 }
3428
3429 SetSize(nInputChannels, nOutputChannels, m_Range);
3430 if (!m_pWhite) {
3431 parseStr += "Unable to SetSize\n";
3432 return false;
3433 }
3434
3435 pData = icXmlFindNode(pNode->children, "WhiteData");
3436 if (pData) {
3437
3438 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
3439 return false;
3440 }
3441 else {
3442 parseStr += "Missing White Data";
3443 }
3444
3445 return true;
3446}
3447
3448bool CIccMpeXmlEmissionObserver::ToXml(std::string &xml, std::string blanks/* = ""*/)
3449{
3450 char buf[128];
3451 sprintf(buf, "<EmissionObserverElement InputChannels=\"%d\" OutputChannels=\"%d\" Flags=\"%d\"", NumInputChannels(), NumOutputChannels(), m_flags);
3452 xml += blanks + buf;
3453
3454 if (m_nReserved) {
3455 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
3456 xml += buf;
3457 }
3458 xml += ">\n";
3459
3460 sprintf(buf, " <Wavelengths start=\"" icXmlHalfFmt "\" end=\"" icXmlHalfFmt "\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
3461 xml += buf;
3462
3463 int i;
3464
3465 if (m_pWhite) {
3466 xml += blanks + " <WhiteData>\n";
3467
3468 xml += blanks + " ";
3469 for (i=0; i<(int)m_Range.steps; i++) {
3470 sprintf(buf, " " icXmlFloatFmt, m_pWhite[i]);
3471 xml += buf;
3472 }
3473 xml += "\n";
3474
3475 xml += blanks + " </WhiteData>\n";
3476 }
3477
3478 xml += blanks + "</EmissionObserverElement>\n";
3479
3480 return true;
3481}
3482
3483bool CIccMpeXmlReflectanceObserver::ParseXml(xmlNode *pNode, std::string &parseStr)
3484{
3485 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
3486 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
3487 m_flags = atoi(icXmlAttrValue(pNode, "Flags"));
3488
3489 if (!nInputChannels || !nOutputChannels) {
3490 parseStr += "Invalid InputChannels or OutputChannels In ReflectanceObserverElement\n";
3491 return false;
3492 }
3493
3494 xmlNode *pData;
3495
3496 pData = icXmlFindNode(pNode->children, "Wavelengths");
3497 if (pData) {
3498 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
3499 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
3500 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
3501
3502 if (dStart >= dEnd || nSteps != nInputChannels) {
3503 parseStr += "Invalid Spectral Range\n";
3504 return false;
3505 }
3506 m_Range.start = icFtoF16(dStart);
3507 m_Range.end = icFtoF16(dEnd);
3508 m_Range.steps = nSteps;
3509 }
3510
3511 SetSize(nInputChannels, nOutputChannels, m_Range);
3512 if (!m_pWhite) {
3513 parseStr += "Unable to SetSize\n";
3514 return false;
3515 }
3516
3517 pData = icXmlFindNode(pNode->children, "WhiteData");
3518 if (pData) {
3519
3520 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
3521 return false;
3522 }
3523 else {
3524 parseStr += "Missing White Data";
3525 }
3526
3527 return true;
3528}
3529
3530bool CIccMpeXmlReflectanceObserver::ToXml(std::string &xml, std::string blanks/* = ""*/)
3531{
3532 char buf[128];
3533 sprintf(buf, "<ReflectanceObserverElement InputChannels=\"%d\" OutputChannels=\"%d\" Flags=\"%d\"", NumInputChannels(), NumOutputChannels(), m_flags);
3534 xml += blanks + buf;
3535
3536 if (m_nReserved) {
3537 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
3538 xml += buf;
3539 }
3540 xml += ">\n";
3541
3542 sprintf(buf, " <Wavelengths start=\"" icXmlHalfFmt "\" end=\"" icXmlHalfFmt "\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
3543 xml += buf;
3544
3545 int i;
3546
3547 if (m_pWhite) {
3548 xml += blanks + " <WhiteData>\n";
3549
3550 xml += blanks + " ";
3551 for (i=0; i<(int)m_Range.steps; i++) {
3552 sprintf(buf, " " icXmlFloatFmt, m_pWhite[i]);
3553 xml += buf;
3554 }
3555 xml += "\n";
3556
3557 xml += blanks + " </WhiteData>\n";
3558 }
3559
3560 xml += blanks + "</ReflectanceObserverElement>\n";
3561
3562 return true;
3563}
3564
3565#ifdef USEREFICCMAXNAMESPACE
3566}
3567#endif
File: IccCAM.h.
float icFloatNumber
All floating point operations/variables in IccProfLib use the icFloatNumber data type.
Definition IccDefs.h:100
char icChar
Definition IccDefs.h:109
#define ICFLOATSFX
String formating macros need to match precision of icFloatNumber If precision is double change the "f...
Definition IccDefs.h:105
CIccIO * IccOpenFileIO(const icChar *szFilename, const char *szAttr)
Definition IccIoXml.cpp:100
File: IccIoXml.h.
icFuncParseStatus
Definition IccMpeCalc.h:308
@ icFuncParseSyntaxError
Definition IccMpeCalc.h:310
@ icFuncParseNoError
Definition IccMpeCalc.h:309
@ icFuncParseStackUnderflow
Definition IccMpeCalc.h:312
@ icFuncParseInvalidOperation
Definition IccMpeCalc.h:311
@ icFuncParseInvalidChannel
Definition IccMpeCalc.h:314
static icCurveSetCurvePtr ParseXmlCurve(xmlNode *pNode, std::string parseStr)
static char * icSegPos(char *buf, icFloatNumber pos)
static bool icXmlParseColorAppearanceParams(xmlNode *pNode, std::string &parseStr, CIccCamConverter *pCam)
static bool icXmlDumpColorAppearanceParams(std::string &xml, std::string blanks, CIccCamConverter *pCam)
CIccCLUT * icCLutFromXml(xmlNode *pNode, int nIn, int nOut, icConvertType nType, std::string &parseStr)
static bool ToXmlCurve(std::string &xml, std::string blanks, icCurveSetCurvePtr pCurve)
icFloatNumber icGetSegPos(const char *str)
File: IccMpeXml.h.
std::pair< int, int > IndexSizePair
Definition IccMpeXml.h:282
std::map< std::string, IndexSizePair > ChanVarMap
Definition IccMpeXml.h:283
#define stricmp
IIccMatrixInverter * IccGetDefaultMatrixInverter()
Name: IccGetDefaultMatrixInverter()
Definition IccSolve.cpp:287
const icChar * szName
File: IccTagXml.h.
icFloat16Number icFtoF16(icFloat32Number num)
Definition IccUtil.cpp:673
icUInt32Number icIntMin(icUInt32Number v1, icUInt32Number v2)
Definition IccUtil.cpp:908
icUInt32Number icGetSigVal(const icChar *pBuf)
Definition IccUtil.cpp:1258
icFloatNumber icF16toF(icFloat16Number num)
Definition IccUtil.cpp:629
const icChar * icGetSigStr(icChar *pBuf, icUInt32Number nSig)
Definition IccUtil.cpp:1056
#define icNotZero(v)
Definition IccUtil.h:89
icUInt32Number icXmlGetHexDataSize(const char *szText)
xmlAttr * icXmlFindAttr(xmlNode *pNode, const char *szAttrName)
xmlNode * icXmlFindNode(xmlNode *pNode, const char *szNodeName)
icUInt32Number icXmlGetHexData(void *pBuf, const char *szText, icUInt32Number nBufSize)
icTagTypeSignature icGetTypeNameTagSig(const icChar *szTagType)
const icChar * icGetTagSigTypeName(icTagTypeSignature tagTypeSig)
icUInt32Number icXmlDumpHexData(std::string &xml, std::string blanks, void *pBuf, icUInt32Number nBufSize)
bool icCLUTDataToXml(std::string &xml, CIccCLUT *pCLUT, icConvertType nType, std::string blanks, bool bSaveGridPoints)
const char * icFixXml(std::string &buf, const char *szStr)
const char * icXmlAttrValue(xmlAttr *attr, const char *szDefault)
icSignature icXmlStrToSig(const char *szStr)
bool icCLUTToXml(std::string &xml, CIccCLUT *pCLUT, icConvertType nType, std::string blanks, bool bSaveGridPoints, const char *szExtraAttrs, const char *szName)
File: IccUtilXml.cpp.
#define icXmlStrCmp(x, y)
Definition IccUtilXml.h:134
icConvertType
@ icConvertFloat
#define icXmlHalfFmt
#define icXmlFloatFmt
icTagTypeSignature
unsigned int icUInt32Number
Class: CIccCLUT.
Definition IccTagLut.h:326
void SetParameter_Nc(icFloatNumber Nc)
Definition IccCAM.cpp:402
void SetParameter_La(icFloatNumber La)
Definition IccCAM.cpp:375
void SetParameter_F(icFloatNumber F)
Definition IccCAM.cpp:411
void GetParameter_WhitePoint(icFloatNumber *whitePoint)
Definition IccCAM.cpp:420
void SetParameter_C(icFloatNumber c)
Definition IccCAM.cpp:393
icFloatNumber GetParameter_C()
Definition IccCAM.cpp:446
icFloatNumber GetParameter_Nc()
Definition IccCAM.cpp:454
icFloatNumber GetParameter_Yb()
Definition IccCAM.cpp:438
icFloatNumber GetParameter_F()
Definition IccCAM.cpp:462
void SetParameter_Yb(icFloatNumber YB)
Definition IccCAM.cpp:384
icFloatNumber GetParameter_La()
Definition IccCAM.cpp:430
void SetParameter_WhitePoint(icFloatNumber *whitePoint)
Definition IccCAM.cpp:364
Class: CIccCurveSegment.
Definition IccMpeBasic.h:95
virtual icCurveSegSignature GetType() const =0
Class: CIccCurveSetCurve.
virtual icCurveElemSignature GetType() const =0
Class: CIccTagFormulaCurveSegment.
CIccFormulaCurveSegmentXml(icFloatNumber start, icFloatNumber end)
bool ToXml(std::string &xml, std::string blanks)
bool ParseXml(xmlNode *pNode, std::string &parseStr)
bool GetIndex(icUInt16Number &v1, icUInt16Number &v2, icUInt16Number initV1=0, icUInt16Number initV2=0)
std::string GetName() const
std::string & GetLast()
Definition IccMpeCalc.h:341
std::string GetReference() const
bool GetNext(bool bForceNoRefs=false)
Type: Class.
Definition IccIO.h:97
icInt32Number ReadFloat32Float(void *pBufFloat, icInt32Number nNum=1)
Definition IccIO.cpp:302
virtual icInt32Number GetLength()
Definition IccIO.h:130
virtual icInt32Number Read8(void *pBuf8, icInt32Number nNum=1)
Definition IccIO.h:104
icInt32Number Read16(void *pBuf16, icInt32Number nNum=1)
Definition IccIO.cpp:114
Type: Class.
Definition IccUtil.h:303
const icChar * GetTagTypeSigName(icTagTypeSignature sig)
Definition IccUtil.cpp:1594
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
bool ParseChanMap(ChanVarMap &chanMap, const char *szNames, int nChannels)
std::string m_sImport
Definition IccMpeXml.h:329
bool UpdateLocals(std::string &func, std::string szFunc, std::string &parseStr, int nLocalsOffset)
bool Flatten(std::string &flatStr, std::string macroName, const char *szFunc, std::string &parseStr, icUInt32Number nLocalsOffset=0)
bool ParseImport(xmlNode *pNode, std::string importPath, std::string &parseStr)
bool ValidMacroCalls(const char *szMacroText, std::string macroStack, std::string &parseStr) const
bool ValidateMacroCalls(std::string &parseStr) const
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
static bool validNameChar(char c, bool bFirst)
static bool validName(const char *saName)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)=0
virtual bool ToXml(std::string &xml, std::string blanks="")=0
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ToXml(std::string &xml, std::string blanks="")
Definition IccMpeXml.cpp:83
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
Class: CIccMultiProcessElement.
Definition IccTagMPE.h:146
virtual IIccExtensionMpe * GetExtension()
Definition IccTagMPE.h:182
virtual const icChar * GetClassName() const =0
icUInt32Number m_nReserved
Definition IccTagMPE.h:188
Class: CIccSampledCalculatorCurve.
bool ToXml(std::string &xml, std::string blanks)
bool ParseXml(xmlNode *pNode, std::string &parseStr)
CIccSampledCalculatorCurveXml(icFloatNumber first=0, icFloatNumber last=0)
Class: CIccSampledCurveSegment.
bool ParseXml(xmlNode *pNode, std::string &parseStr)
CIccSampledCurveSegmentXml(icFloatNumber start, icFloatNumber end)
bool ToXml(std::string &xml, std::string blanks)
bool ParseXml(xmlNode *pNode, std::string &parseStr)
bool ToXml(std::string &xml, std::string blanks)
CIccSinglSampledeCurveXml(icFloatNumber first=0, icFloatNumber last=0)
bool ParseXml(xmlNode *pNode, std::string &parseStr)
bool ToXml(std::string &xml, std::string blanks)
Class: CIccSingleSampledCurve.
Class: CIccTag.
icUInt32Number m_nReserved
static CIccTag * Create(icTagTypeSignature sig)
Name: CIccTag::Create.
virtual bool IsNumArrayType() const
virtual IIccExtensionTag * GetExtension()
Class: CIccTagNumArray.
virtual bool ToXml(std::string &xml, std::string blanks="")=0
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)=0
static CIccMultiProcessElement * CreateElement(const icChar *szElementNodeName)
icUInt16Number m_size
Definition IccMpeXml.h:292
TempVarList m_members
Definition IccMpeXml.h:294
Class: CIccToneMapFunc.
static bool ParseArray(T *buf, icUInt32Number nBufSize, xmlNode *pNode)
bool ParseTextArrayNum(const char *szText, icUInt32Number num, std::string &parseStr)
static bool DumpArray(std::string &xml, std::string blanks, T *buf, icUInt32Number nBufSize, icConvertType nType, icUInt8Number nColumns)
icUInt32Number GetSize()
Definition IccUtilXml.h:166
virtual CIccToneMapFunc * NewCopy()
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)
virtual bool ToXml(std::string &xml, std::string blanks="")
virtual const char * GetExtClassName()=0
virtual const char * GetExtClassName() const =0
Structure: IIccMatrixInverter.
Definition IccSolve.h:149
virtual bool Invert(icFloatNumber *dMatrix, icUInt16Number nRows, icUInt16Number nCols)=0
Member Function: Invert.
@ icSigSegmentedCurve
@ icSigSampledCalculatorCurve
@ icSigSingleSampledCurve
unsigned char icUInt8Number
Number definitions.
float icFloat32Number
#define icSigUnknownType
Convenience Enum Definitions - Not defined in ICC specification.
unsigned short icUInt16Number
@ icSigSampledCurveSeg
@ icSigFormulaCurveSeg
icUInt16Number icFloat16Number
IEEE float storage numbers.
icElemTypeSignature
Multi-Processing Element type signatures.
icUInt32Number icSignature
@ icClipSingleSampledCurve
#define icMinFloat32Number
@ icValueTypeFloat16
@ icValueTypeUInt8
@ icValueTypeUInt16
@ icValueTypeFloat32
#define icMaxFloat32Number
Useful macros for defining Curve Segment breakpoints.