Hoyt's FORK of DemoIccMAX 2.1.17.hoyt
Documentation for Hoyt's FORK of DemoIccMAX
Loading...
Searching...
No Matches
iccApplyNamedCmm.cpp File Reference
#include "IccCmm.h"
#include "IccUtil.h"
#include "IccDefs.h"
#include "IccApplyBPC.h"
#include "IccEnvVar.h"
#include "IccMpeCalc.h"
#include "IccProfLibVer.h"
#include "..\IccCommon\IccCmmConfig.h"
+ Include dependency graph for iccApplyNamedCmm.cpp:

Go to the source code of this file.

Classes

class  CIccLogDebugger
 

Macros

#define IsSpacePCS(x)   ((x)==icSigXYZData || (x)==icSigLabData)
 

Typedefs

typedef std::list< CIccProfile * > IccProfilePtrList
 
typedef std::shared_ptr< CIccLogDebuggerLogDebuggerPtr
 

Functions

int main (int argc, const char *argv[])
 
void Usage ()
 

Macro Definition Documentation

◆ IsSpacePCS

#define IsSpacePCS ( x)    ((x)==icSigXYZData || (x)==icSigLabData)

Definition at line 89 of file iccApplyNamedCmm.cpp.

Referenced by main().

Typedef Documentation

◆ IccProfilePtrList

typedef std::list<CIccProfile*> IccProfilePtrList

Definition at line 183 of file iccApplyNamedCmm.cpp.

◆ LogDebuggerPtr

typedef std::shared_ptr<CIccLogDebugger> LogDebuggerPtr

Definition at line 176 of file iccApplyNamedCmm.cpp.

Function Documentation

◆ main()

int main ( int argc,
const char * argv[] )

Definition at line 234 of file iccApplyNamedCmm.cpp.

