Hoyt's FORK of DemoIccMAX 2.1.17.hoyt
Documentation for Hoyt's FORK of DemoIccMAX
Loading...
Searching...
No Matches
IccCmmConfig.cpp
Go to the documentation of this file.
1/*
2 File: IccCmmConfig.cpp
3
4 Contains: Cmm application configuraiton objects
5
6 Version: V1
7
8 Copyright: (c) see below
9*/
10
11/*
12 * The ICC Software License, Version 0.2
13 *
14 *
15 * Copyright (c) 2003-2024 The International Color Consortium. All rights
16 * reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
29 *
30 * 3. In the absence of prior written permission, the names "ICC" and "The
31 * International Color Consortium" must not be used to imply that the
32 * ICC organization endorses or promotes products derived from this
33 * software.
34 *
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
40 * ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This software consists of voluntary contributions made by many
51 * individuals on behalf of the The International Color Consortium.
52 *
53 *
54 * Membership in the ICC is encouraged when this software is used for
55 * commercial purposes.
56 *
57 *
58 * For more information on The International Color Consortium, please
59 * see <http://www.color.org/>.
60 *
61 *
62 */
63
64 //////////////////////////////////////////////////////////////////////
65 // HISTORY:
66 //
67 // -Initial implementation by Max Derhak 1-11-2024
68 //
69 //////////////////////////////////////////////////////////////////////
70
71#include "IccCmmConfig.h"
72#include <stdio.h>
73#include <fstream>
74#include <string.h>
75
76
77static const icChar* icGetJsonFloatColorEncoding(icFloatColorEncoding val)
78{
79 switch (val) {
80
81 case icEncodeValue:
82 return "value";
83
84 case icEncodeFloat:
85 return "float";
86
87 case icEncodeUnitFloat:
88 return "unitFloat";
89
90 case icEncodePercent:
91 return "percent";
92
93 case icEncode8Bit:
94 return "8Bit";
95
96 case icEncode16Bit:
97 return "16Bit";
98
99 case icEncode16BitV2:
100 return "16BitV2";
101
102 default:
103 return "unknown";
104 }
105}
106
107static const char* clrEncNames[] = { "value", "float", "unitFloat", "percent",
108 "8Bit", "16Bit", "16BitV2", nullptr };
109static icFloatColorEncoding clrEncValues[] = { icEncodeValue, icEncodeFloat, icEncodeUnitFloat, icEncodePercent,
110 icEncode8Bit, icEncode16Bit, icEncode16BitV2, icEncodeUnknown };
111
112icFloatColorEncoding icSetJsonColorEncoding(const char* szEncode)
113{
114
115 int i;
116 for (i = 0; clrEncNames[i]; i++) {
117 if (!stricmp(szEncode, clrEncNames[i]))
118 break;
119 }
120
121 return clrEncValues[i];
122}
123
124bool jsonToValue(const json& j, icFloatColorEncoding& v)
125{
126 std::string str;
127 if (jsonToValue(j, str)) {
128 v = icSetJsonColorEncoding(str.c_str());
129 return true;
130 }
131
132 return false;
133}
134
135const char* icGetJsonColorEncoding(icFloatColorEncoding v)
136{
137 int i;
138 for (i = 0; clrEncNames[i]; i++) {
139 if (v==clrEncValues[i])
140 break;
141 }
142
143 return clrEncNames[i] ? clrEncNames[i] : clrEncNames[0];
144}
145
146static const char* fileEncNames[] = { "8Bit", "16Bit", "float", "sameAsSource", nullptr};
147static icFloatColorEncoding fileEncValues[] = { icEncode8Bit, icEncode16Bit, icEncodeFloat, icEncodeUnknown, icEncode8Bit };
148
149icFloatColorEncoding icSetJsonFileEncoding(const char* szEncode)
150{
151
152 int i;
153 for (i = 0; fileEncNames[i]; i++) {
154 if (!stricmp(szEncode, fileEncNames[i]))
155 break;
156 }
157
158 return fileEncValues[i];
159}
160
161const char* icGetJsonFileEncoding(icFloatColorEncoding v)
162{
163
164 int i;
165 for (i = 0; fileEncNames[i]; i++) {
166 if (v == fileEncValues[i])
167 break;
168 }
169
170 return fileEncNames[i] ? fileEncNames[i] : clrEncNames[0];
171}
172
173
174
179
181{
182 m_debugCalc = false;
185 m_srcFile.clear();
187 m_dstFile.clear();
188 m_dstEncoding = icEncodeValue;
189 m_dstDigits = 9;
190 m_dstPrecision = 4;
191}
192
193bool jsonToValue(const json& j, icCfgDataType& v)
194{
195 std::string str;
196 if (jsonToValue(j, str)) {
197 if (str == "colorData")
198 v = icCfgColorData;
199 else if (str == "legacy")
200 v = icCfgLegacy;
201 else if (str == "it8")
202 v = icCfgIt8;
203 else
204 return false;
205 }
206 else
207 return false;
208
209 return true;
210}
211
212void jsonSetValue(json& j, const char* szName, icCfgDataType v)
213{
214 if (v == icCfgColorData)
215 j[szName] = "colorData";
216 else if (v == icCfgLegacy)
217 j[szName] = "legacy";
218 else if (v == icCfgIt8)
219 j[szName] = "it8";
220}
221
222
223
224int CIccCfgDataApply::fromArgs(const char** args, int nArg, bool bReset)
225{
226 if (nArg < 2) {
227 return 0;
228 }
229
230 if (bReset)
231 reset();
232
234 m_srcFile = args[0];
235
237 m_dstFile.clear();
238
239 //Setup destination encoding
240 m_dstEncoding = (icFloatColorEncoding)atoi(args[1]);
241
242 const char *colon = strchr(args[1], ':');
243 if (colon) {
244 colon++;
245 m_dstPrecision = (icUInt8Number)atoi(colon);
247 colon = strchr(colon, ':');
248 if (colon) {
249 m_dstDigits = atoi(colon);
250 }
251 }
252
253 return 2;
254}
255
256bool CIccCfgDataApply::fromJson(json j, bool bReset)
257{
258 if (!j.is_object())
259 return false;
260
261 if (bReset)
262 reset();
263
264 jsonToValue(j["debugCalc"], m_debugCalc);
265
266 jsonToValue(j["srcType"], m_srcType);
267 if (j.find("srcSpace")!=j.end())
268 jsonToColorSpace(j["srcSpace"], m_srcSpace);
269 jsonToValue(j["srcFile"], m_srcFile);
270
271 jsonToValue(j["dstType"], m_dstType);
272 jsonToValue(j["dstFile"], m_dstFile);
273 jsonToValue(j["dstEncoding"], m_dstEncoding);
274
275 jsonToValue(j["dstDigits"], m_dstDigits);
276 jsonToValue(j["dstPrecision"], m_dstPrecision);
277
278 return true;
279}
280
281void CIccCfgDataApply::toJson(json& j) const
282{
283 char buf[30];
284
285 if (m_debugCalc)
286 j["debugCalc"] = m_debugCalc;
287
288 jsonSetValue(j, "srcType", m_srcType);
290 j["srcSpace"] = icGetColorSigStr(buf, m_srcSpace);
291
292 if (m_srcFile.size())
293 j["srcFile"] = m_srcFile;
294
295 jsonSetValue(j, "dstType", m_dstType);
296 if (m_dstFile.size())
297 j["dstFile"] = m_dstFile;
298
299 if (m_dstEncoding != icEncodeValue)
300 j["dstEncoding"] = icGetJsonColorEncoding(m_dstEncoding);
301
302 if (m_dstDigits != 9)
303 j["dstDigits]"] = m_dstDigits;
304
305 if (m_dstPrecision != 4)
306 j["dstPrecision"] = m_dstPrecision;
307}
308
313
314bool jsonToValue(const json& j, icDstBool& v)
315{
316 if (j.is_boolean())
317 v = j.get<bool>() ? icDstBoolTrue : icDstBoolFalse;
318 else if (j.is_string()) {
319 std::string str = j.get<std::string>();
320 if (str == "true")
321 v = icDstBoolTrue;
322 else if (str == "false")
323 v = icDstBoolFalse;
324 else if (str == "sameAsSource")
326 else
327 return false;
328 }
329 else
330 return false;
331
332 return true;
333}
334
344
345int CIccCfgImageApply::fromArgs(const char** args, int nArg, bool bReset)
346{
347 if (nArg < 6) {
348 return 0;
349 }
350
351 if (bReset)
352 reset();
353
354 m_srcImgFile = args[0];
355 m_dstImgFile = args[1];
356
357 int n = atoi(args[2]);
358 switch (n)
359 {
360 case 0:
361 m_dstEncoding = icEncodeUnknown;
362 break;
363
364 default:
365 case 1:
366 m_dstEncoding = icEncode8Bit;
367 break;
368
369 case 2:
370 m_dstEncoding = icEncode16Bit;
371 break;
372
373 case 3:
374 m_dstEncoding = icEncodeFloat;
375 break;
376 }
377
378 m_dstCompression = atoi(args[3]) != 0 ? icDstBoolTrue : icDstBoolFalse;
379 m_dstPlanar = atoi(args[4]) != 0 ? icDstBoolTrue : icDstBoolFalse;
380 m_dstEmbedIcc = atoi(args[5]) != 0 ? icDstBoolTrue : icDstBoolFalse;
381
382 return 6;
383}
384
385static void setDstBool(json &j, const char *szName, icDstBool v)
386{
387 if (v == icDstBoolTrue)
388 j[szName] = true;
389 else if (v == icDstBoolFalse)
390 j[szName] = false;
391 else if (v = icDstBoolFromSrc)
392 j[szName] = "sameAsSoure";
393}
394
395bool CIccCfgImageApply::fromJson(json j, bool bReset)
396{
397 if (!j.is_object())
398 return false;
399
400 if (bReset)
401 reset();
402
403 jsonToValue(j["srcImageFile"], m_srcImgFile);
404 jsonToValue(j["dstImageFile"], m_dstImgFile);
405
406 std::string str;
407 if (jsonToValue(j["dstEncoding"], str))
409
410 jsonToValue(j["dstCompression"], m_dstCompression);
411 jsonToValue(j["dstPlanar"], m_dstPlanar);
412 jsonToValue(j["dstEmbedIcc"], m_dstEmbedIcc);
413
414 return true;
415}
416
417void CIccCfgImageApply::toJson(json& j) const
418{
419 if (m_srcImgFile.size())
420 j["srcImgFile"] = m_srcImgFile;
421 if (m_dstImgFile.size())
422 j["dstImgFile"] = m_dstImgFile;
423
424 if (m_dstEncoding != icEncode8Bit)
425 j["dstEncoding"] = icGetJsonFileEncoding(m_dstEncoding);
426
427 setDstBool(j, "dstCompression", m_dstCompression);
428 setDstBool(j, "dstPlanar", m_dstPlanar);
429 setDstBool(j, "dstEmbedIcc", m_dstEmbedIcc);
430}
431
436
448
449int CIccCfgCreateLink::fromArgs(const char** args, int nArg, bool bReset)
450{
451 if (nArg < 8) {
452 return 0;
453 }
454
455 if (bReset)
456 reset();
457
458 m_linkFile = args[0];
459
460 int n = atoi(args[1]);
461 m_linkGridSize = atoi(args[2]);
462 int o = atoi(args[3]);
463
464 switch (n)
465 {
466 case 0:
468 break;
469
470 case 1:
473 break;
474
475 default:
477 break;
478 }
479
480 m_linkTitle = args[4];
481
482 m_linkMinRange = (icFloatNumber)atof(args[5]);
483 m_linkMaxRange = (icFloatNumber)atof(args[6]);
484
485 m_useSourceTransform = atoi(args[7]) != 0;
486
487 return 8;
488}
489
490bool CIccCfgCreateLink::fromJson(json j, bool bReset)
491{
492 if (!j.is_object())
493 return false;
494
495 if (bReset)
496 reset();
497
498 jsonToValue(j["linkFile"], m_linkFile);
499
500 std::string linkType;
501 jsonToValue(j["linkType"], linkType);
502 if (!stricmp(linkType.c_str(), "cubeFile"))
504 else if (!stricmp(linkType.c_str(), "iccDeviceLinkV5"))
506 else /*!stricmp(linkType.c_str(), "iccDeviceLinkV4")*/
508
509 jsonToValue(j["linkGridSize"], m_linkGridSize);
510 jsonToValue(j["linkPrecision"], m_linkPrecision);
511 jsonToValue(j["linkTitle"], m_linkTitle);
512 jsonToValue(j["linkMinRange"], m_linkMinRange);
513 jsonToValue(j["linkMaxRange"], m_linkMaxRange);
514 jsonToValue(j["useSourceTransform"], m_useSourceTransform);
515
516 return true;
517}
518
519void CIccCfgCreateLink::toJson(json& j) const
520{
521 if (m_linkFile.size())
522 j["linkFile"] = m_linkFile;
523
524 switch (m_linkType) {
526 j["linkType"] = "cubeFile";
527 j["linkPrecision"] = m_linkPrecision;
528 break;
529 default:
531 j["linkType"] = "iccDeviceLinkV4";
532 break;
534 j["linkType"] = "iccDeviceLinkV5";
535 break;
536 }
537
538 j["linkTitle"] = m_linkTitle;
539 j["linkMinRange"] = m_linkMinRange;
540 j["linkMaxRange"] = m_linkMaxRange;
541 j["useSourceTransform"] = m_useSourceTransform;
542}
543
548
550{
551 m_iccFile.clear();
554 m_iccEnvVars.clear();
555 m_pccFile.clear();
556 m_pccEnvVars.clear();
557 m_adjustPcsLuminance = false;
558 m_useD2BxB2Dx = false;
559 m_useBPC = false;
560 m_useHToS = false;
561 m_useV5SubProfile = false;
563}
564
565static bool icGetJsonRenderingIntent(const json& j, int& v)
566{
567 if (j.is_string()) {
568 std::string str = j.get<std::string>();
569 if (str == "perceptual")
570 v = icPerceptual;
571 else if (str == "relative")
572 v = icRelative;
573 else if (str == "saturation")
574 v = icSaturation;
575 else if (str == "absolute")
576 v = icAbsolute;
577 else
578 v = icUnknownIntent;
579 }
580 else if (j.is_number_integer()) {
581 v = j.get<int>();
582 }
583 else
584 return false;
585
586 return true;
587}
588
589static const char* icTranNames[] = { "default", "named", "colorimetric", "spectral",
590 "MCS", "preview", "gamut", "brdfParam",
591 "brdfDirect", "brdfMcsParam" , nullptr };
592
596
597static const char* icInterpNames[] = { "linear", "tetrahedral", nullptr };
598
600
601bool jsonToValue(const json& j, icCmmEnvSigMap& v)
602{
603 if (!j.is_array())
604 return false;
605
606 for (auto e = j.begin(); e != j.end(); e++) {
607 if (e->is_object()) {
608 std::string name;
609 icFloatNumber value;
610 if (jsonToValue((*e)["name"], name) && jsonToValue((*e)["value"], value)) {
612 v[sig]=value;
613 }
614 }
615 }
616 return true;
617}
618
619bool CIccCfgProfile::fromJson(json j, bool bReset)
620{
621 if (!j.is_object())
622 return false;
623
624 if (bReset)
625 reset();
626
627 jsonToValue(j["iccFile"], m_iccFile);
628
630
631 std::string str;
632 if (jsonToValue(j["transform"], str)) {
633 int i;
634 for (i = 0; icTranNames[i]; i++) {
635 if (str == icTranNames[i])
636 break;
637 }
639 }
640
641 jsonToValue(j["iccEnvVars"], m_iccEnvVars);
642
643 jsonToValue(j["pccFile"], m_pccFile);
644 jsonToValue(j["pccEnvVars"], m_pccEnvVars);
645
646 jsonToValue(j["adjustPcsLuminance"], m_adjustPcsLuminance);
647 jsonToValue(j["useBPC"], m_useBPC);
648 jsonToValue(j["useHToS"], m_useHToS);
649 jsonToValue(j["useV5SubProfile"], m_useV5SubProfile);
650
651 if (jsonToValue(j["transform"], str)) {
652 int i;
653 for (i = 0; icInterpNames[i]; i++) {
654 if (str == icInterpNames[i])
655 break;
656 }
658 }
659
660 return true;
661}
662
663static bool jsonFromEnvMap(json& j, const icCmmEnvSigMap& map)
664{
665 char buf[30];
666 j.clear();
667 for (auto e = map.begin(); e != map.end(); e++) {
668 json var;
669 var["name"] = icGetSigStr(buf, e->first);
670 var["value"] = e->second;
671 j.push_back(var);
672 }
673 return j.is_array() && j.size() > 0;
674}
675
676void CIccCfgProfile::toJson(json& j) const
677{
678 if (m_iccFile.size())
679 j["iccProfile"] = m_iccFile;
680 json iccMap;
681 if (jsonFromEnvMap(iccMap, m_iccEnvVars))
682 j["iccEnvVars"] = iccMap;
683 if (m_pccFile.size())
684 j["pccFile"] = m_pccFile;
685 json pccMap;
686 if (jsonFromEnvMap(pccMap, m_pccEnvVars))
687 j["pccEnvVars"] = pccMap;
689 j["adjustPcsLuminance"] = m_adjustPcsLuminance;
690 if (m_useBPC)
691 j["useBPC"] = m_useBPC;
692 if (m_useHToS)
693 j["useHToS"] = m_useHToS;
695 j["useV5SubProfile"] = m_useV5SubProfile;
696 int i;
697 for (i = 0; icInterpNames[i]; i++)
699 break;
701 j["interpolation"] = icInterpNames;
702}
703
707
709{
710 m_profiles.clear();
711}
712
713int CIccCfgProfileSequence::fromArgs(const char** args, int nArg, bool bReset)
714{
715 int nUsed = 0;
716 if (bReset)
717 reset();
718
719 icXformInterp interpolation = icInterpTetrahedral;
720
721 if (nArg > 1) {
722 interpolation = (icXformInterp)atoi(args[0]);
723 args++;
724 nArg--;
725 nUsed++;
726 }
727
728 bool bFirst = true;
729 while (nArg >= 2) {
731
732 while (nArg >= 2 && !strnicmp(args[0], "-ENV:", 5)) { //check for -ENV: to allow for Cmm Environment variables to be defined for next transform
733 icSignature sig = icGetSigVal(args[0] + 5);
734 icFloatNumber val = (icFloatNumber)atof(args[1]);
735 args += 2;
736 nArg -= 2;
737 nUsed += 2;
738
739 pProf->m_iccEnvVars[sig] = val;
740 }
741
742 if (nArg >= 2) {
743
744 pProf->m_iccFile = args[0];
745 if (bFirst) {
746 if (!stricmp(args[0], "-embedded")) {
747 pProf->m_iccFile.clear();
748 }
749 bFirst = false;
750 }
751 int nType;
752 int nIntent = atoi(args[1]);
753
754 pProf->m_useD2BxB2Dx = true;
755 pProf->m_useHToS = (nIntent / 100000) != 0;
756 pProf->m_useV5SubProfile = (nIntent / 10000) != 0;
757 nIntent = nIntent % 10000;
758 pProf->m_adjustPcsLuminance = nIntent / 1000 != 0;
759 nIntent = nIntent % 1000;
760 nType = abs(nIntent) / 10;
761 nIntent = nIntent % 10;
762
763 if (nType == 1) {
764 pProf->m_useD2BxB2Dx = false;
765 nType = icXformLutColor;
766 }
767 else if (nType == 4) {
768 pProf->m_useBPC = true;
769 nType = icXformLutColor;
770 }
771
772 pProf->m_intent = (icRenderingIntent)nIntent;
773 pProf->m_transform = (icXformLutType)nType;
774 pProf->m_interpolation = interpolation;
775
776 args += 2;
777 nArg -= 2;
778 nUsed += 2;
779 }
780
781 if (nArg >= 2 && !stricmp(args[0], "-PCC")) {
782 pProf->m_pccFile = args[1];
783 args += 2;
784 nArg -= 2;
785 nUsed += 2;
786 }
787 m_profiles.push_back(pProf);
788 }
789
790 return m_profiles.size()>0 ? nUsed : 0;
791}
792
793bool CIccCfgProfileSequence::fromJson(json j, bool bReset)
794{
795 if (!j.is_array())
796 return false;
797
798 if (bReset)
799 reset();
800
801 for (auto p = j.begin(); p != j.end(); p++) {
802 if (p->is_object()) {
804 if (pProf->fromJson(*p)) {
805 m_profiles.push_back(pProf);
806 }
807 else {
808 pProf.reset();
809 }
810 }
811 }
812
813 return true;
814}
815
817{
818 for (auto p = m_profiles.begin(); p != m_profiles.end(); p++) {
819 CIccCfgProfile* pProf = p->get();
820 if (!pProf)
821 continue;
822 json prof;
823 pProf->toJson(prof);
824 obj.push_back(prof);
825 }
826}
827
829{
830public:
831 CIccIt8Parser() { m_f = nullptr; }
832 ~CIccIt8Parser() { if (m_f) delete m_f; }
833
834 bool open(const char* szFilename) {
835 if (m_f)
836 delete m_f;
837 m_f = new std::ifstream(szFilename);
838 return m_f != nullptr;
839 }
840 bool isEOF() { return m_f->eof(); }
841 bool parseLine(std::vector<std::string>& line) {
842 line.clear();
843 if (isEOF())
844 return false;
845 std::string str;
846
847 int c = 0;
848 while (!isEOF()) {
849 c = m_f->get();
850 if (c < 0) {
851 if (str.size())
852 line.push_back(str);
853 if (!line.size())
854 return false;
855 break;
856 }
857 else if (c == '\n')
858 continue;
859 else if (c == '\r') {
860 line.push_back(str);
861 break;
862 }
863 else if (c == '\t') {
864 line.push_back(str);
865 str.clear();
866 }
867 else {
868 str += c;
869 }
870 }
871 return true;
872 }
873
874 bool parseNextLine(std::vector<std::string>& line) {
875 while (parseLine(line)) {
876 if (line.size())
877 return true;
878 }
879 return false;
880 }
881
882 bool findTokenLine(std::vector<std::string>& line, const char* szToken) {
883 while (parseNextLine(line)) {
884 if (line[0] == szToken)
885 break;
886 }
887 return false;
888 }
889
890protected:
891 std::ifstream* m_f;
892};
893
898
900{
902 m_encoding = icEncodeValue;
903
905 m_srcEncoding = icEncodeValue;
906
907 m_data.clear();
908}
909
910static bool ParseNumbers(icFloatNumber* pData, icChar* pString, icUInt32Number nSamples)
911{
912 icUInt32Number nNumbersRead = 0;
913
914 icChar* ptr = pString;
915
916 while (*ptr && nNumbersRead < nSamples) {
917 while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\r')
918 ptr++;
919 if (sscanf(ptr, ICFLOATFMT, &pData[nNumbersRead]) == 1)
920 nNumbersRead++;
921 else
922 break;
923 while (*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != 'n' && *ptr != '\r')
924 ptr++;
925 }
926
927 if (nNumbersRead != nSamples) {
928 return false;
929 }
930
931 return true;
932}
933
934static bool ParseNextNumber(icFloatNumber& num, icChar** text)
935{
936 if (!text)
937 return false;
938
939 icChar* ptr = *text;
940 while (*ptr == ' ') ptr++;
941 if ((*ptr >= '0' && *ptr <= '9') || *ptr == '.') {
942 num = (icFloatNumber)atof(ptr);
943
944 while (*ptr && *ptr != ' ') ptr++;
945
946 *text = ptr;
947
948 return true;
949 }
950 return false;
951}
952
953//===================================================
954
955static bool ParseName(icChar* pName, icChar* pString)
956{
957 if (strncmp(pString, "{ \"", 3))
958 return false;
959
960 icChar* ptr = strstr(pString, "\" }");
961
962 if (!ptr)
963 return false;
964
965 icUInt32Number nNameLen = (icUInt32Number)(ptr - (pString + 3));
966
967 if (!nNameLen)
968 return false;
969
970 strncpy(pName, pString + 3, nNameLen);
971 pName[nNameLen] = '\0';
972
973 return true;
974}
975
976
977bool CIccCfgColorData::fromLegacy(const char* filename, bool bReset)
978{
979 if (bReset)
980 reset();
981
982 std::ifstream InputData(filename);
983
984 if (!InputData) {
985 return false;
986 }
987
988 icChar ColorSig[7], *tempBuf = new icChar[20000];
989 if (!tempBuf)
990 return false;
991 InputData.getline(tempBuf, sizeof(tempBuf));
992
993 int i;
994 for (i = 0; (i < 4 || tempBuf[i + 1] != '\'') && i < 6; i++) {
995 ColorSig[i] = tempBuf[i + 1];
996 }
997 for (; i < 7; i++)
998 ColorSig[i] = '\0';
999
1000 //Init source number of samples from color signature is source data file
1002 int nSamples = icGetSpaceSamples(m_srcSpace);
1003 if (m_srcSpace != icSigNamedData) {
1004 if (!nSamples) {
1005 delete[] tempBuf;
1006 return false;
1007 }
1008 }
1009
1010 InputData.getline(tempBuf, sizeof(tempBuf));
1011 sscanf(tempBuf, "%s", tempBuf);
1012
1013 //Setup source encoding
1014 m_encoding = CIccCmm::GetFloatColorEncoding(tempBuf);
1015 if (m_encoding == icEncodeUnknown) {
1016 delete[] tempBuf;
1017 return false;
1018 }
1019 char SrcNameBuf[256];
1020 int nSrcSamples = icGetSpaceSamples(m_srcSpace);
1021 CIccPixelBuf Pixel(nSrcSamples + 16);
1022
1023 while (!InputData.eof()) {
1025
1026 //Are names coming is as an input?
1027 if (m_srcSpace == icSigNamedData) {
1028 InputData.getline(tempBuf, sizeof(tempBuf));
1029 if (!ParseName(SrcNameBuf, tempBuf))
1030 continue;
1031
1032 data->m_name = SrcNameBuf;
1033
1034 icChar* numptr = strstr(tempBuf, "\" }");
1035 if (numptr)
1036 numptr += 3;
1037
1038 icFloatNumber tint;
1039 if (!ParseNextNumber(tint, &numptr))
1040 tint = 1.0;
1041 data->m_values.push_back(tint);
1042 }
1043 else { //pixel sample data coming in as input
1044
1045 InputData.getline(tempBuf, sizeof(tempBuf));
1046 if (!ParseNumbers(Pixel, tempBuf, nSamples))
1047 continue;
1048
1049 for (int n = 0; n < nSamples; n++) {
1050 data->m_values.push_back(Pixel[n]);
1051 }
1052 }
1053
1054 m_data.push_back(data);
1055 }
1056 delete[] tempBuf;
1057 return true;
1058}
1059
1061{
1062public:
1064 nIndex = -1;
1065 nValue = 0;
1067 }
1068
1072};
1073
1074typedef std::pair<int, std::string> icIndexName;
1075typedef std::vector<CIccIndexValue> icValueVector;
1076
1077static void setSampleIndex(std::vector<icValueVector>& samples, int index, const char* szFmt, const char** szChannels)
1078{
1079 size_t nPos = samples.size() - 1;
1080 for (int i = 0; i < samples[nPos].size(); i++) {
1081 if (!strcmp(szFmt, szChannels[i])) {
1082 samples[nPos][i].nIndex = index;
1083 }
1084 }
1085}
1086
1087bool CIccCfgColorData::fromIt8(const char* filename, bool bReset)
1088{
1089 if (bReset)
1090 reset();
1091
1092 CIccIt8Parser f;
1093
1094 if (!f.open(filename))
1095 return false;
1096
1097 std::vector<std::string> line;
1098 if (!f.findTokenLine(line, "CGATS.17"))
1099 return false;
1100 if (!f.findTokenLine(line, "NUBER_OF_FIELDS"))
1101 return false;
1102 int nFields = 0;
1103 if (line.size() >= 2) {
1104 nFields = atoi(line[1].c_str());
1105 }
1106 if (!f.findTokenLine(line, "BEGIN_DATA_FORMAT"))
1107 return false;
1108 if (!f.parseNextLine(line)) {
1109 return false;
1110 }
1111 if (line.size() != nFields)
1112 return false;
1113
1114 std::string lastSpace;
1115 std::vector<icValueVector> samples;
1116 std::vector<std::string> spaces;
1117 std::vector<icIndexName> names;
1118 int nSpace = 0;
1119 int nName = 0;
1120
1121 int nId = -1;
1122 int nLabel = -1;
1123
1124 int index = 0;
1125 for (auto fmt = line.begin(); fmt != line.end(); fmt++, index++) {
1126 if (*fmt == "SAMPLE_ID") {
1127 nId = index;
1128 }
1129 else if (*fmt == "SAMPLE_NAME") {
1130 nLabel = index;
1131 }
1132 else {
1133 std::string space;
1134 const char* szFmt = fmt->c_str();
1135 if (!strncmp(szFmt, "SRC_", 4)) {
1136 space += "SRC_";
1137 szFmt += 4;
1138 }
1139 if (!strcmp(szFmt, "NAME")) {
1140 space += "NAME";
1141 names.push_back(icIndexName(index, space));
1142 }
1143 else if (!strncmp(szFmt, "TINT", 4)) {
1144 space += "TINT";
1145 if (space != lastSpace) {
1146 icValueVector val(1);
1147 val[0].nIndex = index;
1148 val[0].space = icSigNamedData;
1149 samples.push_back(val);
1150 lastSpace = "";
1151 }
1152 }
1153 else if (!strncmp(szFmt, "RGB_", 4)) {
1154 space += "RGB";
1155 szFmt += 4;
1156 if (space != lastSpace) {
1157 lastSpace = space;
1158 icValueVector val(3);
1159 val[0].space = icSigRgbData;
1160 samples.push_back(val);
1161 spaces.push_back(space);
1162 }
1163 const char* szChannels[] = { "R", "G", "B" };
1164 setSampleIndex(samples, index, szFmt, &szChannels[0]);
1165 }
1166 else if (!strncmp(szFmt, "CMYK_", 5)) {
1167 space += "CMYK";
1168 szFmt += 5;
1169 if (space != lastSpace) {
1170 lastSpace = space;
1171 icValueVector val(4);
1172 val[0].space = icSigCmykData;
1173 spaces.push_back(space);
1174 }
1175 const char* szChannels[] = { "C", "M", "Y", "K" };
1176 setSampleIndex(samples, index, szFmt, &szChannels[0]);
1177 }
1178 else if (!strncmp(szFmt, "LAB_", 4)) {
1179 space += "LAB";
1180 szFmt += 4;
1181 if (space != lastSpace) {
1182 lastSpace = space;
1183 icValueVector val(4);
1184 val[0].space = icSigLabData;
1185 samples.push_back(val);
1186 spaces.push_back(space);
1187 }
1188 const char* szChannels[] = { "L", "A", "B" };
1189 setSampleIndex(samples, index, szFmt, &szChannels[0]);
1190 }
1191 else if (!strncmp(szFmt, "XYZ_", 4)) {
1192 space += "XYZ";
1193 szFmt += 4;
1194 if (space != lastSpace) {
1195 lastSpace = space;
1196 icValueVector val(4);
1197 val[0].space = icSigXYZData;
1198 samples.push_back(val);
1199 spaces.push_back(space);
1200 }
1201 const char* szChannels[] = { "X", "Y", "Z" };
1202 setSampleIndex(samples, index, szFmt, &szChannels[0]);
1203 }
1204 else {
1205 int nColor = -1;
1206 if (sscanf(szFmt, "%uCOLOR_", &nColor) && nColor >= 1) {
1207 char buf[30];
1208 sprintf(buf, "%uCOLOR", nColor);
1209 space += buf;
1210
1211 if (space != lastSpace) {
1212 lastSpace = space;
1213 icValueVector val(nColor);
1214 val[0].space = (icColorSpaceSignature)(icSigNChannelData + (nColor & 0xffff));
1215 samples.push_back(val);
1216 spaces.push_back(space);
1217 }
1218
1219 szFmt = strchr(szFmt, '_');
1220 if (szFmt) {
1221 szFmt++;
1222 int nChannel = atoi(szFmt);
1223 size_t last = samples.size() - 1;
1224 if (nChannel > 0 && samples[last].size() >= nChannel) {
1225 samples[samples.size() - 1][nChannel - 1].nIndex = index;
1226 }
1227 }
1228 }
1229 }
1230 }
1231 }
1232
1233 if (!f.findTokenLine(line, "END_DATA_FORMAT"))
1234 return false;
1235
1236 if (!f.findTokenLine(line, "NUMBER_OF_SETS"))
1237 return false;
1238
1239 int nSets = 0;
1240 if (line.size() > 1) {
1241 nSets = atoi(line[1].c_str());
1242 }
1243
1244 if (!f.findTokenLine(line, "BEGIN_DATA"))
1245 return false;
1246
1247 do {
1248 if (!f.parseNextLine(line) || line[0] == "END_DATA")
1249 break;
1251
1252 if (nId >= 0 && nId < line.size()) {
1253 pData->m_index = atoi(line[nId].c_str());
1254 }
1255 else if (nLabel >= 0 && nLabel < line.size()) {
1256 pData->m_label = line[nLabel];
1257 }
1258
1259 if (names.size() > 0) {
1260 if (names[0].second == "NAME") {
1261 if (names[0].first >= 0)
1262 pData->m_name = line[names[0].first];
1263 if (names.size() > 1) {
1264 if (names[1].first >= 0)
1265 pData->m_srcName = line[names[1].first];
1266 }
1267 }
1268 else if (names[0].second == "SRC_NAME") {
1269 if (names[0].first >= 0)
1270 pData->m_srcName = line[names[0].first];
1271 if (names.size() > 1) {
1272 if (names[1].first >= 0)
1273 pData->m_name = line[names[1].first];
1274 }
1275 }
1276 }
1277
1278 int nValueIdx;
1279 for (nValueIdx = 0; nValueIdx < samples.size(); nValueIdx++) {
1280 if (samples[nValueIdx][0].space == m_space)
1281 break;
1282 }
1283 if (nValueIdx != samples.size()) {
1284 for (int i = 0; i < samples[nValueIdx].size(); i++) {
1285 int nPos = samples[nValueIdx][i].nIndex;
1286 if (nPos < line.size()) {
1287 pData->m_values.push_back((icFloatNumber)atof(line[nPos].c_str()));
1288 }
1289 }
1290 }
1291 else {
1292 for (nValueIdx = 0; nValueIdx < spaces.size(); nValueIdx++) {
1293 if (strncmp(spaces[nValueIdx].c_str(), "SRC_", 4))
1294 break;
1295 }
1296 if (nValueIdx != spaces.size() && nValueIdx < samples.size()) {
1297 m_space = samples[nValueIdx][0].space;
1298 for (int j = 0; j < samples[nValueIdx].size(); j++) {
1299 int nPos = samples[nValueIdx][j].nIndex;
1300 if (nPos < line.size()) {
1301 pData->m_values.push_back((icFloatNumber)atof(line[nPos].c_str()));
1302 }
1303 }
1304 }
1305 }
1306
1307 int nSrcIndex;
1308 for (nSrcIndex = 0; nSrcIndex < samples.size(); nSrcIndex++) {
1309 if (samples[nSrcIndex][0].space == m_srcSpace)
1310 break;
1311 }
1312 if (nSrcIndex != samples.size() && nSrcIndex != nValueIdx) {
1313 for (int i = 0; i < samples[nSrcIndex].size(); i++) {
1314 int nPos = samples[nSrcIndex][i].nIndex;
1315 if (nPos < line.size()) {
1316 pData->m_values.push_back((icFloatNumber)atof(line[nPos].c_str()));
1317 }
1318 }
1319 }
1320 else {
1321 for (nSrcIndex = 0; nSrcIndex < spaces.size(); nSrcIndex++) {
1322 if (!strncmp(spaces[nValueIdx].c_str(), "SRC_", 4))
1323 break;
1324 }
1325 if (nSrcIndex != spaces.size() && nSrcIndex < samples.size()) {
1326 m_srcSpace = samples[nSrcIndex][0].space;
1327 for (int j = 0; j < samples[nValueIdx].size(); j++) {
1328 int nPos = samples[nValueIdx][j].nIndex;
1329 if (nPos < line.size()) {
1330 pData->m_srcValues.push_back((icFloatNumber)atof(line[nPos].c_str()));
1331 }
1332 }
1333 }
1334 else {
1335 for (nSrcIndex = 0; nSrcIndex < samples.size(); nSrcIndex++) {
1336 if (nSrcIndex != nValueIdx)
1337 break;
1338 }
1339 if (nSrcIndex < samples.size()) {
1340 m_srcSpace = samples[nSrcIndex][0].space;
1341 for (int j = 0; j < samples[nValueIdx].size(); j++) {
1342 int nPos = samples[nValueIdx][j].nIndex;
1343 if (nPos < line.size()) {
1344 pData->m_srcValues.push_back((icFloatNumber)atof(line[nPos].c_str()));
1345 }
1346 }
1347 }
1348 }
1349 }
1350
1351 if (pData->m_values.size() || pData->m_srcValues.size() || pData->m_name.size() || pData->m_srcName.size())
1352 m_data.push_back(pData);
1353 else
1354 pData.reset();
1355
1356 } while (!f.isEOF());
1357
1358 return m_data.size() == nSets;
1359}
1360
1361bool CIccCfgColorData::fromJson(json j, bool bReset)
1362{
1363 if (!j.is_object())
1364 return false;
1365
1366 if (bReset)
1367 reset();
1368
1369 std::string str;
1370
1371 jsonToColorSpace(j["space"], m_space);
1372 if (jsonToValue(j["encoding"], str))
1373 m_encoding = icSetJsonColorEncoding(str.c_str());
1374
1375 jsonToColorSpace(j["srcSpace"], m_srcSpace);
1376 if (jsonToValue(j["srcEncoding"], str))
1378
1379 if (j.find("data")!=j.end()) {
1380 json data = j["data"];
1381 if (data.is_array()) {
1382 for (auto d = data.begin(); d != data.end(); d++) {
1383 if (d->is_object()) {
1385 if (entry->fromJson(*d)) {
1386 m_data.push_back(entry);
1387 }
1388 else
1389 entry.reset();
1390 }
1391 }
1392 }
1393 }
1394
1395 return true;
1396}
1397
1398bool CIccCfgColorData::toLegacy(const char* filename, CIccCfgProfileSequence *pProfiles, icUInt8Number nDigits, icUInt8Number nPrecision, bool bShowDebug)
1399{
1400 FILE* f;
1401 char tempBuf[256];
1402 char fmt[20];
1403 if (!nDigits)
1404 sprintf(fmt, " %%.%df", nPrecision);
1405 else
1406 sprintf(fmt, " %%%d.%df", nDigits, nPrecision);
1407
1408 if (!filename || !filename[0])
1409 f = stdout;
1410 else
1411 f = fopen(filename, "wt");
1412
1413 if (!f)
1414 return false;
1415
1416 std::string out;
1417 sprintf(tempBuf, "%s\t; ", icGetColorSig(tempBuf, m_space, false));
1418 out = tempBuf;
1419 out += "Data Format\n";
1420 fwrite(out.c_str(), out.size(), 1, f);
1421
1422 sprintf(tempBuf, "%s\t; ", CIccCmm::GetFloatColorEncoding(m_encoding));
1423 out = tempBuf;
1424 out += "Encoding\n\n";
1425 fwrite(out.c_str(), out.size(), 1, f);
1426
1427 out = ";Source Data Format: ";
1428 sprintf(tempBuf, "%s\n", icGetColorSig(tempBuf, m_srcSpace, false));
1429 out += tempBuf;
1430 fwrite(out.c_str(), out.size(), 1, f);
1431
1432 out = ";Source Data Encoding: ";
1433 sprintf(tempBuf, "%s\n", CIccCmm::GetFloatColorEncoding(m_srcEncoding));
1434 out += tempBuf;
1435 fwrite(out.c_str(), out.size(), 1, f);
1436
1437 fprintf(f, ";Source data is after semicolon\n");
1438 if (pProfiles) {
1439 fprintf(f, "\n;Profiles applied\n");
1440 for (auto pIter = pProfiles->m_profiles.begin(); pIter != pProfiles->m_profiles.end(); pIter++) {
1441 CIccCfgProfile* pProf = pIter->get();
1442 if (!pProf)
1443 continue;
1444 if (pProf->m_pccFile.size()) {
1445 fprintf(f, "; %s -PCC %s\n", pProf->m_iccFile.c_str(), pProf->m_pccFile.c_str());
1446 }
1447 else {
1448 fprintf(f, "; %s\n", pProf->m_iccFile.c_str());
1449 }
1450 }
1451 }
1452 fprintf(f, "\n");
1453
1454 for (auto dIter = m_data.begin(); dIter != m_data.end(); dIter++) {
1455 CIccCfgDataEntry* pData = dIter->get();
1456 if (!pData)
1457 continue;
1458
1459 if (bShowDebug && pData->m_debugInfo.size()) {
1460 for (auto l = pData->m_debugInfo.begin(); l != pData->m_debugInfo.end(); l++) {
1461 fprintf(f, "; %s\n", l->c_str());
1462 }
1463 }
1464
1465 if (pData->m_name.size()) {
1466 fprintf(f, "{ \"%s\" }\t;", pData->m_name.c_str());
1467 }
1468 else {
1469 for (int i = 0; i < pData->m_values.size(); i++) {
1470 fprintf(f, fmt, pData->m_values[i]);
1471 }
1472 fprintf(f, "\t;");
1473 }
1474
1475 if (pData->m_srcName.size()) {
1476 fprintf(f,"{ \"%s\" }", pData->m_srcName.c_str());
1477 if (pData->m_srcValues.size() && pData->m_srcValues[0] != 1.0) {
1478 fprintf(f, fmt, pData->m_srcValues[0]);
1479 }
1480 }
1481 else {
1482 for (int i = 0; i < pData->m_srcValues.size(); i++) {
1483 fprintf(f, fmt, pData->m_srcValues[i]);
1484 }
1485 }
1486 fprintf(f, "\n");
1487 }
1488
1489 if (f != stdout)
1490 fclose(f);
1491
1492 return true;
1493}
1494
1496{
1497 switch (sig) {
1498 case icSigRgbData:
1499 return "RGB";
1500 case icSigCmykData:
1501 return "CMYK";
1502 case icSigDevXYZData:
1503 case icSigXYZData:
1504 return "XYZ";
1505 case icSigDevLabData:
1506 case icSigLabData:
1507 return "LAB";
1508 case icSigNamedData:
1509 return "TINT";
1510 default:
1511 {
1512 int nSamples = icGetSpaceSamples(sig);
1513 char buf[32];
1514 sprintf(buf, "%dCOLOR", nSamples);
1515 return buf;
1516 }
1517 }
1518}
1519
1520void CIccCfgColorData::addFields(std::string& dataFormat, int& nFields, int& nSamples, icColorSpaceSignature sig, std::string prefix)
1521{
1522 std::string tabStr = "\t";
1523 char buf[32];
1524
1525 switch (sig) {
1526 case icSigRgbData:
1527 nSamples = 3;
1528 if (nFields) dataFormat += tabStr;
1529 dataFormat += prefix + "RGB_R";
1530 dataFormat += tabStr + prefix + "RGB_G";
1531 dataFormat += tabStr + prefix + "RGB_B";
1532 nFields += nSamples;
1533 return;
1534 case icSigCmykData:
1535 nSamples = 4;
1536 if (nFields) dataFormat += tabStr;
1537 dataFormat += prefix + "CMYK_C";
1538 dataFormat += tabStr + prefix + "CMYK_M";
1539 dataFormat += tabStr + prefix + "CMYK_Y";
1540 dataFormat += tabStr + prefix + "CMYK_K";
1541 nFields += nSamples;
1542 return;
1543 case icSigDevLabData:
1544 case icSigLabData:
1545 nSamples += 3;
1546 if (nFields) dataFormat += tabStr;
1547 dataFormat += prefix + "LAB_L";
1548 dataFormat += tabStr + prefix + "LAB_A";
1549 dataFormat += tabStr + prefix + "LAB_B";
1550 nFields += nSamples;
1551 return;
1552 case icSigDevXYZData:
1553 case icSigXYZData:
1554 nSamples += 3;
1555 if (nFields) dataFormat += tabStr;
1556 dataFormat += prefix + "XYZ_X";
1557 dataFormat += tabStr + prefix + "XYZ_Y";
1558 dataFormat += tabStr + prefix + "XYZ_Z";
1559 nFields += 3;
1560 return;
1561 case icSigNamedData:
1562 nSamples += 1;
1563 if (nFields) dataFormat += tabStr;
1564 dataFormat += prefix + "TINT";
1565 nFields += nSamples;
1566 return;
1567 default:
1568 nSamples = icGetSpaceSamples(sig);
1569 if (nFields) dataFormat += tabStr;
1570 for (int i = 0; i < nSamples; i++) {
1571 sprintf(buf, "%dCOLOR_%d", nSamples, i + 1);
1572 if (i)
1573 dataFormat += tabStr;
1574 dataFormat += buf;
1575 }
1576 nFields += nSamples;
1577 return;
1578 }
1579}
1580
1581bool CIccCfgColorData::toIt8(const char* filename, icUInt8Number nDigits, icUInt8Number nPrecision)
1582{
1583 if (!m_data.size())
1584 return false;
1585
1586 FILE* f;
1587 char fmt[64];
1588 if (!nDigits)
1589 sprintf(fmt, " %%.%df", nPrecision);
1590 else
1591 sprintf(fmt, " %%%d.%df", nDigits, nPrecision);
1592
1593 auto first = m_data.begin();
1594 CIccCfgDataEntry* pEntry = first->get();
1595
1596 std::string dataFormat;
1597 int nFields = 0;
1598 bool bShowIndex = false;
1599 bool bShowLabel = false;
1600 bool bShowSrcName = false;
1601 bool bShowSrcValues = false;
1602 bool bShowName = false;
1603 bool bShowValues = false;
1604
1605 int nSrcSamples = 0, nDstSamples = 0;
1606
1607 if (pEntry->m_index >= 0) {
1608 dataFormat = "INDEX";
1609 nFields = 1;
1610 bShowIndex = true;
1611 }
1612
1613 if (pEntry->m_label.size()) {
1614 if (nFields) dataFormat+="\t";
1615 dataFormat += "SAMPLE_ID";
1616 nFields++;
1617 bShowLabel = true;
1618 }
1619
1620 bool bSameSpace = spaceName(m_space) == spaceName(m_srcSpace);
1621
1622 if (pEntry->m_name.size()) {
1623 if (nFields) dataFormat += "\t";
1624 dataFormat += "NAME";
1625 nFields++;
1626 bShowName = true;
1627 }
1628
1629 if (m_space != icSigUnknownData) {
1630 addFields(dataFormat, nFields, nDstSamples, m_space, "");
1631 if (nDstSamples)
1632 bShowValues = true;
1633 }
1634
1635 if (pEntry->m_srcName.size()) {
1636 if (nFields) dataFormat += "\t";
1637 if (bSameSpace)
1638 dataFormat += "SRC_";
1639 dataFormat += "NAME";
1640 nFields++;
1641 bShowSrcName = true;
1642 }
1643
1645 addFields(dataFormat, nFields, nSrcSamples, m_srcSpace, bSameSpace ? "SRC_" : "");
1646 if (nSrcSamples)
1647 bShowSrcValues = true;
1648 }
1649
1650 if (!nFields)
1651 return false;
1652
1653 if (!filename || !filename[0])
1654 f = stdout;
1655 else
1656 f = fopen(filename, "wt");
1657
1658 if (!f)
1659 return false;
1660
1661 fprintf(f, "CGATS.17\n");
1662 fprintf(f, "ORIGINATOR\t\"DemoIccMAX\"\n");
1663 fprintf(f, "FILE_DESCRIPTOR\t\"Color Data\"\n");
1664
1665 fprintf(f, "NUMBER_OF_FIELDS\t%d\n", nFields);
1666 fprintf(f, "BEGIN_DATA_FORMAT\n");
1667 fprintf(f, "%s\n", dataFormat.c_str());
1668 fprintf(f, "END_DATA_FORMAT\n");
1669 fprintf(f, "NUMBER_OF_SETS\t%u\n", (int)m_data.size());
1670
1671 CIccCfgDataEntry blank;
1672 char buf[256];
1673
1674 fprintf(f, "BEGIN_DATA\n");
1675 for (auto e = m_data.begin(); e != m_data.end(); e++) {
1676 std::string line;
1677
1678 CIccCfgDataEntry* pEntry = e->get();
1679 if (!pEntry)
1680 pEntry = &blank;
1681
1682 if (bShowIndex) {
1683 sprintf(buf, "%d", pEntry->m_index);
1684 line += buf;
1685 }
1686
1687 if (bShowLabel) {
1688 if (line.size()) line += "\t";
1689 if (!pEntry->m_label.size())
1690 line += "\"\"";
1691 else
1692 line += pEntry->m_label;
1693 }
1694
1695 if (bShowName) {
1696 if (line.size()) line += "\t";
1697 if (!pEntry->m_name.size())
1698 line += "\"\"";
1699 else
1700 line += pEntry->m_name;
1701 }
1702
1703 if (bShowValues) {
1704 if (line.size()) line += "\t";
1705 for (int i = 0; i < nDstSamples; i++) {
1706 icFloatNumber v = i >= pEntry->m_values.size() ? 0 : pEntry->m_values[i];
1707 sprintf(buf, fmt, v);
1708 if (i)
1709 line += "\t";
1710 line += buf;
1711 }
1712 }
1713
1714 if (bShowSrcName) {
1715 if (line.size()) line += "\t";
1716 if (!pEntry->m_srcName.size())
1717 line += "\"\"";
1718 else
1719 line += pEntry->m_srcName;
1720 }
1721
1722 if (bShowSrcValues) {
1723 if (line.size()) line += "\t";
1724 for (int i = 0; i < nSrcSamples; i++) {
1725 icFloatNumber v = i >= pEntry->m_srcValues.size() ? 0 : pEntry->m_srcValues[i];
1726 sprintf(buf, fmt, v);
1727 if (i)
1728 line += "\t";
1729 line += buf;
1730 }
1731 }
1732
1733 fprintf(f, "%s\n", line.c_str());
1734 }
1735 fprintf(f, "END_DATA\n");
1736
1737 if (f != stdout)
1738 fclose(f);
1739
1740 return true;
1741}
1742
1743void CIccCfgColorData::toJson(json& obj) const
1744{
1745 char buf[32];
1746 obj["space"] = icGetColorSigStr(buf, m_space);
1747 obj["encoding"] = icGetJsonFloatColorEncoding(m_encoding);
1748 obj["srcSpace"] = icGetColorSigStr(buf, m_srcSpace);
1749 obj["srcEncoding"] = icGetJsonFloatColorEncoding(m_srcEncoding);
1750
1751 json data;
1752 for (auto e = m_data.begin(); e != m_data.end(); e++) {
1753 CIccCfgDataEntry *pData = e->get();
1754 if (!pData)
1755 continue;
1756
1757 json entry;
1758 pData->toJson(entry);
1759 if (entry.is_object())
1760 data.push_back(entry);
1761 }
1762 if (data.is_array() && data.size()) {
1763 obj["data"] = data;
1764 }
1765}
1766
1771
1773{
1774 m_name.clear();
1775 m_values.clear();
1776 m_srcName.clear();
1777 m_srcValues.clear();
1778 m_index = -1;
1779 m_label.clear();
1780 m_debugInfo.clear();
1781}
1782
1783bool CIccCfgDataEntry::fromJson(json j, bool bReset)
1784{
1785 if (!j.is_object())
1786 return false;
1787
1788 if (bReset)
1789 reset();
1790
1791 jsonToValue(j["n"], m_name);
1792 jsonToArray(j["v"], m_values);
1793
1794 jsonToValue(j["sn"], m_srcName);
1795 jsonToArray(j["sv"], m_srcValues);
1796
1797 jsonToValue(j["i"], m_index);
1798 jsonToValue(j["l"], m_label);
1799
1800 jsonToList(j["d"], m_debugInfo);
1801
1802 return true;
1803}
1804
1806{
1807 if (m_name.size())
1808 obj["n"] = m_name;
1809 if (m_values.size())
1810 obj["v"] = m_values;
1811
1812 if (m_srcName.size())
1813 obj["sn"] = m_srcName;
1814 if (m_srcValues.size())
1815 obj["sv"] = m_srcValues;
1816
1817 if (m_label.size())
1818 obj["l"] = m_label;
1819
1820 if (m_index >= 0)
1821 obj["i"] = m_index;
1822
1823 if (m_debugInfo.size())
1824 obj["d"] = m_debugInfo;
1825}
icArraySignature sig
icXformLutType
CMM Xform LUT types.
Definition IccCmm.h:125
@ icXformLutNamedColor
Definition IccCmm.h:127
@ icXformLutBRDFDirect
Definition IccCmm.h:132
@ icXformLutBRDFMcsParam
Definition IccCmm.h:133
@ icXformLutGamut
Definition IccCmm.h:129
@ icXformLutColorimetric
Definition IccCmm.h:135
@ icXformLutMCS
Definition IccCmm.h:134
@ icXformLutColor
Definition IccCmm.h:126
@ icXformLutSpectral
Definition IccCmm.h:136
@ icXformLutPreview
Definition IccCmm.h:128
@ icXformLutBRDFParam
Definition IccCmm.h:131
icXformInterp
CMM Interpolation types.
Definition IccCmm.h:113
@ icInterpTetrahedral
Definition IccCmm.h:115
@ icInterpLinear
Definition IccCmm.h:114
static bool ParseNextNumber(icFloatNumber &num, icChar **text)
static int icTranValues[]
static const char * icTranNames[]
void jsonSetValue(json &j, const char *szName, icCfgDataType v)
bool jsonToValue(const json &j, icFloatColorEncoding &v)
static bool ParseName(icChar *pName, icChar *pString)
static icFloatColorEncoding fileEncValues[]
const char * icGetJsonFileEncoding(icFloatColorEncoding v)
static bool icGetJsonRenderingIntent(const json &j, int &v)
static bool jsonFromEnvMap(json &j, const icCmmEnvSigMap &map)
const char * icGetJsonColorEncoding(icFloatColorEncoding v)
icFloatColorEncoding icSetJsonFileEncoding(const char *szEncode)
std::pair< int, std::string > icIndexName
static icXformInterp icInterpValues[]
static const char * clrEncNames[]
static const char * fileEncNames[]
static bool ParseNumbers(icFloatNumber *pData, icChar *pString, icUInt32Number nSamples)
static const char * icInterpNames[]
static icFloatColorEncoding clrEncValues[]
std::vector< CIccIndexValue > icValueVector
static void setSampleIndex(std::vector< icValueVector > &samples, int index, const char *szFmt, const char **szChannels)
static void setDstBool(json &j, const char *szName, icDstBool v)
static const icChar * icGetJsonFloatColorEncoding(icFloatColorEncoding val)
icFloatColorEncoding icSetJsonColorEncoding(const char *szEncode)
icDstBool
@ icDstBoolTrue
@ icDstBoolFalse
@ icDstBoolFromSrc
@ icCfgCreateIccLinkV5
@ icCfgCreateTextCube
@ icCfgCreateIccLinkV4
std::shared_ptr< CIccCfgDataEntry > CIccCfgDataEntryPtr
std::shared_ptr< CIccCfgProfile > CIccCfgProfilePtr
icCfgDataType
Definition IccCmmConfig.h:8
@ icCfgLegacy
@ icCfgColorData
Definition IccCmmConfig.h:9
@ icCfgIt8
float icFloatNumber
All floating point operations/variables in IccProfLib use the icFloatNumber data type.
Definition IccDefs.h:100
#define ICFLOATFMT
Definition IccDefs.h:106
#define icSigDevXYZData
Definition IccDefs.h:92
char icChar
Definition IccDefs.h:109
#define icSigDevLabData
Additional convenience color space signatures to distinguish between device encoding and PCS encoding...
Definition IccDefs.h:91
std::map< icSignature, icFloatNumber > icCmmEnvSigMap
Definition IccEnvVar.h:83
bool jsonToArray(const json &v, T *vals, int n)
bool jsonToList(const json &v, std::list< std::string > &vals)
bool jsonToColorSpace(const json &j, icColorSpaceSignature &sig)
#define strnicmp
#define stricmp
const icChar * szName
const icChar * icGetColorSig(icChar *pBuf, icUInt32Number nSig, bool bGetHexVal)
Definition IccUtil.cpp:1088
icUInt32Number icGetSpaceSamples(icColorSpaceSignature sig)
Definition IccUtil.cpp:1303
const icChar * icGetColorSigStr(icChar *pBuf, icUInt32Number nSig)
Definition IccUtil.cpp:1139
icUInt32Number icGetSigVal(const icChar *pBuf)
Definition IccUtil.cpp:1258
const icChar * icGetSigStr(icChar *pBuf, icUInt32Number nSig)
Definition IccUtil.cpp:1056
unsigned int icUInt32Number
bool fromLegacy(const char *filename, bool bReset=false)
icFloatColorEncoding m_srcEncoding
bool toIt8(const char *filename, icUInt8Number nDigits, icUInt8Number nPrecision)
void addFields(std::string &dataFormat, int &nFields, int &nSamples, icColorSpaceSignature sig, std::string prefix)
icColorSpaceSignature m_srcSpace
bool fromJson(json obj, bool bReset=false)
bool fromIt8(const char *filename, bool bReset=false)
std::string spaceName(icColorSpaceSignature sig)
void toJson(json &obj) const
icFloatColorEncoding m_encoding
CIccCfgDataEntryList m_data
icColorSpaceSignature m_space
bool toLegacy(const char *filename, CIccCfgProfileSequence *pProfiles, icUInt8Number nDigits, icUInt8Number nPrecision, bool bShowDebug=false)
bool fromJson(json obj, bool bReset=false)
icCfgDataType m_srcType
icUInt8Number m_dstPrecision
void toJson(json &obj) const
icCfgDataType m_dstType
int fromArgs(const char **args, int nArg, bool bReset=false)
icColorSpaceSignature m_srcSpace
icUInt8Number m_dstDigits
std::string m_dstFile
icFloatColorEncoding m_dstEncoding
std::string m_srcFile
void reset()
std::vector< icFloatNumber > m_srcValues
std::string m_srcName
bool fromJson(json obj, bool bReset=false)
int m_index
std::string m_label
std::vector< icFloatNumber > m_values
CIccCfgDataEntry()
std::list< std::string > m_debugInfo
std::string m_name
void toJson(json &obj)
icFloatColorEncoding m_dstEncoding
void toJson(json &obj) const
int fromArgs(const char **args, int nArg, bool bReset=false)
std::string m_dstImgFile
bool fromJson(json obj, bool bReset=false)
std::string m_srcImgFile
icDstBool m_dstCompression
icDstBool m_dstPlanar
icDstBool m_dstEmbedIcc
icCmmEnvSigMap m_pccEnvVars
icXformInterp m_interpolation
void toJson(json &obj) const
std::string m_iccFile
std::string m_pccFile
icXformLutType m_transform
icCmmEnvSigMap m_iccEnvVars
bool m_adjustPcsLuminance
bool fromJson(json obj, bool bReset=false)
CIccCfgProfileArray m_profiles
int fromArgs(const char **args, int nArg, bool bReset=false)
bool fromJson(json obj, bool bReset=false)
void toJson(json &obj) const
icColorSpaceSignature space
icFloatNumber nValue
bool open(const char *szFilename)
bool findTokenLine(std::vector< std::string > &line, const char *szToken)
std::ifstream * m_f
bool parseNextLine(std::vector< std::string > &line)
bool parseLine(std::vector< std::string > &line)
unsigned char icUInt8Number
Number definitions.
#define icUnknownIntent
Convenience Enum Definitions - Not defined in ICC specification.
icColorSpaceSignature
Color Space Signatures.
@ icSigLabData
@ icSigXYZData
@ icSigNamedData
@ icSigCmykData
@ icSigNChannelData
@ icSigRgbData
icUInt32Number icSignature
#define icSigUnknownData
icRenderingIntent
Rendering Intents, used in the profile header.
@ icRelative
@ icPerceptual
@ icAbsolute
@ icSaturation