Hoyt's FORK of DemoIccMAX 2.1.17.hoyt
Documentation for Hoyt's FORK of DemoIccMAX
Loading...
Searching...
No Matches
iccApplyToLink.cpp
Go to the documentation of this file.
1/*
2 File: IccApplyToLink.cpp
3
4 Contains: Console app that applies profiles to create link
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-2023 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 3-15-2023
68//
69//////////////////////////////////////////////////////////////////////
70
71
72#include <stdio.h>
73#include <string>
74#include "IccCmm.h"
75#include "IccUtil.h"
76#include "IccDefs.h"
77#include "IccApplyBPC.h"
78#include "IccEnvVar.h"
79#include "IccProfLibVer.h"
80#include "IccProfile.h"
81#include "IccTagBasic.h"
82#include "IccTagLut.h"
83#include "IccTagMPE.h"
84#include "IccMpeBasic.h"
85
86
87
89{
90public:
92 virtual ~ILinkWriter() {};
93
94 virtual bool setFile(const char* szOutputFile) = 0;
95
96 virtual void setOption(int nOptionValue) = 0;
97
98 virtual void setTitle(const char* szTitle) = 0;
99
100 virtual void setCmm(CIccCmm *pCmm) = 0;
101
102 virtual bool setLutSize(icUInt8Number nGridSize) = 0;
103
104 virtual void setInputRange(icFloatNumber fMinInput, icFloatNumber fMaxInput) = 0;
105
106 virtual bool begin(icColorSpaceSignature srcSpace, icColorSpaceSignature dstSpace) = 0;
107
108 virtual void setNextNode(icFloatNumber* pPixel)=0;
109
110 virtual bool finish() = 0;
111};
112
113typedef std::shared_ptr <ILinkWriter> LinkWriterPtr;
114
115class CCubeWriter : public ILinkWriter, public IXformIterator
116{
117public:
119 virtual ~CCubeWriter()
120 {
121 if (m_f)
122 fclose(m_f);
123 }
124
125 virtual bool setFile(const char* szOutputFile)
126 {
127 m_filename = szOutputFile;
128
129 return true;
130 }
131
132 virtual void setOption(int nOptionValue)
133 {
134 m_precision = nOptionValue;
135 }
136
137 virtual void setTitle(const char* szTitle)
138 {
139 m_title = szTitle;
140 }
141
142 virtual void setCmm(CIccCmm* pCmm)
143 {
144 m_pCmm = pCmm;
145 }
146
147 virtual bool setLutSize(icUInt8Number nGridSize)
148 {
149 m_grid = nGridSize;
150
151 return true;
152 }
153
154 virtual void setInputRange(icFloatNumber fMinInput, icFloatNumber fMaxInput)
155 {
156 m_fMinInput = fMinInput;
157 m_fMaxInput = fMaxInput;
158 }
159
160 virtual bool begin(icColorSpaceSignature srcSpace, icColorSpaceSignature dstSpace)
161 {
162 icUInt32Number nSrcSamples = icGetSpaceSamples(srcSpace);
163 icUInt32Number nDstSamples = icGetSpaceSamples(dstSpace);
164
165 if (nSrcSamples != 3) {
166 printf("# of source Samples is not 3\n");
167 return false;
168 }
169
170 if (nDstSamples != 3) {
171 printf("# of destination samples is not 3\n");
172 return false;
173 }
174
175 m_f = fopen(m_filename.c_str(), "wb");
176 if (!m_f) {
177 printf("Unable to open '%s'\n", m_filename.c_str());
178 return false;
179 }
180
181 fprintf(m_f, "TITLE \"%s\"\n\n", m_title.c_str());
182
183 fprintf(m_f, "# cube file created by iccApplyToLink version " ICCPROFLIBVER "\n#\n");
184 if (m_pCmm) {
185 fprintf(m_f, "# Profiles applied (by profile description):\n");
186 m_pCmm->IterateXforms(this);
187 }
188 fprintf(m_f, "\n");
189
190 fprintf(m_f, "LUT_3D_SIZE %d\n", m_grid);
191
192 if (!icIsNear(m_fMinInput, 0.0f) || !icIsNear(m_fMaxInput, 1.0f)) {
193 char fmt[100];
194 sprintf(fmt, "LUT_3D_INPUT_RANGE %%.%df %%.%df\n", m_precision, m_precision);
195 fprintf(m_f, fmt, m_fMinInput, m_fMaxInput);
196 }
197
198 fprintf(m_f, "\n");
199
200 return true;
201 }
202
203 virtual void iterate(const CIccXform* pXform)
204 {
205 if (pXform) {
206 const CIccProfile* pProfile = pXform->GetProfile();
207 if (pProfile) {
208 const CIccTag* pDesc = pProfile->FindTagConst(icSigProfileDescriptionTag);
209 std::string text;
210 if (icGetTagText(pDesc, text)) {
211 fprintf(m_f, "# - %s\n", text.c_str());
212 }
213
214 }
215 }
216 }
217
218 virtual void setNextNode(icFloatNumber* pPixel)
219 {
220 char fmt[30];
221 sprintf(fmt, "%%.%df", m_precision);
222
223 for (int i = 0; i < 3; i++) {
224 if (i)
225 fprintf(m_f, " ");
226 fprintf(m_f, fmt, pPixel[i]);
227 }
228 fprintf(m_f, "\n");
229 }
230
231 virtual bool finish()
232 {
233 if (m_f)
234 fclose(m_f);
235
236 m_f = nullptr;
237
238 return true;
239 }
240
241protected:
242 std::string m_filename;
243 int m_precision = 4;
244 std::string m_title;
245
246 CIccCmm* m_pCmm = nullptr;
247
248 int m_grid = 0;
249
252
253 FILE* m_f = nullptr;
254};
255
256class CDevLinkWriter : public ILinkWriter, public IXformIterator
257{
258public:
261 {
262 if (m_pProfile)
263 delete m_pProfile;
264 }
265
266 virtual bool setFile(const char* szOutputFile)
267 {
268 m_filename = szOutputFile;
269
270 return true;
271 }
272
273 virtual void setOption(int nOptionValue)
274 {
275 m_bWriteV5 = nOptionValue != 0;
276 }
277
278 virtual void setTitle(const char* szTitle)
279 {
280 m_title = szTitle;
281 }
282
283 virtual void setCmm(CIccCmm* pCmm)
284 {
285 m_pCmm = pCmm;
286 }
287
288 virtual bool setLutSize(icUInt8Number nGridSize)
289 {
290 m_grid = nGridSize;
291
292 return true;
293 }
294
295 virtual void setInputRange(icFloatNumber fMinInput, icFloatNumber fMaxInput)
296 {
297 m_fMinInput = fMinInput;
298 m_fMaxInput = fMaxInput;
299 }
300
301 virtual bool begin(icColorSpaceSignature srcSpace, icColorSpaceSignature dstSpace)
302 {
303 icUInt16Number nSrcSamples = (icUInt16Number)icGetSpaceSamples(srcSpace);
304 icUInt16Number nDstSamples = (icUInt16Number)icGetSpaceSamples(dstSpace);
305 m_nOutSamples = nDstSamples;
306
307 if (!nSrcSamples || (!m_bWriteV5 && nSrcSamples > 15) || (m_bWriteV5 && nSrcSamples > 16)) {
308 printf("Invalid number of source samples\n");
309 return false;
310 }
311 if (!nDstSamples || (!m_bWriteV5 && nDstSamples > 15)) {
312 printf("Invalid number of destination samples\n");
313 return false;
314 }
315
316 CIccInfo Info;
317 if (!Info.IsValidSpace(srcSpace)) {
318 printf("Invalid source color space\n");
319 return false;
320 }
321 if (!Info.IsValidSpace(dstSpace)) {
322 printf("Invalid destination color space\n");
323 return false;
324 }
325
326 m_pProfile = new CIccProfile();
327
328 //Initialize profile header
329 m_pProfile->InitHeader();
330 m_pProfile->m_Header.colorSpace = srcSpace;
331 m_pProfile->m_Header.pcs = dstSpace;
332 m_pProfile->m_Header.deviceClass = icSigLinkClass;
333
334 //Add description Tag
336 if (m_title.size()) {
337 pTextTag->SetText(m_title.c_str());
338 }
339 else {
340 pTextTag->SetText("Device link created by iccApplyToLink");
341 }
342 m_pProfile->AttachTag(icSigProfileDescriptionTag, pTextTag);
343
344 pTextTag = new CIccTagMultiLocalizedUnicode();
345 pTextTag->SetText("Copyright ICC");
346 m_pProfile->AttachTag(icSigCopyrightTag, pTextTag);
347
348 if (m_bWriteV5) {
349 m_pProfile->m_Header.version = icVersionNumberV5;
350
351 //Create A2B0 Tag with LUT
352 CIccTagMultiProcessElement* pTag = new CIccTagMultiProcessElement(nSrcSamples, nDstSamples);
353
354 if (!icIsNear(m_fMinInput, 0.0) || !icIsNear(m_fMaxInput, 1.0)) {
355 CIccMpeCurveSet* pCurves = new CIccMpeCurveSet(nSrcSamples);
357
358 pCurve0->SetSize(2);
359 pCurve0->GetSamples()[0] = 0;
360 pCurve0->GetSamples()[1] = 1;
361
362 pCurves->SetCurve(0, pCurve0);
363
364 for (icUInt16Number i = 1; i < nSrcSamples; i++) {
365 pCurves->SetCurve(1, pCurve0);
366 }
367
368 pTag->Attach(pCurves);
369 }
370
371 CIccMpeCLUT* pMpeCLUT = new CIccMpeCLUT();
372 CIccCLUT* pCLUT = new CIccCLUT((icUInt8Number)nSrcSamples, (icUInt8Number)nDstSamples);
373 pCLUT->Init(m_grid);
374 m_pLutPtr = pCLUT->GetData(0);
375 m_nCountdown = pCLUT->NumPoints();
376
377 pMpeCLUT->SetCLUT(pCLUT);
378 pTag->Attach(pMpeCLUT);
379
380 m_pProfile->AttachTag(icSigAToB0Tag, pTag);
381 }
382 else {
383 m_pProfile->m_Header.version = icVersionNumberV4_3;
384
385 m_pFirstProfile = nullptr;
386 m_pLastProfile = nullptr;
387
389
390 if (m_pCmm) {
391 m_pCmm->IterateXforms(this);
392 }
393
396 }
397 else {
398 delete m_pTagSeq;
399 m_pTagSeq = nullptr;
400 }
401
402 if (icIsSpaceCLR(srcSpace) && m_pFirstProfile) {
403 if (m_pFirstProfile->m_Header.version < icVersionNumberV5) {
404 const CIccTag* pTagColor = m_pFirstProfile->FindTagConst(icSigColorantTableTag);
405 if (pTagColor) {
406 m_pProfile->AttachTag(icSigColorantTableTag, pTagColor->NewCopy());
407 }
408 }
409 else if (m_pFirstProfile->m_Header.version >= icVersionNumberV5) {
410
411 }
412 }
413
414 if (icIsSpaceCLR(dstSpace) && m_pLastProfile) {
415 if (m_pLastProfile->m_Header.deviceClass == icSigLinkClass) {
416 if (m_pLastProfile->m_Header.version < icVersionNumberV5) {
417 const CIccTag* pTagColor = m_pLastProfile->FindTagConst(icSigColorantTableOutTag);
418 if (pTagColor) {
419 m_pProfile->AttachTag(icSigColorantTableTag, pTagColor->NewCopy());
420 }
421 }
422 else if (m_pLastProfile->m_Header.version >= icVersionNumberV5) {
423
424 }
425 }
426 else if (m_pLastProfile->m_Header.version < icVersionNumberV5) {
427 const CIccTag* pTagColor = m_pLastProfile->FindTagConst(icSigColorantTableTag);
428 if (pTagColor) {
429 m_pProfile->AttachTag(icSigColorantTableOutTag, pTagColor->NewCopy());
430 }
431 }
432 else if (m_pLastProfile->m_Header.version >= icVersionNumberV5) {
433
434 }
435 }
436
437 CIccTagLutAtoB* pTagLut = new CIccTagLutAtoB();
438 pTagLut->Init((icUInt8Number)nSrcSamples, (icUInt8Number)nDstSamples);
439 LPIccCurve *pCurves = pTagLut->NewCurvesA();
440 for (icUInt16Number i = 0; i < nSrcSamples; i++) {
441 pCurves[i] = new CIccTagCurve();
442 }
443 pCurves = pTagLut->NewCurvesB();
444 for (icUInt16Number i = 0; i < nDstSamples; i++) {
445 pCurves[i] = new CIccTagCurve();
446 }
447 CIccCLUT* pCLUT = pTagLut->NewCLUT(m_grid);
448 m_pLutPtr = pCLUT->GetData(0);
449 m_nCountdown = pCLUT->NumPoints();
450
451 m_pProfile->AttachTag(icSigAToB0Tag, pTagLut);
452 }
453
454 return true;
455 }
456
457 virtual void iterate(const CIccXform* pXform)
458 {
459 if (pXform) {
460 const CIccProfile* pProfile = pXform->GetProfile();
461 if (pProfile) {
462 if (!m_pFirstProfile)
463 m_pFirstProfile = pProfile;
464 m_pLastProfile = pProfile;
465
466 if (!m_bWriteV5 && m_pTagSeq) {
468
469 psd.m_deviceMfg = pProfile->m_Header.manufacturer;
470 psd.m_deviceModel = pProfile->m_Header.model;
471 psd.m_attributes = pProfile->m_Header.attributes;
472 const CIccTag* pTag = pProfile->FindTagConst(icSigTechnologyTag);
473 if (pTag && pTag->GetType() == icSigSignatureType) {
474 const CIccTagSignature* pSigTag = (const CIccTagSignature*)pTag;
475
477 }
478
479 pTag = pProfile->FindTagConst(icSigDeviceMfgDescTag);
480 if (pTag) {
481 if (pTag->GetType() == icSigTextDescriptionType) {
482 const CIccTagTextDescription* pTextTag = (const CIccTagTextDescription*)pTag;
483
486 if (pText)
487 *pText = *pTextTag;
488 }
489 else if (pTag->GetType() == icSigMultiLocalizedUnicodeType) {
490 const CIccTagMultiLocalizedUnicode* pTextTag = (const CIccTagMultiLocalizedUnicode*)pTag;
491
494 if (pText)
495 *pText = *pTextTag;
496 }
497 }
498
499 pTag = pProfile->FindTagConst(icSigDeviceModelDescTag);
500 if (pTag) {
501 if (pTag->GetType() == icSigTextDescriptionType) {
502 const CIccTagTextDescription* pTextTag = (const CIccTagTextDescription*)pTag;
503
506 if (pText)
507 *pText = *pTextTag;
508 }
509 else if (pTag->GetType() == icSigMultiLocalizedUnicodeType) {
510 const CIccTagMultiLocalizedUnicode* pTextTag = (const CIccTagMultiLocalizedUnicode*)pTag;
511
514 if (pText)
515 *pText = *pTextTag;
516 }
517 }
518
519 m_pTagSeq->m_Descriptions->push_back(psd);
520 }
521 }
522 }
523 }
524
525 virtual void setNextNode(icFloatNumber* pPixel)
526 {
527 if (m_nCountdown) {
528 memcpy(m_pLutPtr, pPixel, m_nOutSamples * sizeof(icFloatNumber));
530 m_nCountdown--;
531 }
532 }
533
534 virtual bool finish()
535 {
536 bool rv = false;
537 if (m_pProfile) {
538 rv = SaveIccProfile(m_filename.c_str(), m_pProfile);
539 delete m_pProfile;
540 }
541
542 m_pProfile = nullptr;
543
544 return rv;
545 }
546
547protected:
548 std::string m_filename;
549 bool m_bWriteV5 = true;
550 std::string m_title;
551
552 std::string m_description;
553
554 CIccCmm* m_pCmm = nullptr;
555
556 int m_grid = 0;
557
560
563
565
566 CIccProfile* m_pProfile = nullptr;
567
568 //For establishing the profile sequence description and color order tags for v4
569 const CIccProfile* m_pFirstProfile = nullptr;
570 const CIccProfile* m_pLastProfile = nullptr;
571
573};
574
575
576typedef std::list<CIccProfile*> IccProfilePtrList;
577
578
579void Usage()
580{
581 printf("iccApplyToLink built with IccProfLib version " ICCPROFLIBVER "\n\n");
582
583 printf("Usage: iccApplyToLink dst_link_file link_type lut_size option title range_min range_max first_transform interp {{-ENV:sig value} profile_file_path rendering_intent {-PCC connection_conditions_path}}\n\n");
584 printf(" dst_link_file is path of file to create\n\n");
585
586 printf(" For link_type:\n");
587 printf(" 0 - Device Link\n");
588 printf(" 1 - .cube text file\n\n");
589
590 printf(" Where lut_size represents the number of grid entries for each lut dimension.\n\n");
591
592 printf(" For option when link_type is 0:\n");
593 printf(" option represents the digits of precision for lut for .cube files\n");
594 printf(" For option when link_type is 1:\n");
595 printf(" 0 - version 4 profile with 16-bit table\n");
596 printf(" 1 - version 5 profile\n\n");
597
598 printf(" title is the title/description for the dest_link_file\n\n");
599
600 printf(" range_min specifies the minimum input value (usually 0.0)\n");
601 printf(" range_max specifies the maximum input value (usually 1.0)\n\n");
602
603 printf(" For first_transform:\n");
604 printf(" 0 - use source transform from first profile\n");
605 printf(" 1 - use destination transform from first profile\n\n");
606
607 printf(" For interp:\n");
608 printf(" 0 - linear interpolation\n");
609 printf(" 1 - tetrahedral interpolation\n\n");
610
611 printf(" For rendering_intent:\n");
612 printf(" 0 - Perceptual\n");
613 printf(" 1 - Relative\n");
614 printf(" 2 - Saturation\n");
615 printf(" 3 - Absolute\n");
616 printf(" 10 - Perceptual without D2Bx/B2Dx\n");
617 printf(" 11 - Relative without D2Bx/B2Dx\n");
618 printf(" 12 - Saturation without D2Bx/B2Dx\n");
619 printf(" 13 - Absolute without D2Bx/B2Dx\n");
620 printf(" 20 - Preview Perceptual\n");
621 printf(" 21 - Preview Relative\n");
622 printf(" 22 - Preview Saturation\n");
623 printf(" 23 - Preview Absolute\n");
624 printf(" 30 - Gamut\n");
625 printf(" 33 - Gamut Absolute\n");
626 printf(" 40 - Perceptual with BPC\n");
627 printf(" 41 - Relative Colorimetric with BPC\n");
628 printf(" 42 - Saturation with BPC\n");
629 printf(" 50 - BDRF Parameters\n");
630 printf(" 60 - BDRF Direct\n");
631 printf(" 70 - BDRF MCS Parameters\n");
632 printf(" 80 - MCS connection\n");
633 printf(" +100 - Use Luminance based PCS adjustment\n");
634 printf(" +1000 - Use V5 sub-profile if present\n");
635}
636
637//===================================================
638
639int main(int argc, icChar* argv[])
640{
641 int minargs = 10; // minimum number of arguments
642 if(argc<minargs) {
643 Usage();
644 return -1;
645 }
646
647 int nNumProfiles, temp;
648 temp = argc - minargs;
649
650 //remaining arguments must be in pairs
651 if(temp%2 != 0) {
652 printf("\nMissing arguments!\n");
653 Usage();
654 return -1;
655 }
656
657 nNumProfiles = temp/2;
658
659 ILinkWriter* pLinkWriter;
660 if (atoi(argv[2])) {
661 pLinkWriter = new CCubeWriter();
662 }
663 else {
664 pLinkWriter = new CDevLinkWriter();
665 }
666
667 if (!pLinkWriter) {
668 printf("Unable to allocate writer\n");
669 return -1;
670 }
671
672 LinkWriterPtr pWriter(pLinkWriter);
673
674 pWriter->setFile(argv[1]);
675
676 int nLutSize = atoi(argv[3]);
677 pWriter->setLutSize(nLutSize);
678
679 pWriter->setOption(atoi(argv[4]));
680
681 pWriter->setTitle(argv[5]);
682
683 icFloatNumber loRange = (icFloatNumber)atof(argv[6]);
684 icFloatNumber hiRange = (icFloatNumber)atof(argv[7]);
685 icFloatNumber sizeRange = hiRange - loRange;
686 pWriter->setInputRange(loRange, hiRange);
687
688 //Retrieve command line arguments
689 bool bFirstTransform = atoi(argv[8]) != 0;
690 icXformInterp nInterp = (icXformInterp)atoi(argv[9]);
691
692 int nIntent, nType, nLuminance;
693
694 //Allocate a CIccCmm to use to apply profiles.
695 //Let profiles determine starting and ending color spaces.
696 //Third argument indicates that Input transform from first profile should be used.
697 CIccCmm theCmm(icSigUnknownData, icSigUnknownData, bFirstTransform);
698
699 //PCC profiles need to stay around until the CMM has been completely initialized to apply transforms.
700 //TheCmm doesn't own them so keep a list so they can be released when they aren't needed any more.
701 IccProfilePtrList pccList;
702
703 int i, nCount;
704 bool bUseD2BxB2DxTags;
705 icStatusCMM stat; //status variable for CMM operations
706 icCmmEnvSigMap sigMap; //Keep track of CMM Environment for each profile
707 bool bUseSubProfile;
708
709 //Remaining arguments define a sequence of profiles to be applied.
710 //Add them to theCmm one at a time providing CMM environment variables and PCC overrides as provided.
711 for(i = 0, nCount=minargs; i<nNumProfiles; i++, nCount+=2) {
712#if defined(_WIN32) || defined(_WIN64)
713 if (!strnicmp(argv[nCount], "-ENV:", 5)) { //check for -ENV: to allow for CMM Environment variables to be defined for next transform
714#else
715 if (!strncasecmp(argv[nCount], "-ENV:", 5)) {
716#endif
717 icSignature sig = icGetSigVal(argv[nCount]+5);
718 icFloatNumber val = (icFloatNumber)atof(argv[nCount+1]);
719
720 sigMap[sig]=val;
721 }
722 else if (stricmp(argv[nCount], "-PCC")) { //Attach profile while ignoring -PCC (this are handled below as profiles are attached)
723 bUseD2BxB2DxTags = true;
724 nIntent = atoi(argv[nCount+1]);
725 bUseSubProfile = (nIntent / 1000) > 0;
726 nIntent = nIntent % 1000;
727 nLuminance = nIntent / 100;
728 nIntent = nIntent % 100;
729 nType = abs(nIntent) / 10;
730 nIntent = nIntent % 10;
731 CIccProfile *pPccProfile = NULL;
732
733 //Adjust type and hint information based on rendering intent
734 CIccCreateXformHintManager Hint;
735 switch(nType) {
736 case 1:
737 nType = 0;
738 bUseD2BxB2DxTags = false;
739 break;
740 case 4:
741 nType = 0;
742 Hint.AddHint(new CIccApplyBPCHint());
743 break;
744 }
745
746 if (nLuminance) {
747 Hint.AddHint(new CIccLuminanceMatchingHint());
748 }
749
750 // Use of following -PCC arg allows for profile connection conditions to be defined
751 if (i+1<nNumProfiles && !stricmp(argv[nCount+2], "-PCC")) {
752 pPccProfile = OpenIccProfile(argv[nCount+3]);
753 if (!pPccProfile) {
754 printf("Unable to open Profile Connections Conditions from '%s'\n", argv[nCount+3]);
755 return -1;
756 }
757 //Keep track of pPccProfile for until after cmm.Begin is called
758 pccList.push_back(pPccProfile);
759 }
760
761
762 //CMM Environment variables are passed in as a Hint to the Xform associated with the profile
763 if (sigMap.size()>0) {
764 Hint.AddHint(new CIccCmmEnvVarHint(sigMap));
765 }
766
767 //Read profile from path and add it to theCmm
768 CIccProfile* pXformProfile = ReadIccProfile(argv[nCount], bUseSubProfile); //We need all tags in profile for providing information to link
769 stat = theCmm.AddXform(pXformProfile, nIntent<0 ? icUnknownIntent : (icRenderingIntent)nIntent, nInterp, pPccProfile,
770 (icXformLutType)nType, bUseD2BxB2DxTags, &Hint);
771 if (stat) {
772 printf("Invalid Profile(%d): %s\n", stat, argv[nCount]);
773 return -1;
774 }
775 sigMap.clear();
776
777 }
778 }
779
780 //All profiles have been added to CMM. Tell CMM that we are ready to begin applying colors/pixels
781 if((stat=theCmm.Begin())) {
782 printf("Error %d - Unable to begin profile application - Possibly invalid or incompatible profiles\n", stat);
783 return -1;
784 }
785
786 pWriter->setCmm(&theCmm);
787
788 //Now we can release the pccProfile nodes.
789 IccProfilePtrList::iterator pcc;
790 for (pcc=pccList.begin(); pcc!=pccList.end(); pcc++) {
791 CIccProfile *pPccProfile = *pcc;
792 delete pPccProfile;
793 }
794 pccList.clear();
795
796 if (!pWriter->begin(theCmm.GetSourceSpace(), theCmm.GetDestSpace())) {
797 printf("Unable to begin writing LUT\n");
798 return -1;
799 }
800
801 //Get and validate the source color space from the Cmm.
802 icColorSpaceSignature SrcspaceSig = theCmm.GetSourceSpace();
803 int nSrcSamples = icGetSpaceSamples(SrcspaceSig);
804
805 //Get and validate the destination color space from theCmm.
806 icColorSpaceSignature DestspaceSig = theCmm.GetDestSpace();
807 int nDestSamples = icGetSpaceSamples(DestspaceSig);
808
809 int* idx = new int[nSrcSamples];
810 icFloatNumber* srcPixel = new icFloatNumber[nSrcSamples];
811 icFloatNumber* dstPixel = new icFloatNumber[nDestSamples];
812
813 icUInt32Number maxLut = nLutSize - 1;
814
815 int curPer, lastPer = -1;
816
817 //init idx;
818 int lutCount = 1;
819 for (auto i = 0; i < nSrcSamples; i++) {
820 idx[i] = 0;
821 lutCount *= nLutSize;
822 }
823
824 int j = 0;
825 for (int c = 0; j >= 0; c++) {
826
827 for (auto i = 0; i < nSrcSamples; i++) {
828 srcPixel[i] = sizeRange * (icFloatNumber)idx[i] / maxLut + loRange;
829 }
830
831 //Use CMM to convert SrcPixel to DestPixel
832 theCmm.Apply(dstPixel, srcPixel);
833
834 pWriter->setNextNode(dstPixel);
835
836 for (j = nSrcSamples - 1; j >= 0;) {
837 idx[j]++;
838 if (idx[j] >= nLutSize) {
839 idx[j] = 0;
840 j--;
841 }
842 else
843 break;
844 }
845
846 //Display status of how much we have accomplished
847 curPer = (int)((float)(c + 1) * 100.0f / (float)lutCount);
848 if (curPer != lastPer) {
849 printf("\r%d%%", curPer);
850 lastPer = curPer;
851 }
852 }
853
854 delete[] dstPixel;
855 delete[] srcPixel;
856 delete[] idx;
857
858 if (pWriter->finish()) {
859 printf("\nLUT successfully written to '%s'\n", argv[1]);
860 }
861 else {
862 printf("\nUnable to write LUT to '%s'\n", argv[1]);
863 }
864
865 return 0;
866}
867
File: IccApplyBPC.h.
icArraySignature sig
File: IccCmm.h.
icXformLutType
CMM Xform LUT types.
Definition IccCmm.h:125
icXformInterp
CMM Interpolation types.
Definition IccCmm.h:113
icStatusCMM
CMM return status values.
Definition IccCmm.h:90
File: IccDefs.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
File: IccEnvVar.h.
std::map< icSignature, icFloatNumber > icCmmEnvSigMap
Definition IccEnvVar.h:83
File: IccMpeBasic.h.
#define strnicmp
#define stricmp
#define ICCPROFLIBVER
bool SaveIccProfile(const icChar *szFilename, CIccProfile *pIcc, icProfileIDSaveMethod nWriteId)
Name: SaveIccProfile.
CIccProfile * ReadIccProfile(const icChar *szFilename, bool bUseSubProfile)
Name: ReadIccProfile.
CIccProfile * OpenIccProfile(const icChar *szFilename, bool bUseSubProfile)
Name: OpenIccProfile.
File: IccProfile.h.
bool icGetTagText(const CIccTag *pTag, std::string &text)
File: IccTagBasic.h.
File: IccTagLut.h.
File: IccTagMPE.h.
icUInt32Number icGetSpaceSamples(icColorSpaceSignature sig)
Definition IccUtil.cpp:1303
bool icIsNear(icFloatNumber v1, icFloatNumber v2, icFloatNumber nearRange)
Name: icIsNear.
Definition IccUtil.cpp:142
bool icIsSpaceCLR(icColorSpaceSignature sig)
Definition IccUtil.cpp:262
icUInt32Number icGetSigVal(const icChar *pBuf)
Definition IccUtil.cpp:1258
File: IccUtil.h.
int main()
Core and external libraries necessary for the fuzzer functionality.
unsigned int icUInt32Number
virtual void setNextNode(icFloatNumber *pPixel)
virtual ~CCubeWriter()
virtual bool setFile(const char *szOutputFile)
icFloatNumber m_fMinInput
std::string m_title
virtual void setTitle(const char *szTitle)
virtual void setInputRange(icFloatNumber fMinInput, icFloatNumber fMaxInput)
virtual bool begin(icColorSpaceSignature srcSpace, icColorSpaceSignature dstSpace)
virtual bool finish()
virtual void setCmm(CIccCmm *pCmm)
std::string m_filename
icFloatNumber m_fMaxInput
virtual bool setLutSize(icUInt8Number nGridSize)
virtual void setOption(int nOptionValue)
virtual void iterate(const CIccXform *pXform)
Type: Class.
Definition IccApplyBPC.h:89
Class: CIccCLUT.
Definition IccTagLut.h:326
icUInt32Number NumPoints() const
Definition IccTagLut.h:348
icFloatNumber * GetData(int index)
Definition IccTagLut.h:347
bool Init(icUInt8Number nGridPoints, icUInt32Number nMaxSize=0, icUInt8Number nBytesPerPoint=4)
Name: CIccCLUT::Init.
Class: CIccCurve.
Definition IccTagLut.h:91
Type: Class.
Definition IccUtil.h:303
bool IsValidSpace(icColorSpaceSignature sig)
Definition IccUtil.cpp:2531
LPIccCurve * NewCurvesB()
Name: CIccMBB::NewCurvesB.
LPIccCurve * NewCurvesA()
Name: CIccMBB::NewCurvesA.
CIccCLUT * NewCLUT(icUInt8Number nGridPoints, icUInt8Number nPrecision=2)
Name: CIccMBB::NewCLUT.
void Init(icUInt8Number nInputChannels, icUInt8Number nOutputChannels)
Name: CIccMBB::Init.
Class: CIccMpeCLUT.
void SetCLUT(CIccCLUT *pCLUT)
Name: CIccMpeCLUT::SetCLUT.
Class: CIccMpeCurveSet.
bool SetCurve(int nIndex, icCurveSetCurvePtr newCurve)
Name: CIccMpeCurveSet::SetCurve.
Data Class: CIccProfileDescStruct.
CIccProfileDescText m_deviceMfgDesc
icSignature m_deviceModel
icTechnologySignature m_technology
CIccProfileDescText m_deviceModelDesc
icUInt64Number m_attributes
bool SetType(icTagTypeSignature nType)
Name: CIccProfileDescText::SetType.
CIccTag * GetTag() const
Class: CIccSingleSampledCurve.
virtual icFloatNumber * GetSamples()
virtual bool SetSize(icUInt32Number nSize, bool bZeroAlloc=true)
Name: CIccSingleSampledCurve::SetSize.
Class: CIccTagCurve.
Definition IccTagLut.h:128
Class: CIccTag.
virtual icTagTypeSignature GetType() const
Function: GetType()
virtual CIccTag * NewCopy() const
Function: NewCopy(sDescription) Each derived tag will implement it's own NewCopy() function.
Class: CIccTagLutAtoB.
Definition IccTagLut.h:502
Class: CIccTagMultiLocalizedUnicode.
void SetText(const icChar *szText, icLanguageCode nLanguageCode=icLanguageCodeEnglish, icCountryCode nRegionCode=icCountryCodeUSA)
Name: refIccMAX::CIccTagMultiLocalizedUnicode::SetText.
Class: CIccTagMultiProcessElement.
Definition IccTagMPE.h:358
virtual void Attach(CIccMultiProcessElement *pElement)
Name: CIccTagMultiProcessElement::Attach.
Class: CIccTagProfileSeqDesc.
CIccProfileSeqDesc * m_Descriptions
Class: CIccTagSignature.
icUInt32Number GetValue() const
Class: CIccTagTextDescription()
unsigned char icUInt8Number
Number definitions.
#define icVersionNumberV4_3
#define icUnknownIntent
Convenience Enum Definitions - Not defined in ICC specification.
unsigned short icUInt16Number
icTechnologySignature
technology signature descriptions
@ icSigLinkClass
icColorSpaceSignature
Color Space Signatures.
icUInt32Number icSignature
@ icSigMultiLocalizedUnicodeType
@ icSigTextDescriptionType
@ icSigSignatureType
#define icSigUnknownData
#define icVersionNumberV5
@ icSigDeviceMfgDescTag
@ icSigAToB0Tag
@ icSigDeviceModelDescTag
@ icSigColorantTableTag
@ icSigProfileSequenceDescTag
@ icSigProfileDescriptionTag
@ icSigCopyrightTag
@ icSigColorantTableOutTag
@ icSigTechnologyTag
icRenderingIntent
Rendering Intents, used in the profile header.
std::list< CIccProfile * > IccProfilePtrList