235{
236 int minargs = 2;
237 if (argc < minargs) {
238 Usage();
239 return -1;
240 }
241
242 CIccCfgDataApply cfgApply;
243 CIccCfgProfileSequence cfgProfiles;
244 CIccCfgColorData cfgData;
245
246 if (argc > 2 && !stricmp(argv[1], "-cfg")) {
247 json cfg;
248 if (!loadJsonFrom(cfg, argv[2]) || !cfg.is_object()) {
249 printf("Unable to read configuration from '%s'\n", argv[2]);
250 return -1;
251 }
252
253 if (cfg.find("dataFiles") == cfg.end() || !cfgApply.fromJson(cfg["dataFiles"])) {
254 printf("Unable to parse dataFile configuration from '%s'\n", argv[2]);
255 return -1;
256 }
257
258 if (cfg.find("profileSequence") == cfg.end() || !cfgProfiles.fromJson(cfg["profileSequence"])) {
259 printf("Unable to parse profileSequence configuration from '%s'\n", argv[2]);
260 return -1;
261 }
262
263 if (cfgApply.m_srcType == icCfgColorData) {
264 if (cfgApply.m_srcFile.empty()) {
265 if (!cfgData.fromJson(cfg["colorData"])) {
266 printf("Unable to parse colorData configuration from '%s'\n", argv[2]);
267 }
268 }
269 else {
270 json data;
271 if (!loadJsonFrom(data, cfgApply.m_srcFile.c_str()) || !cfgData.fromJson(data)) {
272 printf("Unable to load color data from '%s'\n", cfgApply.m_srcFile.c_str());
273 return -1;
274 }
275 }
276 }
277 }
278 else {
279 argv++;
280 argc--;
281
282 if (argc > 1 && !stricmp(argv[0], "-debugcalc")) {
283 cfgApply.m_debugCalc = true;
284
285 argv++;
286 argc--;
287 }
288
289 int nArg = cfgApply.fromArgs(&argv[0], argc);
290 if (!nArg) {
291 printf("Unable to parse configuration arguments\n");
292 return -1;
293 }
294 argv += nArg;
295 argc -= nArg;
296
297 nArg = cfgProfiles.fromArgs(&argv[0], argc);
298 if (!nArg) {
299 printf("Unable to parse profile sequence arguments\n");
300 return -1;
301 }
302
303 if (cfgApply.m_srcType != icCfgLegacy || !cfgData.fromLegacy(cfgApply.m_srcFile.c_str())) {
304 printf("Unable to parse legacy data file '%s'\n", cfgApply.m_srcFile.c_str());
305 return -1;
306 }
307 }
308 LogDebuggerPtr pDebugger;
309
310 if (cfgApply.m_debugCalc) {
311 pDebugger = LogDebuggerPtr(new CIccLogDebugger());
312 IIccCalcDebugger::SetDebugger(pDebugger.get());
313 }
314
315 char precisionStr[30];
316 sprintf(precisionStr, "%%%d.%dlf ", cfgApply.m_dstDigits, cfgApply.m_dstPrecision);
317
318 icFloatColorEncoding srcEncoding, destEncoding;
319
320 //Setup source encoding
321 srcEncoding = cfgData.m_encoding;
322
323 icColorSpaceSignature SrcspaceSig = cfgData.m_srcSpace;
324
325 //If first profile colorspace is PCS and it matches the source data space then treat as input profile
326 bool bInputProfile = !IsSpacePCS(SrcspaceSig);
327 if (!bInputProfile) {
328 CIccProfile *pProf = OpenIccProfile(cfgProfiles.m_profiles[0]->m_iccFile.c_str());
329 if (pProf) {
330 if (pProf->m_Header.deviceClass!=icSigAbstractClass && IsSpacePCS(pProf->m_Header.colorSpace))
331 bInputProfile = true;
332 delete pProf;
333 }
334 }
335
336 //Allocate a CIccCmm to use to apply profiles
337 CIccNamedColorCmm namedCmm(SrcspaceSig, icSigUnknownData, bInputProfile);
338 IccProfilePtrList pccList;
339
340 icCmmEnvSigMap sigMap;
341 bool bUseSubProfile = false;
342
343 for (auto pProfIter = cfgProfiles.m_profiles.begin(); pProfIter != cfgProfiles.m_profiles.end(); pProfIter++) {
344 CIccCfgProfile* pProfCfg = pProfIter->get();
345
346 if (!pProfCfg)
347 continue;
348
349 CIccProfile *pPccProfile = NULL;
350
351 //Adjust type and hint information based on rendering intent
352 CIccCreateXformHintManager Hint;
353 if (pProfCfg->m_useBPC)
354 Hint.AddHint(new CIccApplyBPCHint());
355
356 if (pProfCfg->m_adjustPcsLuminance) {
357 Hint.AddHint(new CIccLuminanceMatchingHint());
358 }
359
360 if (pProfCfg->m_pccFile.size()) {
361 pPccProfile = OpenIccProfile(pProfCfg->m_pccFile.c_str());
362 if (!pPccProfile) {
363 printf("Unable to open Profile Connections Conditions from '%s'\n", pProfCfg->m_pccFile.c_str());
364 return -1;
365 }
366 //Keep track of pPccProfile for until after cmm.Begin is called
367 pccList.push_back(pPccProfile);
368 }
369
370 //CMM Environment variables are passed in as a Hint to the Xform associated with the profile
371 if (pProfCfg->m_iccEnvVars.size()>0) {
372 Hint.AddHint(new CIccCmmEnvVarHint(pProfCfg->m_iccEnvVars));
373 }
374
375 if (pProfCfg->m_pccEnvVars.size() > 0) {
376 Hint.AddHint(new CIccCmmPccEnvVarHint(pProfCfg->m_pccEnvVars));
377 }
378
379 //Read profile from path and add it to namedCmm
380 if (namedCmm.AddXform(pProfCfg->m_iccFile.c_str(),
381 pProfCfg->m_intent<0 ? icUnknownIntent : (icRenderingIntent)pProfCfg->m_intent,
382 pProfCfg->m_interpolation,
383 pPccProfile,
384 pProfCfg->m_transform,
385 pProfCfg->m_useD2BxB2Dx,
386 &Hint,
387 pProfCfg->m_useV5SubProfile)) {
388 printf("Invalid Profile: %s\n", pProfCfg->m_iccFile.c_str());
389 return -1;
390 }
391 }
392
393 icStatusCMM stat;
394
395 //All profiles have been added to CMM. Tell CMM that we are ready to begin applying colors/pixels
396 if((stat=namedCmm.Begin())) {
397 printf("Error %d - Unable to begin profile application - Possibly invalid or incompatible profiles\n", stat);
398 return -1;
399 }
400
401 CIccCmm *pMruCmm = NULL; // CIccMruCmm::Attach(&namedCmm, 6, false);
402
403 //Now we can release the pccProfile nodes.
404 IccProfilePtrList::iterator pcc;
405 for (pcc=pccList.begin(); pcc!=pccList.end(); pcc++) {
406 CIccProfile *pPccProfile = *pcc;
407 delete pPccProfile;
408 }
409 pccList.clear();
410
411 //Get and validate the source color space from namedCmm.
412 SrcspaceSig = namedCmm.GetSourceSpace();
413 int nSrcSamples = icGetSpaceSamples(SrcspaceSig);
414
415 bool bClip = true;
416 //We don't want to interpret device data as pcs encoded data
417 if (bInputProfile && IsSpacePCS(SrcspaceSig)) {
418 if (SrcspaceSig == icSigXYZPcsData)
419 SrcspaceSig = icSigDevXYZData;
420 else if (SrcspaceSig == icSigLabPcsData)
421 SrcspaceSig = icSigDevLabData;
422
423 if (srcEncoding == icEncodeFloat)
424 bClip = false;
425 }
426
427 //Get and validate the destination color space from namedCmm.
428 icColorSpaceSignature DestspaceSig = namedCmm.GetDestSpace();
429 int nDestSamples = icGetSpaceSamples(DestspaceSig);
430
431 //Allocate pixel buffers for performing encoding transformations
432 char SrcNameBuf[256], DestNameBuf[256];
433 CIccPixelBuf SrcPixel(nSrcSamples+16), DestPixel(nDestSamples+16), Pixel(icIntMax(nSrcSamples, nDestSamples)+16);
434
435 CIccCfgColorData outData;
436
437 outData.m_space = DestspaceSig;
438
439 destEncoding = cfgApply.m_dstEncoding;
440 if(DestspaceSig==icSigNamedData)
441 destEncoding = icEncodeValue;
442 outData.m_encoding = destEncoding;
443
444 outData.m_srcSpace = SrcspaceSig;
445
446 if(SrcspaceSig==icSigNamedData)
447 srcEncoding = icEncodeValue;
448 outData.m_srcEncoding = srcEncoding;
449
450 //Apply profiles to each input color
451 for (auto dataIter = cfgData.m_data.begin(); dataIter != cfgData.m_data.end(); dataIter++) {
452 CIccCfgDataEntry* pData = dataIter->get();
453
454 int i;
455
456 if (!pData)
457 continue;
458
459 if (pDebugger)
460 pDebugger->reset();
461
463
464 out->m_srcName = pData->m_name;
465 out->m_srcValues = pData->m_srcValues;
466
467 //Are names coming is as an input?
468 if(SrcspaceSig ==icSigNamedData) {
469
470 const char* szName = pData->m_name.c_str();
471 icFloatNumber tint;
472
473 if (pData->m_values.size())
474 tint = pData->m_values[0];
475 else
476 tint = 1.0;
477
478 switch(namedCmm.GetInterface()) {
479 case icApplyNamed2Pixel:
480 {
481
482 if(namedCmm.Apply(DestPixel, szName, tint)) {
483 printf("Profile application failed.\n");
484 return -1;
485 }
486
487 if(CIccCmm::FromInternalEncoding(DestspaceSig, destEncoding, DestPixel, DestPixel, destEncoding!=icEncodeFloat)) {
488 printf("Invalid final data encoding\n");
489 return -1;
490 }
491
492 for(i = 0; i<nDestSamples; i++) {
493 out->m_values.push_back(DestPixel[i]);
494 }
495 break;
496 }
497 case icApplyNamed2Named:
498 {
499 if(namedCmm.Apply(DestNameBuf, SrcNameBuf, tint)) {
500 printf("Profile application failed.\n");
501 return -1;
502 }
503
504 out->m_name = DestNameBuf;
505 break;
506 }
507 case icApplyPixel2Pixel:
508 case icApplyPixel2Named:
509 default:
510 printf("Incorrect interface.\n");
511 return -1;
512 }
513 }
514 else {
515 for (i = 0; i < nSrcSamples && i < pData->m_values.size(); i++) {
516 Pixel[i] = pData->m_values[i];
517 }
518
519 out->m_srcValues = pData->m_values;
520
521 if(CIccCmm::ToInternalEncoding(SrcspaceSig, srcEncoding, SrcPixel, Pixel, bClip)) {
522 printf("Invalid source data encoding\n");
523 return -1;
524 }
525
526 switch(namedCmm.GetInterface()) {
527 case icApplyPixel2Pixel:
528 {
529 if (pMruCmm) {
530 if (pMruCmm->Apply(DestPixel, SrcPixel)) {
531 printf("Profile application failed.\n");
532 return -1;
533 }
534 }
535 else if(namedCmm.Apply(DestPixel, SrcPixel)) {
536 printf("Profile application failed.\n");
537 return -1;
538 }
539 if(CIccCmm::FromInternalEncoding(DestspaceSig, destEncoding, DestPixel, DestPixel)) {
540 printf("Invalid final data encoding\n");
541 return -1;
542 }
543
544 for(i = 0; i<nDestSamples; i++) {
545 out->m_values.push_back(DestPixel[i]);
546 }
547 break;
548 }
549 case icApplyPixel2Named:
550 {
551 if(namedCmm.Apply(DestNameBuf, SrcPixel)) {
552 printf("Profile application failed.\n");
553 return -1;
554 }
555 out->m_name = DestNameBuf;
556 break;
557 }
558 case icApplyNamed2Pixel:
559 case icApplyNamed2Named:
560 default:
561 printf("Incorrect interface.\n");
562 return -1;
563 }
564 }
565
566 if (pDebugger)
567 out->m_debugInfo = pDebugger->m_log;
568
569 outData.m_data.push_back(out);
570 }
571
572 //Now output the data
573// cfgApply.m_dstType = icCfgIt8;
574// cfgApply.m_dstDigits = 0;
575// cfgApply.m_dstPrecision = 2;
576// cfgApply.m_debugCalc = false;
577
578 if (cfgApply.m_dstType == icCfgLegacy) {
579 outData.toLegacy(cfgApply.m_dstFile.c_str(), &cfgProfiles, cfgApply.m_dstDigits, cfgApply.m_dstPrecision, cfgApply.m_debugCalc);
580 }
581 else if (cfgApply.m_dstType == icCfgColorData) {
582 json out;
583 json seq;
584 cfgProfiles.toJson(seq);
585 if (seq.is_object())
586 out["appliedProfileSequence"] = seq;
587
588 json data;
589 outData.toJson(data);
590 if (data.is_object())
591 out["colorData"] = data;
592
593 if (out.is_object())
594 saveJsonAs(out, cfgApply.m_dstFile.c_str());
595 }
596 else if (cfgApply.m_dstType==icCfgIt8) {
597 outData.toIt8(cfgApply.m_dstFile.c_str(), cfgApply.m_dstDigits, cfgApply.m_dstPrecision);
598 }
599 else {
600 printf("Unsupported output format\n");
601 delete pMruCmm;
602
603 return -1;
604 }
605
606 if (pMruCmm)
607 delete pMruCmm;
608
609 return 0;
610}
icStatusCMM
CMM return status values.
Definition IccCmm.h:90
std::shared_ptr< CIccCfgDataEntry > CIccCfgDataEntryPtr
@ 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 icSigDevXYZData
Definition IccDefs.h:92
#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 loadJsonFrom(json &j, const char *szFname)
bool saveJsonAs(const json &j, const char *szFname, int indent)
#define stricmp
CIccProfile * OpenIccProfile(const icChar *szFilename, bool bUseSubProfile)
Name: OpenIccProfile.
const icChar * szName
icUInt32Number icGetSpaceSamples(icColorSpaceSignature sig)
Definition IccUtil.cpp:1303
icUInt32Number icIntMax(icUInt32Number v1, icUInt32Number v2)
Definition IccUtil.cpp:913
Type: Class.
Definition IccApplyBPC.h:89
bool fromLegacy(const char *filename, bool bReset=false)
icFloatColorEncoding m_srcEncoding
bool toIt8(const char *filename, icUInt8Number nDigits, icUInt8Number nPrecision)
icColorSpaceSignature m_srcSpace
bool fromJson(json obj, bool bReset=false)
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
icCfgDataType m_dstType
int fromArgs(const char **args, int nArg, bool bReset=false)
icUInt8Number m_dstDigits
std::string m_dstFile
icFloatColorEncoding m_dstEncoding
std::string m_srcFile
void reset()
std::vector< icFloatNumber > m_srcValues
std::vector< icFloatNumber > m_values
std::string m_name
icCmmEnvSigMap m_pccEnvVars
std::string m_iccFile
std::string m_pccFile
icCmmEnvSigMap m_iccEnvVars
bool m_adjustPcsLuminance
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
static void SetDebugger(IIccCalcDebugger *pDebugger)
#define icSigLabPcsData
Allowable icColorSpaceSignature values for xform PCS purposes.
#define icUnknownIntent
Convenience Enum Definitions - Not defined in ICC specification.
@ icSigAbstractClass
#define icSigXYZPcsData
icColorSpaceSignature
Color Space Signatures.
@ icSigNamedData
#define icSigUnknownData
icRenderingIntent
Rendering Intents, used in the profile header.
std::list< CIccProfile * > IccProfilePtrList
void Usage()
std::shared_ptr< CIccLogDebugger > LogDebuggerPtr
#define IsSpacePCS(x)

