Hoyt's FORK of DemoIccMAX 2.1.17.hoyt
Documentation for Hoyt's FORK of DemoIccMAX
Loading...
Searching...
No Matches
IccProfileXml.cpp
Go to the documentation of this file.
1/** @file
2 File: IccProfileXml.cpp
3
4 Contains: Implementation Icc Profile XML format conversions
5
6 Version: V1
7
8 Copyright: (c) see ICC Software License
9*/
10
11/*
12 * The ICC Software License, Version 0.2
13 *
14 *
15 * Copyright (c) 2003-2012 The International Color Consortium. All rights
16 * reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
29 *
30 * 3. In the absence of prior written permission, the names "ICC" and "The
31 * International Color Consortium" must not be used to imply that the
32 * ICC organization endorses or promotes products derived from this
33 * software.
34 *
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
40 * ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This software consists of voluntary contributions made by many
51 * individuals on behalf of the The International Color Consortium.
52 *
53 *
54 * Membership in the ICC is encouraged when this software is used for
55 * commercial purposes.
56 *
57 *
58 * For more information on The International Color Consortium, please
59 * see <http://www.color.org/>.
60 *
61 *
62 */
63#include "stdio.h"
64#include "IccProfileXml.h"
65#include "IccTagXml.h"
66#include "IccUtilXml.h"
67#include "IccArrayBasic.h"
68#include <set>
69#include <cstring> /* C strings strcpy, memcpy ... */
70#include <map>
71
72typedef std::map<icUInt32Number, icTagSignature> IccOffsetTagSigMap;
73
74bool CIccProfileXml::ToXml(std::string &xml)
75{
76 CIccInfo info;
77
78 xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
79 return ToXmlWithBlanks(xml, "");
80}
81
82bool CIccProfileXml::ToXmlWithBlanks(std::string &xml, std::string blanks)
83{
84 CIccInfo info;
85 char line[256];
86 char buf[256];
87 char fix[256];
88 int n;
89 bool nonzero;
90
91 xml += blanks + "<IccProfile>\n";
92 xml += blanks + " <Header>\n";
93 sprintf(line, " <PreferredCMMType>%s</PreferredCMMType>\n", icFixXml(fix, icGetColorSigStr(buf, m_Header.cmmId)));
94 xml += blanks + line;
95 sprintf(line, " <ProfileVersion>%s</ProfileVersion>\n", info.GetVersionName(m_Header.version));
96 xml += blanks + line;
97 if (m_Header.version & 0x0000ffff) {
98 sprintf(line, " <ProfileSubClassVersion>%s</ProfileSubClassVersion>\n", info.GetSubClassVersionName(m_Header.version));
99 xml += blanks + line;
100 }
101 sprintf(line, " <ProfileDeviceClass>%s</ProfileDeviceClass>\n", icFixXml(fix, icGetSigStr(buf, m_Header.deviceClass)));
102 xml += blanks + line;
103
104 if (m_Header.deviceSubClass) {
105 sprintf(line, " <ProfileDeviceSubClass>%s</ProfileDeviceSubClass>\n", icFixXml(fix, icGetSigStr(buf, m_Header.deviceSubClass)));
106 xml += blanks + line;
107 }
108
109 sprintf(line, " <DataColourSpace>%s</DataColourSpace>\n", icFixXml(fix, icGetColorSigStr(buf, m_Header.colorSpace)));
110 xml += blanks + line;
111 sprintf(line, " <PCS>%s</PCS>\n", icFixXml(fix, icGetColorSigStr(buf, m_Header.pcs)));
112 xml += blanks + line;
113
114 sprintf(line, " <CreationDateTime>%d-%02d-%02dT%02d:%02d:%02d</CreationDateTime>\n",
115 m_Header.date.year,
116 m_Header.date.month,
117 m_Header.date.day,
118 m_Header.date.hours,
119 m_Header.date.minutes,
120 m_Header.date.seconds);
121 xml += blanks + line;
122
123 // if (m_Header.magic != 0){
124 // sprintf(line, " <Signature>%s</Signature>\n", icFixXml(fix, icGetSigStr(buf, m_Header.magic)));
125 // xml += line;
126 // }
127
128 if (m_Header.platform != icSigUnkownPlatform){
129 sprintf(line, " <PrimaryPlatform>%s</PrimaryPlatform>\n", icFixXml(fix, icGetSigStr(buf, m_Header.platform)));
130 xml += blanks + line;
131 }
132
133 xml+= blanks + " ";
134 xml+= icGetHeaderFlagsName(m_Header.flags, m_Header.mcs!=0);
135
136 if (m_Header.manufacturer != 0){
137 sprintf(line, " <DeviceManufacturer>%s</DeviceManufacturer>\n", icFixXml(fix, icGetSigStr(buf, m_Header.manufacturer)));
138 xml += blanks + line;
139 }
140
141 if (m_Header.model != 0){
142 sprintf(line, " <DeviceModel>%s</DeviceModel>\n", icFixXml(fix, icGetSigStr(buf, m_Header.model)));
143 xml += blanks + line;
144 }
145
146 xml+= " ";
147 xml += blanks + icGetDeviceAttrName(m_Header.attributes);
148
149 sprintf(line, " <RenderingIntent>%s</RenderingIntent>\n", info.GetRenderingIntentName((icRenderingIntent)m_Header.renderingIntent, m_Header.version>=icVersionNumberV5));
150 xml += blanks + line;
151 sprintf(line, " <PCSIlluminant>\n%s <XYZNumber X=\"" icXmlFloatFmt "\" Y=\"" icXmlFloatFmt "\" Z=\"" icXmlFloatFmt "\"/>\n%s </PCSIlluminant>\n", blanks.c_str(),
152 (float)icFtoD(m_Header.illuminant.X),
153 (float)icFtoD(m_Header.illuminant.Y),
154 (float)icFtoD(m_Header.illuminant.Z),
155 blanks.c_str());
156
157 xml += blanks + line;
158
159 sprintf(line, " <ProfileCreator>%s</ProfileCreator>\n", icFixXml(fix, icGetSigStr(buf, m_Header.creator)));
160 xml += blanks + line;
161
162 if (m_Header.profileID.ID32[0] || m_Header.profileID.ID32[1] ||
163 m_Header.profileID.ID32[2] || m_Header.profileID.ID32[3]) {
164 xml += blanks;
165 for (n=0; n<16; n++) {
166 sprintf(buf + n*2, "%02X", m_Header.profileID.ID8[n]);
167 }
168 buf[n*2]='\0';
169 xml += " <ProfileID>";
170 xml += buf;
171 xml += "</ProfileID>\n";
172 }
173 nonzero = false;
174
175 if (m_Header.spectralPCS) {
176 sprintf(line, " <SpectralPCS>%s</SpectralPCS>\n", icFixXml(fix, icGetColorSigStr(buf, m_Header.spectralPCS)));
177 xml += blanks + line;
178
179 if (m_Header.spectralRange.steps) {
180 xml += blanks + " <SpectralRange>\n";
181 sprintf(line, " <Wavelengths start=\"" icXmlHalfFmt "\" end=\"" icXmlHalfFmt "\" steps=\"%d\"/>\n",
182 icF16toF(m_Header.spectralRange.start), icF16toF(m_Header.spectralRange.end), m_Header.spectralRange.steps);
183 xml += blanks + line;
184 xml += blanks + " </SpectralRange>\n";
185 }
186 if (m_Header.biSpectralRange.steps) {
187 xml += blanks + " <BiSpectralRange>\n";
188 sprintf(line, " <Wavelengths start=\"" icXmlHalfFmt "\" end=\"" icXmlHalfFmt "\" steps=\"%d\"/>\n)",
189 icF16toF(m_Header.biSpectralRange.start), icF16toF(m_Header.biSpectralRange.end), m_Header.biSpectralRange.steps);
190 xml += blanks + line;
191 xml += blanks + " </BiSpectralRange>\n";
192 }
193 }
194
195 if (m_Header.mcs) {
196 sprintf(line, " <MCS>%s</MCS>\n", icFixXml(fix, icGetColorSigStr(buf, m_Header.mcs)));
197 xml += blanks + line;
198 }
199
200 for (n=0; n<sizeof(m_Header.reserved); n++) {
201 if (m_Header.reserved[n])
202 nonzero = true;
203 sprintf(buf + n*2, "%02X", m_Header.reserved[n]);
204 }
205 buf[n*2]='\0';
206 if (nonzero) {
207 xml += blanks + " <Reserved>";
208 xml += buf;
209 xml += "</Reserved>\n";
210 }
211 xml += blanks + " </Header>\n";
212
213 xml += blanks + " <Tags>\n";
214 TagEntryList::iterator i, j;
215 std::set<icTagSignature> sigSet;
216 CIccInfo Fmt;
217 IccOffsetTagSigMap offsetTags;
218
219 for (i=m_Tags->begin(); i!=m_Tags->end(); i++) {
220 if (sigSet.find(i->TagInfo.sig)==sigSet.end()) {
221 CIccTag *pTag = FindTag(i->TagInfo.sig);
222
223 if (pTag) {
224 CIccTagXml *pTagXml = (CIccTagXml*)(pTag->GetExtension());
225 if (pTagXml) {
226 IccOffsetTagSigMap::iterator prevTag = offsetTags.find(i->TagInfo.offset);
227 const icChar *tagName = Fmt.GetTagSigName(i->TagInfo.sig);
228 if (prevTag == offsetTags.end()) {
229 const icChar* tagSig = icGetTagSigTypeName(pTag->GetType());
230
231 if (tagName && strncmp(tagName, "Unknown ", 8)) {
232 sprintf(line, " <%s> ", icFixXml(fix, tagName));
233 }
234 else {
235 sprintf(line, " <PrivateTag TagSignature=\"%s\"> ", icFixXml(fix, icGetSigStr(buf, i->TagInfo.sig)));
236 tagName = "PrivateTag";
237 }
238 xml += blanks + line;
239 // PrivateType - a type that does not belong to the list in the icc specs - custom for vendor.
240 if (!strcmp("PrivateType", tagSig))
241 sprintf(line, "<PrivateType type=\"%s\">\n", icFixXml(fix, icGetSigStr(buf, pTag->GetType())));
242 else
243 sprintf(line, "<%s>\n", tagSig); //parent node is the tag type
244
245 xml += line;
246 j = i;
247#if 0
248 // print out the tag signature (there is at least one)
249 sprintf(line, " <TagSignature>%s</TagSignature>\n", icFixXml(fix, icGetSigStr(buf, i->TagInfo.sig)));
250 xml += line;
251
252 sigSet.insert(i->TagInfo.sig);
253
254 // print out the rest of the tag signatures
255 for (j++; j != m_Tags->end(); j++) {
256 if (j->pTag == i->pTag || j->TagInfo.offset == i->TagInfo.offset) {
257 sprintf(line, " <TagSignature>%s</TagSignature>\n", icFixXml(fix, icGetSigStr(buf, j->TagInfo.sig)));
258 xml += line;
259 sigSet.insert(j->TagInfo.sig);
260 }
261 }
262#endif
263 //convert the rest of the tag to xml
264 if (!pTagXml->ToXml(xml, blanks + " ")) {
265 printf("Unable to output tag with type %s\n", icGetSigStr(buf, i->TagInfo.sig));
266 return false;
267 }
268 sprintf(line, " </%s> </%s>\n\n", tagSig, tagName);
269 xml += blanks + line;
270 offsetTags[i->TagInfo.offset] = i->TagInfo.sig;
271 }
272 else {
273 const icChar *prevTagName = Fmt.GetTagSigName(prevTag->second);
274 char nameBuf[200], fix2[200];
275 if (!prevTagName || !strncmp(prevTagName, "Unknown ", 8)) {
276 strcpy(nameBuf, "PrivateTag");
277 prevTagName = nameBuf;
278 }
279
280 if (tagName && strncmp(tagName, "Unknown ", 8))
281 sprintf(line, " <%s SameAs=\"%s\"", icFixXml(fix, tagName), icFixXml(fix2, prevTagName)); //parent node is the tag type
282 else
283 sprintf(line, " <PrivateTag TagSignature=\"%s\" SameAs=\"%s\"", icFixXml(fix2, icGetSigStr(buf, i->TagInfo.sig)), icFixXml(fix, prevTagName));
284
285 xml += blanks + line;
286 if (prevTagName == nameBuf) {
287 sprintf(line, " SameAsSignature=\"%s\"", icFixXml(fix2, icGetSigStr(buf, prevTag->second)));
288 xml += blanks + line;
289 }
290
291 xml += "/>\n\n";
292 }
293 }
294 else {
295 printf("Non XML tag in list with tag %s!\n", icGetSigStr(buf, i->TagInfo.sig));
296 return false;
297 }
298 }
299 else {
300 printf("Unable to find tag with tag %s!\n", icGetSigStr(buf, i->TagInfo.sig));
301 return false;
302 }
303 }
304 }
305 xml += blanks + " </Tags>\n";
306 xml += blanks + "</IccProfile>\n";
307
308 return true;
309}
310
311static unsigned char parseVersion(const char *szVer)
312{
313 unsigned char rv;
314 int val = atoi(szVer);
315 rv = ((val / 10) % 10) * 16 + (val % 10);
316
317 return rv;
318}
319
320/**
321*****************************************************************************
322* Name: CIccProfileXml::ParseBasic
323*
324* Purpose: Parse ICC header.
325*
326* Args:
327* pNode - pointer to xmlNode object to read data with
328*
329* Return:
330* true - valid ICC header, false - failure
331******************************************************************************
332*/
333bool CIccProfileXml::ParseBasic(xmlNode *pNode, std::string &parseStr)
334{
335 std::string temp;
336 memset(&m_Header, 0, sizeof(m_Header));
337
338 for (pNode=pNode->children; pNode; pNode=pNode->next) {
339 if (pNode->type==XML_ELEMENT_NODE) {
340 if (!icXmlStrCmp((const char*)pNode->name, "ProfileVersion")) {
341 const char *szVer = (const char*)pNode->children->content;
342 std::string ver;
343 unsigned long verMajor=0, verMinor=0, verClassMajor=0, verClassMinor=0;
344
345 for (; *szVer && *szVer != '.' && *szVer != ','; szVer++) {
346 ver += *szVer;
347 }
348 verMajor = parseVersion(ver.c_str());
349 ver.clear();
350 if (*szVer)
351 szVer++;
352
353 if (*szVer) {
354 for (; *szVer && *szVer != '.' && *szVer != ','; szVer++) {
355 ver += *szVer;
356 }
357 verMinor = parseVersion(ver.c_str());
358 ver.clear();
359 if (*szVer)
360 szVer++;
361
362 if (*szVer) {
363 for (; *szVer && *szVer != '.' && *szVer != ','; szVer++) {
364 ver = *szVer;
365 }
366 verClassMajor = parseVersion(ver.c_str());
367 ver.clear();
368 if (*szVer)
369 szVer++;
370
371 if (*szVer) {
372 for (; *szVer && *szVer != '.' && *szVer != ','; szVer++) {
373 ver = *szVer;
374 }
375 verClassMinor = parseVersion(ver.c_str());
376 ver.clear();
377 }
378 }
379 }
380
381 m_Header.version = (verMajor << 24) | (verMinor << 16) | (verClassMajor << 8) | verClassMinor;
382 }
383 else if (!icXmlStrCmp((const char*)pNode->name, "ProfileSubClassVersion")) {
384 const char *szVer = (const char*)pNode->children->content;
385 std::string ver;
386 unsigned long verClassMajor = 0, verClassMinor = 0;
387
388 for (; *szVer && *szVer != '.' && *szVer != ','; szVer++) {
389 ver = *szVer;
390 }
391 verClassMajor = (unsigned char)atoi(ver.c_str());
392 ver.clear();
393
394 if (szVer) {
395 for (; *szVer && *szVer != '.' && *szVer != ','; szVer++) {
396 ver = *szVer;
397 }
398 verClassMinor = (unsigned char)atoi(ver.c_str());
399 }
400
401 m_Header.version = (m_Header.version & 0xffff0000) | (((verClassMajor << 8) | verClassMinor) & 0x0000ffff);
402 }
403 else if (!icXmlStrCmp(pNode->name, "PreferredCMMType")) {
404 m_Header.cmmId = icXmlGetChildSigVal(pNode);
405 }
406 else if (!icXmlStrCmp(pNode->name, "ProfileDeviceClass")) {
407 m_Header.deviceClass = (icProfileClassSignature)icXmlGetChildSigVal(pNode);
408 }
409 else if (!icXmlStrCmp(pNode->name, "ProfileDeviceSubClass")) {
410 m_Header.deviceSubClass = (icSignature)icXmlGetChildSigVal(pNode);
411 }
412 else if (!icXmlStrCmp(pNode->name, "DataColourSpace")) {
413 m_Header.colorSpace = (icColorSpaceSignature)icXmlGetChildSigVal(pNode);
414 }
415 else if (!icXmlStrCmp(pNode->name, "PCS")) {
416 m_Header.pcs = (icColorSpaceSignature)icXmlGetChildSigVal(pNode);
417 }
418 else if (!icXmlStrCmp(pNode->name, "CreationDateTime")) {
419 if (pNode && pNode->children && pNode->children->content) {
420 const char *datetime = (const char*)pNode->children->content;
421 m_Header.date = icGetDateTimeValue(datetime);
422 }
423 else
424 memset(&m_Header.date, 0, sizeof(m_Header.date));
425 }
426 else if (!icXmlStrCmp(pNode->name, "PrimaryPlatform")) {
427 m_Header.platform = (icPlatformSignature)icXmlGetChildSigVal(pNode);
428 }
429 else if (!icXmlStrCmp(pNode->name, "ProfileFlags")) {
430 m_Header.flags = 0;
431 xmlAttr *attr = icXmlFindAttr(pNode, "EmbeddedInFile");
432 if (attr && !strcmp(icXmlAttrValue(attr), "true")) {
433 m_Header.flags |= icEmbeddedProfileTrue;
434 }
435
436 attr = icXmlFindAttr(pNode, "UseWithEmbeddedDataOnly");
437 if (attr && !strcmp(icXmlAttrValue(attr), "true")) {
438 m_Header.flags |= icUseWithEmbeddedDataOnly;
439 }
440
441 attr = icXmlFindAttr(pNode, "ExtendedRangePCS");
442 if (attr && !strcmp(icXmlAttrValue(attr), "true")) {
443 m_Header.flags |= icExtendedRangePCS;
444 }
445
446 attr = icXmlFindAttr(pNode, "MCSNeedsSubset");
447 if (attr && !strcmp(icXmlAttrValue(attr), "true")) {
448 m_Header.flags |= icMCSNeedsSubsetTrue;
449 }
450
451 attr = icXmlFindAttr(pNode, "VendorFlags");
452 if (attr) {
453 icUInt32Number vendor;
454 sscanf(icXmlAttrValue(attr), "%x", &vendor);
455 m_Header.flags |= vendor;
456 }
457 }
458 else if (!icXmlStrCmp(pNode->name, "DeviceManufacturer")) {
459 m_Header.manufacturer = icXmlGetChildSigVal(pNode);
460 }
461 else if (!icXmlStrCmp(pNode->name, "DeviceModel")) {
462 m_Header.model = icXmlGetChildSigVal(pNode);
463 }
464 else if (!icXmlStrCmp(pNode->name, "DeviceAttributes")) {
465 m_Header.attributes = icGetDeviceAttrValue(pNode);
466 }
467 else if (!icXmlStrCmp(pNode->name, "RenderingIntent")) {
468 if (!strcmp((const char*)pNode->children->content, "Perceptual"))
469 m_Header.renderingIntent = icPerceptual;
470 else if (!strcmp((const char*)pNode->children->content, "Relative Colorimetric") || !strcmp((const char*)pNode->children->content, "Relative"))
471 m_Header.renderingIntent = icRelativeColorimetric;
472 else if (!strcmp((const char*)pNode->children->content, "Saturation"))
473 m_Header.renderingIntent = icSaturation;
474 else if (!strcmp((const char*)pNode->children->content, "Absolute Colorimetric") || !strcmp((const char*)pNode->children->content, "Absolute"))
475 m_Header.renderingIntent = icAbsoluteColorimetric;
476
477 }
478 else if (!icXmlStrCmp(pNode->name, "PCSIlluminant")) {
479 xmlNode *xyzNode = icXmlFindNode(pNode->children, "XYZNumber");
480
481 xmlAttr *x = icXmlFindAttr(xyzNode, "X");
482 xmlAttr *y = icXmlFindAttr(xyzNode, "Y");
483 xmlAttr *z = icXmlFindAttr(xyzNode, "Z");
484
485 if (x && y && z) {
486 m_Header.illuminant.X = icDtoF((icFloatNumber)atof(icXmlAttrValue(x)));
487 m_Header.illuminant.Y = icDtoF((icFloatNumber)atof(icXmlAttrValue(y)));
488 m_Header.illuminant.Z = icDtoF((icFloatNumber)atof(icXmlAttrValue(z)));
489 }
490 }
491 else if (!icXmlStrCmp(pNode->name, "ProfileCreator")) {
492 m_Header.creator = icXmlGetChildSigVal(pNode);
493 }
494 else if (!icXmlStrCmp(pNode->name, "ProfileID")) {
495 if (pNode->children && pNode->children->content)
496 icXmlGetHexData(&m_Header.profileID.ID8, (const char*)pNode->children->content, sizeof(m_Header.profileID.ID8));
497 else
498 memset(&m_Header.profileID.ID8, 0, sizeof(m_Header.profileID.ID8));
499 }
500 else if (!icXmlStrCmp(pNode->name, "SpectralPCS")) {
501 m_Header.spectralPCS = (icSpectralColorSignature)icXmlGetChildSigVal(pNode);
502 }
503 else if (!icXmlStrCmp(pNode->name, "SpectralRange")) {
504 xmlNode *xyzNode = icXmlFindNode(pNode->children, "Wavelengths");
505
506 xmlAttr *start = icXmlFindAttr(xyzNode, "start");
507 xmlAttr *end = icXmlFindAttr(xyzNode, "end");
508 xmlAttr *steps = icXmlFindAttr(xyzNode, "steps");
509
510 if (start && end && steps) {
511 m_Header.spectralRange.start = icFtoF16((icFloatNumber)atof(icXmlAttrValue(start)));
512 m_Header.spectralRange.end = icFtoF16((icFloatNumber)atof(icXmlAttrValue(end)));
513 m_Header.spectralRange.steps = (icUInt16Number)atoi(icXmlAttrValue(steps));
514 }
515 }
516 else if (!icXmlStrCmp(pNode->name, "BiSpectralRange")) {
517 xmlNode *xyzNode = icXmlFindNode(pNode->children, "Wavelengths");
518
519 xmlAttr *start = icXmlFindAttr(xyzNode, "start");
520 xmlAttr *end = icXmlFindAttr(xyzNode, "end");
521 xmlAttr *steps = icXmlFindAttr(xyzNode, "steps");
522
523 if (start && end && steps) {
524 m_Header.biSpectralRange.start = icFtoF16((icFloatNumber)atof(icXmlAttrValue(start)));
525 m_Header.biSpectralRange.end = icFtoF16((icFloatNumber)atof(icXmlAttrValue(end)));
526 m_Header.biSpectralRange.steps = (icUInt16Number)atoi(icXmlAttrValue(steps));
527 }
528 }
529 else if (!icXmlStrCmp(pNode->name, "MCS")) {
530 m_Header.mcs = (icMaterialColorSignature)icXmlGetChildSigVal(pNode);
531 }
532 else if (!icXmlStrCmp(pNode->name, "ProfileDeviceSubClass")) {
533 m_Header.deviceSubClass = (icProfileClassSignature)icXmlGetChildSigVal(pNode);
534 }
535 else if (!icXmlStrCmp(pNode->name, "Reserved")) {
536 if (pNode->children && pNode->content)
537 icXmlGetHexData(&m_Header.reserved, (const char*)pNode->children->content, sizeof(m_Header.reserved));
538 else
539 memset(&m_Header.reserved, 0, sizeof(m_Header.reserved));
540 }
541 else {
542 parseStr += "Unknown Profile Header attribute: ";
543 parseStr += (const char*)pNode->name;
544 parseStr += "=\"";
545 if (pNode->children && pNode->children->content)
546 parseStr += (const char*)pNode->children->content;
547 parseStr += "\"\n";
548 }
549 }
550 }
551
552 m_Header.magic = icMagicNumber;
553
554 return true;
555}
556
557
558/**
559******************************************************************************
560* Name: CIccProfileXml::ParseTag
561*
562* Purpose: This will load from the indicated IO object and associate a tag
563* object to a tag directory entry. Nothing happens if tag directory entry
564* is associated with a tag object.
565*
566* Args:
567* pNode - pointer to xmlNode object to parse from
568*
569* Return:
570* true - tag from node successfully parsed,
571* false - failure
572*******************************************************************************
573*/
574bool CIccProfileXml::ParseTag(xmlNode *pNode, std::string &parseStr)
575{
576 xmlAttr *attr;
577
578 if (pNode->type != XML_ELEMENT_NODE) {// || icXmlStrCmp(pNode->name, "Tag")) {
579 parseStr += "Invalid Tag Node: ";
580 parseStr += (const char *)pNode->name;
581 parseStr += "\n";
582 return false;
583 }
584
585 CIccTag *pTag = NULL;
586
587 std::string nodeName = (icChar*)pNode->name;
588 icTagSignature sigTag = icGetTagNameSig(nodeName.c_str());
589
590 if (sigTag != icSigUnknownTag || nodeName == "PrivateTag") { //Parsing of XML tags by name
591 if (nodeName == "PrivateTag") {
592 const char *tagSig = icXmlAttrValue(pNode, "TagSignature", "");
593 if (tagSig[0]) {
594 sigTag = (icTagSignature)icGetSigVal(tagSig);
595 }
596 else {
597 parseStr += "Invalid TagSignature for PrivateTag\n";
598 return false;
599 }
600 }
601
602 const char *sameAs = icXmlAttrValue(pNode, "SameAs", "");
603
604 if (sameAs[0]) {
605 icTagSignature sigParentTag = icGetTagNameSig(sameAs);
606 if (!strcmp(sameAs, "PrivateTag") || sigParentTag == icSigUnknownTag) {
607 const char *sameAsSig = icXmlAttrValue(pNode, "SameAsSignature", "");
608 if (sameAsSig[0]) {
609 sigParentTag = (icTagSignature)icGetSigVal(sameAsSig);
610 }
611 else {
612 parseStr += "Invalid SameAsSignature for PrivateTag\n";
613 return false;
614 }
615 }
616 pTag = this->FindTag(sigParentTag);
617 if (pTag) {
618 AttachTag(sigTag, pTag);
619 }
620 else {
621 parseStr += "SameAs tag ";
622 parseStr += sameAs;
623 parseStr += " for ";
624 parseStr += nodeName + " does not exist\n";
625 return false;
626 }
627
628 return true;
629 }
630 else { //Parse the type node as the first child
631 xmlNode *pTypeNode;
632 for (pTypeNode = pNode->children; pTypeNode; pTypeNode = pTypeNode->next) {
633 if (pTypeNode->type == XML_ELEMENT_NODE) {
634 break;
635 }
636 }
637
638 if (!pTypeNode) {
639 parseStr += "No tag type node defined for ";
640 parseStr += nodeName;
641 parseStr += "\n";
642 return false;
643 }
644
645 // get the tag type signature
646 icTagTypeSignature sigType = icGetTypeNameTagSig((const icChar*)pTypeNode->name);
647
648 if (sigType == icSigUnknownType) {
649 xmlAttr *attr = icXmlFindAttr(pTypeNode, "type");
651 }
652
653 CIccInfo info;
654
655 // create a tag based on the signature
656 pTag = CIccTag::Create(sigType);
657
658 IIccExtensionTag *pExt;
659
660 if (pTag && (pExt = pTag->GetExtension()) && !strcmp(pExt->GetExtClassName(), "CIccTagXml")) {
661 CIccTagXml* pXmlTag = (CIccTagXml*)pExt;
662
663 if (pXmlTag->ParseXml(pTypeNode->children, parseStr)) {
664 if ((attr = icXmlFindAttr(pTypeNode, "reserved"))) {
665 sscanf(icXmlAttrValue(attr), "%u", &pTag->m_nReserved);
666 }
667 AttachTag(sigTag, pTag);
668 }
669 else {
670 char str[100];
671 parseStr += "Unable to Parse \"";
672 parseStr += (const char*)pTypeNode->name;
673 parseStr += "\" (";
674 parseStr += nodeName;
675 sprintf(str, ") Tag on line %d\n", pTypeNode->line);
676 parseStr += str;
677 return false;
678 }
679 }
680 else {
681 char str[100];
682 parseStr += "Invalid tag extension for \"";
683 parseStr += (const char*)pTypeNode->name;
684 parseStr += "\" (";
685 sprintf(str, ") Tag on line %d\n", pTypeNode->line);
686 parseStr += str;
687 return false;
688 }
689 }
690 }
691 else { //Legacy parsing of XML tags by type
692 sigTag = (icTagSignature)0;
693 // get the tag type signature
694 icTagTypeSignature sigType = icGetTypeNameTagSig(nodeName.c_str());
695
696 if (sigType == icSigUnknownType) {
697 xmlAttr *attr = icXmlFindAttr(pNode, "type");
699 }
700
701 CIccInfo info;
702
703 // create a tag based on the signature
704 pTag = CIccTag::Create(sigType);
705
706 IIccExtensionTag *pExt;
707
708 if (pTag && (pExt = pTag->GetExtension()) && !strcmp(pExt->GetExtClassName(), "CIccTagXml")) {
709 CIccTagXml* pXmlTag = (CIccTagXml*)pExt;
710
711 if (pXmlTag->ParseXml(pNode->children, parseStr)) {
712 if ((attr = icXmlFindAttr(pNode, "reserved"))) {
713 sscanf(icXmlAttrValue(attr), "%u", &pTag->m_nReserved);
714 }
715
716 for (xmlNode *tagSigNode = pNode->children; tagSigNode; tagSigNode = tagSigNode->next) {
717 if (tagSigNode->type == XML_ELEMENT_NODE && !icXmlStrCmp(tagSigNode->name, "TagSignature")) {
718 sigTag = (icTagSignature)icGetSigVal((const icChar*)tagSigNode->children->content);
719 AttachTag(sigTag, pTag);
720 }
721 }
722 }
723 else {
724 char str[100];
725 parseStr += "Unable to Parse \"";
726 parseStr += info.GetTagTypeSigName(sigType);
727 parseStr += "\" (";
728 parseStr += nodeName;
729 sprintf(str, ") Tag on line %d\n", pNode->line);
730 parseStr += str;
731 return false;
732 }
733 }
734 else {
735 char str[100];
736 parseStr += "Invalid tag extension for \"";
737 parseStr += info.GetTagTypeSigName(sigType);
738 parseStr += "\" (";
739 parseStr += nodeName;
740 sprintf(str, ") Tag on line %d\n", pNode->line);
741 parseStr += str;
742 return false;
743 }
744 }
745
746 switch(sigTag) {
747 case icSigAToB0Tag:
748 case icSigAToB1Tag:
749 case icSigAToB2Tag:
750 case icSigAToB3Tag:
751 if (pTag->IsMBBType())
752 ((CIccMBB*)pTag)->SetColorSpaces(m_Header.colorSpace, m_Header.pcs);
753 break;
754
755 case icSigBToA0Tag:
756 case icSigBToA1Tag:
757 case icSigBToA2Tag:
758 case icSigBToA3Tag:
759 if (pTag->IsMBBType())
760 ((CIccMBB*)pTag)->SetColorSpaces(m_Header.pcs, m_Header.colorSpace);
761 break;
762
763 case icSigHToS0Tag:
764 case icSigHToS1Tag:
765 case icSigHToS2Tag:
766 case icSigHToS3Tag:
767 if (pTag->IsMBBType())
768 ((CIccMBB*)pTag)->SetColorSpaces(m_Header.pcs, m_Header.pcs);
769 break;
770
771 case icSigGamutTag:
772 if (pTag->IsMBBType())
773 ((CIccMBB*)pTag)->SetColorSpaces(m_Header.pcs, icSigGamutData);
774 break;
775
777 {
778 if (pTag->GetType()==icSigNamedColor2Type) {
779 ((CIccTagNamedColor2*)pTag)->SetColorSpaces(m_Header.pcs, m_Header.colorSpace);
780 }
781 else if (pTag->GetTagArrayType()==icSigNamedColorArray) {
783
784 if (pAry) {
785 pAry->SetColorSpaces(m_Header.pcs, m_Header.colorSpace,
786 m_Header.spectralPCS,
787 &m_Header.spectralRange,
788 &m_Header.biSpectralRange);
789 }
790 }
791 }
792 default:
793 break;
794 }
795
796 return true;
797}
798
799
800// entry function for converting xml to icc
801bool CIccProfileXml::ParseXml(xmlNode *pNode, std::string &parseStr)
802{
803 if (icXmlStrCmp(pNode->name, "IccProfile")) {
804 return false;
805 }
806
807 xmlNode *hdrNode = icXmlFindNode(pNode->children, "Header");
808
809 // parse header
810 if (!hdrNode || !ParseBasic(hdrNode, parseStr))
811 return false;
812
813 // parse each tag
814 xmlNode *tagNode = icXmlFindNode(pNode->children, "Tags");
815 if (!tagNode)
816 return false;
817
818 for (tagNode = tagNode->children; tagNode; tagNode = tagNode->next) {
819 if (tagNode->type == XML_ELEMENT_NODE) {
820 if (!ParseTag(tagNode, parseStr))
821 return false;
822 }
823 }
824
825 return true;
826}
827
828// entry function for converting icc to xml
829bool CIccProfileXml::LoadXml(const char *szFilename, const char *szRelaxNGDir, std::string *parseStr)
830{
831 xmlDoc *doc = NULL;
832 xmlNode *root_element = NULL;
833
834 /*parse the file and get the DOM */
835 doc = xmlReadFile(szFilename, NULL, 0);
836
837 if (doc == NULL)
838 return NULL;
839
840 if (szRelaxNGDir && szRelaxNGDir[0]) {
841 xmlRelaxNGParserCtxt* rlxParser;
842
843 rlxParser = xmlRelaxNGNewParserCtxt (szRelaxNGDir);
844
845 //validate the xml file
846 if (rlxParser){
847 xmlRelaxNG* relaxNG = xmlRelaxNGParse(rlxParser);
848 if (relaxNG){
849 xmlRelaxNGValidCtxt* validCtxt = xmlRelaxNGNewValidCtxt(relaxNG);
850 if (validCtxt){
851 int result = xmlRelaxNGValidateDoc(validCtxt, doc);
852 if (result != 0){
853 printf("\nError: %d: '%s' is an invalid XML file.\n", result, szFilename);
854 return false;
855 }
856 }
857 else
858 return false;
859 }
860 else
861 return false;
862 }
863 else
864 return false;
865 }
866
867 std::string my_parseStr;
868
869 if (!parseStr)
870 parseStr = &my_parseStr;
871
872 *parseStr = "";
873
874 /*Get the root element node */
875 root_element = xmlDocGetRootElement(doc);
876
877 bool rv = ParseXml(root_element, *parseStr);
878
879 xmlFreeDoc(doc);
880
881 return rv;
882}
File: IccArrayBasic.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
static unsigned char parseVersion(const char *szVer)
std::map< icUInt32Number, icTagSignature > IccOffsetTagSigMap
File: IccProfileXml.h.
IIccArray * icGetTagArrayHandler(CIccTag *pTag)
File: IccTagXml.h.
icFloatNumber icFtoD(icS15Fixed16Number num)
Definition IccUtil.cpp:559
const icChar * icGetColorSigStr(icChar *pBuf, icUInt32Number nSig)
Definition IccUtil.cpp:1139
icFloat16Number icFtoF16(icFloat32Number num)
Definition IccUtil.cpp:673
icS15Fixed16Number icDtoF(icFloatNumber num)
Definition IccUtil.cpp:545
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
const std::string icGetDeviceAttrName(icUInt64Number devAttr)
icDateTimeNumber icGetDateTimeValue(const icChar *str)
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)
icUInt32Number icXmlGetChildSigVal(xmlNode *pNode)
const icChar * icGetTagSigTypeName(icTagTypeSignature tagTypeSig)
icTagSignature icGetTagNameSig(const icChar *szName)
icUInt64Number icGetDeviceAttrValue(xmlNode *pNode)
const std::string icGetHeaderFlagsName(icUInt32Number flags, bool bUsesMCS)
const char * icFixXml(std::string &buf, const char *szStr)
const char * icXmlAttrValue(xmlAttr *attr, const char *szDefault)
File: IccUtilXml.cpp.
#define icXmlStrCmp(x, y)
Definition IccUtilXml.h:134
#define icXmlHalfFmt
#define icXmlFloatFmt
icTagTypeSignature
unsigned int icUInt32Number
Class: CIccArrayNamedColor.
void SetColorSpaces(icColorSpaceSignature csPcs, icColorSpaceSignature csDevice, icSpectralColorSignature csSpectralPCS=icSigNoSpectralData, const icSpectralRange *pSpectralRange=NULL, const icSpectralRange *pBiSPectralRange=NULL)
Type: Class.
Definition IccUtil.h:303
const icChar * GetVersionName(icUInt32Number val)
Definition IccUtil.cpp:1428
const icChar * GetTagSigName(icTagSignature sig)
Definition IccUtil.cpp:1495
const icChar * GetTagTypeSigName(icTagTypeSignature sig)
Definition IccUtil.cpp:1594
const icChar * GetSubClassVersionName(icUInt32Number val)
Definition IccUtil.cpp:1438
const icChar * GetRenderingIntentName(icRenderingIntent val, bool bIsV5=false)
Definition IccUtil.cpp:2091
Class: CIccMBB.
Definition IccTagLut.h:428
bool LoadXml(const char *szFilename, const char *szRelaxNGDir, std::string *parseStr=NULL)
bool ToXmlWithBlanks(std::string &xmlString, std::string blanks)
bool ParseTag(xmlNode *pNode, std::string &parseStr)
Name: CIccProfileXml::ParseTag.
bool ParseBasic(xmlNode *pNode, std::string &parseStr)
Name: CIccProfileXml::ParseBasic.
bool ToXml(std::string &xmlString)
bool ParseXml(xmlNode *pNode, std::string &parseStr)
Class: CIccTag.
virtual icTagTypeSignature GetType() const
Function: GetType()
icUInt32Number m_nReserved
static CIccTag * Create(icTagTypeSignature sig)
Name: CIccTag::Create.
virtual bool IsMBBType()
virtual IIccExtensionTag * GetExtension()
virtual icArraySignature GetTagArrayType() const
Class: CIccTagNamedColor2.
virtual bool ToXml(std::string &xml, std::string blanks="")=0
virtual bool ParseXml(xmlNode *pNode, std::string &parseStr)=0
virtual const char * GetExtClassName() const =0
#define icSigUnknownType
Convenience Enum Definitions - Not defined in ICC specification.
unsigned short icUInt16Number
icProfileClassSignature
profileClass enumerations
icMaterialColorSignature
icColorSpaceSignature
Color Space Signatures.
#define icMagicNumber
Defines used in the specification.
icUInt32Number icSignature
#define icEmbeddedProfileTrue
@ icSigNamedColor2Type
#define icVersionNumberV5
icSpectralColorSignature
icSpectralColorSignature enumerations
icPlatformSignature
Platform Signatures.
@ icSigUnkownPlatform
#define icUseWithEmbeddedDataOnly
#define icSigUnknownTag
Convenience Enum Definitions - Not defined in ICC specification.
@ icSigNamedColorArray
icTagSignature
public tags and sizes
@ icSigBToA2Tag
@ icSigAToB3Tag
@ icSigHToS3Tag
@ icSigHToS2Tag
@ icSigAToB0Tag
@ icSigBToA1Tag
@ icSigAToB2Tag
@ icSigBToA0Tag
@ icSigHToS1Tag
@ icSigHToS0Tag
@ icSigAToB1Tag
@ icSigBToA3Tag
@ icSigNamedColor2Tag
@ icSigGamutTag
#define icExtendedRangePCS
icRenderingIntent
Rendering Intents, used in the profile header.
@ icPerceptual
@ icRelativeColorimetric
@ icAbsoluteColorimetric
@ icSaturation
#define icMCSNeedsSubsetTrue
#define icSigGamutData
Convenience Enum Definitions - Not defined in ICC specification.