References CIccCfgDataApply::fromArgs(), CIccCfgProfileSequence::fromArgs(), CIccCfgColorData::fromJson(), CIccCfgDataApply::fromJson(), CIccCfgProfileSequence::fromJson(), CIccCfgColorData::fromLegacy(), icCfgColorData, icCfgIt8, icCfgLegacy, icGetSpaceSamples(), icIntMax(), icSigAbstractClass, icSigDevLabData, icSigDevXYZData, icSigLabPcsData, icSigNamedData, icSigUnknownData, icSigXYZPcsData, icUnknownIntent, IsSpacePCS, loadJsonFrom(), CIccCfgProfile::m_adjustPcsLuminance, CIccCfgColorData::m_data, CIccCfgDataApply::m_debugCalc, CIccCfgDataApply::m_dstDigits, CIccCfgDataApply::m_dstEncoding, CIccCfgDataApply::m_dstFile, CIccCfgDataApply::m_dstPrecision, CIccCfgDataApply::m_dstType, CIccCfgColorData::m_encoding, CIccCfgProfile::m_iccEnvVars, CIccCfgProfile::m_iccFile, CIccCfgProfile::m_intent, CIccCfgProfile::m_interpolation, CIccCfgDataEntry::m_name, CIccCfgProfile::m_pccEnvVars, CIccCfgProfile::m_pccFile, CIccCfgProfileSequence::m_profiles, CIccCfgColorData::m_space, CIccCfgColorData::m_srcEncoding, CIccCfgDataApply::m_srcFile, CIccCfgColorData::m_srcSpace, CIccCfgDataApply::m_srcType, CIccCfgDataEntry::m_srcValues, CIccCfgProfile::m_transform, CIccCfgProfile::m_useBPC, CIccCfgProfile::m_useD2BxB2Dx, CIccCfgProfile::m_useV5SubProfile, CIccCfgDataEntry::m_values, OpenIccProfile(), CIccCfgDataEntry::reset(), saveJsonAs(), IIccCalcDebugger::SetDebugger(), stricmp, szName, CIccCfgColorData::toIt8(), CIccCfgColorData::toJson(), CIccCfgProfileSequence::toJson(), CIccCfgColorData::toLegacy(), and Usage().

+ Here is the call graph for this function:

◆ Usage()

void Usage ( )

Definition at line 185 of file iccApplyNamedCmm.cpp.

186{
187 printf("iccApplyNamedCmm built with IccProfLib version " ICCPROFLIBVER "\n\n");
188
189 printf("Usage 1: iccApplyNamedCmm -cfg config_file_path\n");
190 printf(" Where config_file_path is a json formatted ICC profile aplication configuration file\n\n");
191 printf("Usage 2: iccApplyNamedCmm {-debugcalc} data_file_path final_data_encoding{:FmtPrecision{:FmtDigits}} interpolation {{-ENV:Name value} profile_file_path Rendering_intent {-PCC connection_conditions_path}}\n\n");
192 printf("Built with IccProfLib version " ICCPROFLIBVER "\n");
193
194 printf(" For final_data_encoding:\n");
195 printf(" 0 - icEncodeValue (converts to/from lab encoding when samples=3)\n");
196 printf(" 1 - icEncodePercent\n");
197 printf(" 2 - icEncodeUnitFloat (may clip to 0.0 to 1.0)\n");
198 printf(" 3 - icEncodeFloat\n");
199 printf(" 4 - icEncode8Bit\n");
200 printf(" 5 - icEncode16Bit\n");
201 printf(" 6 - icEncode16BitV2\n\n");
202
203 printf(" FmtPrecision - formatting for # of digits after decimal (default=4)\n");
204 printf(" FmtDigits - formatting for total # of digits (default=5+FmtPrecision)\n\n");
205
206 printf(" For interpolation:\n");
207 printf(" 0 - Linear\n");
208 printf(" 1 - Tetrahedral\n\n");
209
210 printf(" For Rendering_intent:\n");
211 printf(" 0 - Perceptual\n");
212 printf(" 1 - Relative\n");
213 printf(" 2 - Saturation\n");
214 printf(" 3 - Absolute\n");
215 printf(" 10 + Intent - without D2Bx/B2Dx\n");
216 printf(" 20 + Intent - Preview\n");
217 printf(" 30 - Gamut\n");
218 printf(" 33 - Gamut Absolute\n");
219 printf(" 40 + Intent - with BPC\n");
220 printf(" 50 - BDRF Model\n");
221 printf(" 60 - BDRF Light\n");
222 printf(" 70 - BDRF Output\n");
223 printf(" 80 - MCS connection\n");
224 printf(" 90 + Intent - Colorimetric Only\n");
225 printf(" 100 + Intent - Spectral Only\n");
226 printf(" +1000 - Use Luminance based PCS adjustment\n");
227 printf(" +10000 - Use V5 sub-profile if present\n");
228 printf("+100000 - Use HToS tag if present\n");
229}
#define ICCPROFLIBVER

References ICCPROFLIBVER.

Referenced by main().

+ Here is the caller graph for this function: