IccMAX 2.1.27
Color Profile Tools
Loading...
Searching...
No Matches
IccCmm.cpp File Reference
#include "IccXformFactory.h"
#include "IccTag.h"
#include "IccMpeBasic.h"
#include "IccArrayBasic.h"
#include "IccStructBasic.h"
#include "IccIO.h"
#include "IccApplyBPC.h"
#include "IccSparseMatrix.h"
#include "IccEncoding.h"
#include "IccMatrixMath.h"
#include "IccCmm.h"
#include "IccDefs.h"
+ Include dependency graph for IccCmm.cpp:

Go to the source code of this file.

Macros

#define ICCDUMPPIXEL(n, pix)
 
#define ICCPCSSTEPDUMPFMT   ICCMTXSTEPDUMPFMT
 
#define IsCompatSpace(x, y)   ((x)==(y) || (IsSpacePCS(x) && IsSpacePCS(y)) || (IsSpaceMCS(x) && IsSpaceMCS(y))/* || (IsSpaceCMYK(x) && IsSpaceCMYK(y))*/)
 
#define IsCompatSpacePCS(x, y)
 
#define IsNChannelCompat(x, y)   ((IsSpaceNChannel(x) && icNumColorSpaceChannels(x)==icGetSpaceSamples(y)) || (IsSpaceNChannel(y) && icNumColorSpaceChannels(y)==icGetSpaceSamples(x)))
 
#define IsSpaceCMYK(x)   ((x)==icSigCmykData || (x)==icSig4colorData)
 
#define IsSpaceColorimetricPCS(x)   ((x)==icSigXYZPcsData || (x)==icSigLabPcsData)
 
#define IsSpaceDevicePCS(x)   ((x)==icSigDevXYZData || (x)==icSigDevLabData)
 
#define IsSpaceMCS(x)   (icGetColorSpaceType(x)==icSigSrcMCSChannelData)
 
#define IsSpaceNChannel(x)   (icGetColorSpaceType(x)==icSigNChannelData)
 
#define IsSpacePCS(x)   (IsSpaceColorimetricPCS(x) || IsSpaceSpectralPCS(x))
 

Functions

static __inline bool IsSpaceSpectralPCS (icUInt32Number sig)
 
static icFloatNumber RGBClip (icFloatNumber v, CIccCurve *pCurve)
 
static icFloatNumber XYZDescale (icFloatNumber v)
 
static icFloatNumber XYZScale (icFloatNumber v)
 

Variables

icFloatNumber icD50XYZ [3]
 

Detailed Description

File: IccCmm.cpp

Contains: Implementation of the CIccCmm class.

Version: V1

Copyright: � see ICC Software License

Definition in file IccCmm.cpp.

Macro Definition Documentation

◆ ICCDUMPPIXEL

#define ICCDUMPPIXEL (   n,
  pix 
)

◆ ICCPCSSTEPDUMPFMT

#define ICCPCSSTEPDUMPFMT   ICCMTXSTEPDUMPFMT

◆ IsCompatSpace

#define IsCompatSpace (   x,
 
)    ((x)==(y) || (IsSpacePCS(x) && IsSpacePCS(y)) || (IsSpaceMCS(x) && IsSpaceMCS(y))/* || (IsSpaceCMYK(x) && IsSpaceCMYK(y))*/)

◆ IsCompatSpacePCS

#define IsCompatSpacePCS (   x,
 
)
Value:
(((x)==icSigDevXYZData && (y)==icSigXYZData) || ((x)==icSigXYZData && (y)==icSigDevXYZData) || \
((x)==icSigDevLabData && (y)==icSigLabData) || ((x)==icSigLabData && (y)==icSigDevLabData))
@ icSigLabData
Definition icProfileHeader.h:847
@ icSigXYZData
Definition icProfileHeader.h:846
#define icSigDevXYZData
Definition IccDefs.h:92
#define icSigDevLabData
Definition IccDefs.h:91
142{
143 if (v<0)
144 v = 0;
145 if (v>1.0)
146 v = 1.0;
147
148 return v;
149}
150
159icFloatNumber CIccPCSUtil::NegClip(icFloatNumber v)
160{
161 if (v<0)
162 v=0;
163
164 return v;
165}
166
175void CIccPCSUtil::LabToXyz(icFloatNumber *Dst, const icFloatNumber *Src, bool bNoClip)
176{
177 icFloatNumber Lab[3];
178
179 memcpy(&Lab,Src,sizeof(Lab));
180
181 icLabFromPcs(Lab);
182
183 icLabtoXYZ(Lab);
184
185 icXyzToPcs(Lab);
186
187 if (!bNoClip) {
188 Dst[0] = UnitClip(Lab[0]);
189 Dst[1] = UnitClip(Lab[1]);
190 Dst[2] = UnitClip(Lab[2]);
191 }
192 else {
193 Dst[0] = Lab[0];
194 Dst[1] = Lab[1];
195 Dst[2] = Lab[2];
196 }
197}
198
199
208void CIccPCSUtil::XyzToLab(icFloatNumber *Dst, const icFloatNumber *Src, bool bNoClip)
209{
210 icFloatNumber XYZ[3];
211
212
213 if (!bNoClip) {
214 XYZ[0] = UnitClip(Src[0]);
215 XYZ[1] = UnitClip(Src[1]);
216 XYZ[2] = UnitClip(Src[2]);
217 }
218 else {
219 XYZ[0] = Src[0];
220 XYZ[1] = Src[1];
221 XYZ[2] = Src[2];
222 }
223
224 icXyzFromPcs(XYZ);
225
226 icXYZtoLab(XYZ);
227
228 icLabToPcs(XYZ);
229
230 if (!bNoClip) {
231 Dst[0] = UnitClip(XYZ[0]);
232 Dst[1] = UnitClip(XYZ[1]);
233 Dst[2] = UnitClip(XYZ[2]);
234 }
235 else {
236 Dst[0] = XYZ[0];
237 Dst[1] = XYZ[1];
238 Dst[2] = XYZ[2];
239 }
240}
241
242
251void CIccPCSUtil::Lab2ToXyz(icFloatNumber *Dst, const icFloatNumber *Src, bool bNoClip)
252{
253 Lab2ToLab4(Dst, Src, bNoClip);
254 LabToXyz(Dst, Dst, bNoClip);
255}
256
257
266void CIccPCSUtil::XyzToLab2(icFloatNumber *Dst, const icFloatNumber *Src, bool bNoClip)
267{
268 XyzToLab(Dst, Src, bNoClip);
269 Lab4ToLab2(Dst, Dst);
270}
271
272
281void CIccPCSUtil::Lab2ToLab4(icFloatNumber *Dst, const icFloatNumber *Src, bool bNoClip)
282{
283 if (bNoClip) {
284 Dst[0] = (icFloatNumber)(Src[0] * 65535.0f / 65280.0f);
285 Dst[1] = (icFloatNumber)(Src[1] * 65535.0f / 65280.0f);
286 Dst[2] = (icFloatNumber)(Src[2] * 65535.0f / 65280.0f);
287 }
288 else {
289 Dst[0] = UnitClip((icFloatNumber)(Src[0] * 65535.0f / 65280.0f));
290 Dst[1] = UnitClip((icFloatNumber)(Src[1] * 65535.0f / 65280.0f));
291 Dst[2] = UnitClip((icFloatNumber)(Src[2] * 65535.0f / 65280.0f));
292 }
293}
294
303void CIccPCSUtil::Lab4ToLab2(icFloatNumber *Dst, const icFloatNumber *Src)
304{
305 Dst[0] = (icFloatNumber)(Src[0] * 65280.0f / 65535.0f);
306 Dst[1] = (icFloatNumber)(Src[1] * 65280.0f / 65535.0f);
307 Dst[2] = (icFloatNumber)(Src[2] * 65280.0f / 65535.0f);
308}
309
310
319CIccCreateXformHintManager::~CIccCreateXformHintManager()
320{
321 if (m_pList) {
322 IIccCreateXformHintList::iterator i;
323
324 for (i=m_pList->begin(); i!=m_pList->end(); i++) {
325 if (i->ptr)
326 delete i->ptr;
327 }
328
329 delete m_pList;
330 }
331}
332
348bool CIccCreateXformHintManager::AddHint(IIccCreateXformHint* pHint)
349{
350 if (!m_pList) {
351 m_pList = new IIccCreateXformHintList;
352 }
353
354 if (pHint) {
355 if (GetHint(pHint->GetHintType())) {
356 delete pHint;
357 return false;
358 }
359 IIccCreateXformHintPtr Hint;
360 Hint.ptr = pHint;
361 m_pList->push_back(Hint);
362 return true;
363 }
364
365 return false;
366}
367
384bool CIccCreateXformHintManager::DeleteHint(IIccCreateXformHint* pHint)
385{
386 if (m_pList && pHint) {
387 IIccCreateXformHintList::iterator i;
388 for (i=m_pList->begin(); i!=m_pList->end(); i++) {
389 if (i->ptr) {
390 if (i->ptr == pHint) {
391 delete pHint;
392 pHint = NULL;
393 m_pList->erase(i);
394 return true;
395 }
396 }
397 }
398 }
399
400 return false;
401}
402
417IIccCreateXformHint* CIccCreateXformHintManager::GetHint(const char* hintName)
418{
419 IIccCreateXformHint* pHint=NULL;
420
421 if (m_pList) {
422 IIccCreateXformHintList::iterator i;
423 for (i=m_pList->begin(); i!=m_pList->end(); i++) {
424 if (i->ptr) {
425 if (!strcmp(i->ptr->GetHintType(), hintName)) {
426 pHint = i->ptr;
427 break;
428 }
429 }
430 }
431 }
432
433 return pHint;
434}
435
444CIccXform::CIccXform()
445{
446 m_pProfile = NULL;
447 m_bOwnsProfile = true;
448 m_bInput = true;
449 m_nIntent = icUnknownIntent;
450 m_pAdjustPCS = NULL;
451 m_bAdjustPCS = false;
452 m_bAbsToRel = false;
453 m_nMCS = icNoMCS;
454 m_bUseSpectralPCS = false;
455 m_bSrcPcsConversion = true;
456 m_bDstPcsConversion = true;
457 m_pConnectionConditions = NULL;
458 m_bDeleteEnvLooup = true;
459 m_pCmmEnvVarLookup = NULL;
460 m_nTagIntent = icPerceptual;
461 m_MediaXYZ = {};
462 m_nInterp = icInterpLinear;
463 m_bUseD2BTags = false;
464 m_bLuminanceMatching = false;
465 m_PCSOffset[0] = m_PCSOffset[1] = m_PCSOffset[2] = 0;
466}
467
468
477CIccXform::~CIccXform()
478{
479 if (m_pProfile && m_bOwnsProfile)
480 delete m_pProfile;
481
482 if (m_pAdjustPCS) {
483 delete m_pAdjustPCS;
484 }
485
486 if (m_pCmmEnvVarLookup && m_bDeleteEnvLooup) {
487 delete m_pCmmEnvVarLookup;
488 }
489
490}
491
492
493void CIccXform::DetachAll()
494{
495 m_pProfile = NULL;
496 m_bOwnsProfile = true;
497 m_pConnectionConditions = NULL;
498}
499
523CIccXform *CIccXform::Create(CIccProfile *pProfile,
524 bool bInput/* =true */,
525 icRenderingIntent nIntent/* =icUnknownIntent */,
526 icXformInterp nInterp/* =icInterpLinear */,
527 IIccProfileConnectionConditions *pPcc/*=NULL*/,
528 icXformLutType nLutType/* =icXformLutColor */,
529 bool bUseD2BTags/* =true */, CIccCreateXformHintManager *pHintManager/* =NULL */)
530{
531 CIccXform *rv = NULL;
532 icRenderingIntent nTagIntent = nIntent;
533 bool bUseSpectralPCS = false;
534 bool bAbsToRel = false;
535 bool bRelToAbs = false;
537 icXformLutType nUseLutType = nLutType;
538 bool bUseColorimeticTags = true;
539
540 if (nLutType == icXformLutSpectral) {
541 nUseLutType = icXformLutColor;
542 bUseD2BTags = true;
543 bUseColorimeticTags = false;
544 }
545 else if (nLutType == icXformLutColorimetric) {
546 nUseLutType = icXformLutColor;
547 }
548
549 if (pProfile->m_Header.deviceClass==icSigColorEncodingClass) {
550 CIccProfile *pEncProfile;
551 if (icConvertEncodingProfile(pEncProfile, pProfile)!=icEncConvertOk)
552 return NULL;
553 delete pProfile;
554 pProfile = pEncProfile;
555 }
556 if (pProfile->m_Header.deviceClass==icSigLinkClass/* && nIntent==icAbsoluteColorimetric*/) {
557 nIntent = icPerceptual;
558 }
559
560 if (nTagIntent == icUnknownIntent)
561 nTagIntent = icPerceptual;
562
563 switch (nUseLutType) {
564 case icXformLutColor:
565 if (bInput) {
566 CIccTag *pTag = NULL;
567 if (bUseD2BTags) {
568 if (pProfile->m_Header.spectralPCS && nLutType!=icXformLutColorimetric) {
569 pTag = pProfile->FindTag(icSigDToB0Tag + nTagIntent);
570
571 if (!pTag && nTagIntent == icAbsoluteColorimetric) {
572 pTag = pProfile->FindTag(icSigDToB1Tag);
573 if (pTag)
574 nTagIntent = icRelativeColorimetric;
575 }
576 else if (!pTag && nTagIntent == icRelativeColorimetric) {
577 pTag = pProfile->FindTag(icSigDToB3Tag);
578 if (pTag) {
579 nTagIntent = icAbsoluteColorimetric;
580 bAbsToRel = true;
581 }
582 }
583
584 if (pTag)
585 bUseSpectralPCS = true;
586
587 if (!pTag) {
588 pTag = pProfile->FindTag(icSigDToB0Tag);
589 }
590 if (!pTag) {
591 pTag = pProfile->FindTag(icSigDToB1Tag);
592 }
593 if (!pTag) {
594 pTag = pProfile->FindTag(icSigDToB3Tag);
595 if (pTag) {
596 nTagIntent = icAbsoluteColorimetric;
597 bAbsToRel = true;
598 }
599 }
600 }
601 else if (pProfile->m_Header.version < icVersionNumberV5) {
602 pTag = pProfile->FindTag(icSigDToB0Tag + nTagIntent);
603
604 if (!pTag && nTagIntent ==icAbsoluteColorimetric) {
605 pTag = pProfile->FindTag(icSigDToB1Tag);
606 if (pTag)
607 nTagIntent = icRelativeColorimetric;
608 }
609
610 //Apparently Using DtoB0 is not prescribed here by the v4 ICC Specification
611 if (!pTag && pProfile->m_Header.version >= icVersionNumberV5) {
612 pTag = pProfile->FindTag(icSigDToB0Tag);
613 }
614 }
615 }
616
617 if (bUseColorimeticTags) {
618 if (!pTag) {
619 pTag = pProfile->FindTag(icSigAToB0Tag + nTagIntent);
620 }
621
622 if (!pTag && nTagIntent == icAbsoluteColorimetric) {
623 pTag = pProfile->FindTag(icSigAToB1Tag);
624 if (pTag)
625 nTagIntent = icRelativeColorimetric;
626 }
627 else if (!pTag && nTagIntent == icRelativeColorimetric) {
628 pTag = pProfile->FindTag(icSigAToB3Tag);
629 if (pTag) {
630 nTagIntent = icAbsoluteColorimetric;
631 bAbsToRel = true;
632 }
633 }
634
635 if (!pTag) {
636 pTag = pProfile->FindTag(icSigAToB0Tag);
637 }
638 if (!pTag) {
639 pTag = pProfile->FindTag(icSigAToB1Tag);
640 }
641 if (!pTag) {
642 pTag = pProfile->FindTag(icSigAToB3Tag);
643 if (pTag) {
644 nTagIntent = icAbsoluteColorimetric;
645 bAbsToRel = true;
646 }
647 }
648 }
649
650 //Unsupported elements cause fall back behavior
651 if (pTag && !pTag->IsSupported())
652 pTag = NULL;
653
654 if (!pTag) {
655 if (pProfile->m_Header.version < icVersionNumberV5) {
656 //Matrix/TRC profiles are deprecated in v5 profiles
657 if (pProfile->m_Header.colorSpace == icSigRgbData) {
658 rv = CIccXformCreator::CreateXform(icXformTypeMatrixTRC, NULL, pHintManager);
659 }
660 else if (pProfile->m_Header.colorSpace == icSigGrayData) {
662 }
663 else
664 return NULL;
665 }
666 else
667 return NULL;
668 }
669 else if (pTag->GetType()==icSigMultiProcessElementType) {
670 rv = CIccXformCreator::CreateXform(icXformTypeMpe, pTag, pHintManager);
671 }
672 else {
673 switch(pProfile->m_Header.colorSpace) {
674 case icSigXYZData:
675 case icSigLabData:
676 case icSigLuvData:
677 case icSigYCbCrData:
678 case icSigYxyData:
679 case icSigRgbData:
680 case icSigHsvData:
681 case icSigHlsData:
682 case icSigCmyData:
683 case icSig3colorData:
684 rv = CIccXformCreator::CreateXform(icXformType3DLut, pTag, pHintManager);
685 break;
686
687 case icSigCmykData:
688 case icSig4colorData:
689 rv = CIccXformCreator::CreateXform(icXformType4DLut, pTag, pHintManager);
690 break;
691
692 default:
693 rv = CIccXformCreator::CreateXform(icXformTypeNDLut, pTag, pHintManager);
694 break;
695 }
696 }
697 }
698 else {
699 CIccTag *pTag = NULL;
700
701 if (nLutType == icXformLutColorimetric && pProfile->m_Header.version >= icVersionNumberV5) {
702 bUseD2BTags = false;
703 }
704
705 if (bUseD2BTags) {
706 pTag = pProfile->FindTag(icSigBToD0Tag + nTagIntent);
707
708 //Additional precedence not prescribed by the v4 ICC Specification
709 if (!pTag && pProfile->m_Header.version >= icVersionNumberV5) {
710 pTag = pProfile->FindTag(icSigBToD0Tag);
711
712 if (!pTag) {
713 pTag = pProfile->FindTag(icSigBToD1Tag);
714 if (pTag) {
715 nTagIntent = icRelativeColorimetric;
716 if (nTagIntent==icAbsoluteColorimetric)
717 bRelToAbs = true;
718 }
719 }
720
721 if (!pTag) {
722 pTag = pProfile->FindTag(icSigBToD3Tag);
723 if (pTag) {
724 nTagIntent = icAbsoluteColorimetric;
725 bAbsToRel = true;
726 }
727 }
728 }
729
730 //Unsupported elements cause fall back behavior
731 if (pTag && !pTag->IsSupported())
732 pTag = NULL;
733
734 if (pTag)
735 bUseSpectralPCS = true;
736
737 if (!pTag && nTagIntent == icAbsoluteColorimetric && pProfile->m_Header.version < icVersionNumberV5) {
738 pTag = pProfile->FindTag(icSigBToD1Tag);
739
740 //Unsupported elements cause fall back behavior
741 if (pTag && !pTag->IsSupported())
742 pTag = NULL;
743
744 if (pTag)
745 nTagIntent = icRelativeColorimetric;
746 }
747 }
748
749 if (bUseColorimeticTags) {
750
751 if (!pTag) {
752 pTag = pProfile->FindTag(icSigBToA0Tag + nTagIntent);
753 }
754
755 if (!pTag && nTagIntent == icAbsoluteColorimetric) {
756 pTag = pProfile->FindTag(icSigBToA1Tag);
757 if (pTag)
758 nTagIntent = icRelativeColorimetric;
759 }
760
761 if (!pTag) {
762 pTag = pProfile->FindTag(icSigBToA0Tag);
763 }
764
765 //Additional precedence not prescribed by the v4 ICC Specification
766 if (!pTag && pProfile->m_Header.version >= icVersionNumberV5) {
767
768 pTag = pProfile->FindTag(icSigBToA1Tag);
769 if (pTag) {
770 nTagIntent = icRelativeColorimetric;
771 if (nTagIntent == icAbsoluteColorimetric)
772 bRelToAbs = true;
773 }
774
775 if (!pTag) {
776 pTag = pProfile->FindTag(icSigBToA3Tag);
777 if (pTag) {
778 nTagIntent = icAbsoluteColorimetric;
779 bAbsToRel = true;
780 }
781 }
782 }
783 }
784
785 if (!pTag) {
786 if (pProfile->m_Header.version < icVersionNumberV5) {
787 if (pProfile->m_Header.colorSpace == icSigRgbData) {
788 rv = CIccXformCreator::CreateXform(icXformTypeMatrixTRC, pTag, pHintManager);
789 }
790 else if (pProfile->m_Header.colorSpace == icSigGrayData) {
792 }
793 else
794 return NULL;
795 }
796 else
797 return NULL;
798 }
799 else if (pTag->GetType()==icSigMultiProcessElementType) {
800 rv = CIccXformCreator::CreateXform(icXformTypeMpe, pTag, pHintManager);
801 }
802 else {
803 switch(pProfile->m_Header.pcs) {
804 case icSigXYZData:
805 case icSigLabData:
806 rv = CIccXformCreator::CreateXform(icXformType3DLut, pTag, pHintManager);
807 break;
808
809 default:
810 break;
811 }
812 }
813 }
814 break;
815
817{
818 CIccTag* pTag = pProfile->FindTag(icSigNamedColor2Tag);
819 if (!pTag)
820 return NULL;
821
822 // Allocate and initialize the hint
823 CIccCreateNamedColorXformHint* pNamedColorHint = new CIccCreateNamedColorXformHint();
824 pNamedColorHint->csPcs = pProfile->m_Header.pcs;
825 pNamedColorHint->csDevice = pProfile->m_Header.colorSpace;
826 pNamedColorHint->csSpectralPcs = pProfile->m_Header.spectralPCS;
827 pNamedColorHint->spectralRange = pProfile->m_Header.spectralRange;
828 pNamedColorHint->biSpectralRange = pProfile->m_Header.biSpectralRange;
829
830 if (pHintManager) {
831 // 🚫 Do not delete manually — ownership is transferred
832 pHintManager->AddHint(pNamedColorHint);
834 // Do NOT call DeleteHint() or delete pNamedColorHint — it's already freed
835 pNamedColorHint = nullptr; // optional, but avoids accidental access
836 }
837 else {
838 CIccCreateXformHintManager HintManager;
839 HintManager.AddHint(pNamedColorHint);
841 // Same here — do NOT delete manually
842 pNamedColorHint = nullptr;
843 }
844
845 // 🚫 Do not manually delete — already freed via AddHint/CreateXform logic
846 // delete pNamedColorHint; ← removed to prevent UAF
847 // pNamedColorHint = nullptr; ← already nullified above
848
849 if (pProfile->m_Header.spectralPCS)
850 bUseSpectralPCS = true;
851}
852break;
853
855 {
856 bInput = false;
857 CIccTag *pTag = pProfile->FindTag(icSigPreview0Tag + nTagIntent);
858 if (!pTag) {
859 pTag = pProfile->FindTag(icSigPreview0Tag);
860 }
861 if (!pTag) {
862 return NULL;
863 }
864 else {
865 switch(pProfile->m_Header.pcs) {
866 case icSigXYZData:
867 case icSigLabData:
868 rv = CIccXformCreator::CreateXform(icXformType3DLut, pTag, pHintManager);
869
870 default:
871 break;
872 }
873 }
874 }
875 break;
876
877 case icXformLutGamut:
878 {
879 bInput = false;
880 CIccTag *pTag = pProfile->FindTag(icSigGamutTag);
881 if (!pTag) {
882 return NULL;
883 }
884 else {
885 switch(pProfile->m_Header.pcs) {
886 case icSigXYZData:
887 case icSigLabData:
888 rv = CIccXformCreator::CreateXform(icXformType3DLut, pTag, pHintManager);
889
890 default:
891 break;
892 }
893 }
894 }
895 break;
896
898 {
899 // get the correct tag first
900
901 CIccTag *pTag = NULL;
902 if (bUseD2BTags) {
903 if (pProfile->m_Header.spectralPCS) {
904
905 pTag = pProfile->FindTag(icSigBrdfSpectralParameter0Tag + nTagIntent);
906
907 if (pTag)
908 bUseSpectralPCS = true;
909 }
910 }
911 else
912 {
913 pTag = pProfile->FindTag(icSigBrdfColorimetricParameter0Tag + nTagIntent);
914
915 //Unsupported elements cause fall back behavior
916 if (pTag && !pTag->IsSupported())
917 pTag = NULL;
918 }
919
920 // now extract the correct part from the structure
921 CIccStructBRDF* pStructTag = dynamic_cast<CIccStructBRDF*>(pTag);
922
923 if (pStructTag != NULL)
924 {
925 CIccTag *pTag2 = NULL;
926
927 switch (nLutType) {
929 pTag2 = pStructTag->GetElem(icSigBrdfTransformMbr);
930 break;
931 default:
932 // can't get here, get rid of warning
933 break;
934 }
935 if (pTag2)
936 rv = CIccXformCreator::CreateXform(icXformTypeMpe, pTag2, pHintManager);
937 }
938 }
939 break;
940
942 {
943 // get the correct tag first
944
945 CIccTag *pTag = NULL;
946 if (bUseD2BTags) {
947 if (pProfile->m_Header.spectralPCS) {
948
949 pTag = pProfile->FindTag(icSigBRDFDToB0Tag + nTagIntent);
950
951 if (pTag)
952 bUseSpectralPCS = true;
953 }
954 }
955 else
956 {
957 pTag = pProfile->FindTag(icSigBRDFAToB0Tag + nTagIntent);
958
959 //Unsupported elements cause fall back behavior
960 if (pTag && !pTag->IsSupported())
961 pTag = NULL;
962 }
963
964 if (pTag != NULL)
965 {
966 rv = CIccXformCreator::CreateXform(icXformTypeMpe, pTag, pHintManager);
967 }
968 }
969 break;
970
972 {
973 CIccTag *pTag = NULL;
974 if (pProfile->m_Header.deviceClass == icSigMaterialVisualizationClass) {
975 bInput = true;
976 nMCS = icFromMCS;
977
978 if (pProfile->m_Header.spectralPCS) {
979 pTag = pProfile->FindTag(icSigBRDFMToS0Tag + nTagIntent);
980
981 if (!pTag && nTagIntent == icAbsoluteColorimetric) {
982 pTag = pProfile->FindTag(icSigBRDFMToS1Tag);
983 if (pTag)
984 nTagIntent = icRelativeColorimetric;
985 }
986 else if (!pTag && nTagIntent != icAbsoluteColorimetric) {
987 pTag = pProfile->FindTag(icSigBRDFMToS3Tag);
988 if (pTag) {
989 nTagIntent = icAbsoluteColorimetric;
990 bAbsToRel = true;
991 }
992 }
993
994 if (!pTag) {
995 pTag = pProfile->FindTag(icSigBRDFMToS0Tag);
996 }
997 if (!pTag) {
998 pTag = pProfile->FindTag(icSigBRDFMToS1Tag);
999 }
1000 if (!pTag) {
1001 pTag = pProfile->FindTag(icSigBRDFMToS3Tag);
1002 if (pTag) {
1003 nTagIntent = icAbsoluteColorimetric;
1004 bAbsToRel = true;
1005 }
1006 }
1007
1008 if (pTag)
1009 bUseSpectralPCS = true;
1010 }
1011 if (!pTag && pProfile->m_Header.pcs != 0) {
1012 pTag = pProfile->FindTag(icSigBRDFMToB0Tag + nTagIntent);
1013
1014 if (!pTag && nTagIntent == icAbsoluteColorimetric) {
1015 pTag = pProfile->FindTag(icSigBRDFMToB1Tag);
1016 if (pTag)
1017 nTagIntent = icRelativeColorimetric;
1018 }
1019 else if (!pTag && nTagIntent != icAbsoluteColorimetric) {
1020 pTag = pProfile->FindTag(icSigBRDFMToB3Tag);
1021 if (pTag) {
1022 nTagIntent = icAbsoluteColorimetric;
1023 bAbsToRel = true;
1024 }
1025 }
1026 if (!pTag) {
1027 pTag = pProfile->FindTag(icSigBRDFMToB0Tag);
1028 }
1029 if (!pTag) {
1030 pTag = pProfile->FindTag(icSigBRDFMToB1Tag);
1031 }
1032 if (!pTag) {
1033 pTag = pProfile->FindTag(icSigBRDFMToB3Tag);
1034 if (pTag) {
1035 nTagIntent = icAbsoluteColorimetric;
1036 bAbsToRel = true;
1037 }
1038 }
1039 }
1040
1041 //Unsupported elements cause fall back behavior
1042 if (pTag && !pTag->IsSupported())
1043 pTag = NULL;
1044
1045 //Unsupported elements cause fall back behavior
1046 if (pTag && !pTag->IsSupported())
1047 pTag = NULL;
1048 }
1049 if (pTag && pProfile->m_Header.mcs) {
1050 rv = CIccXformCreator::CreateXform(icXformTypeMpe, pTag, pHintManager);
1051 }
1052 else
1053 rv = NULL;
1054 }
1055 break;
1056
1057 case icXformLutMCS:
1058 {
1059 CIccTag *pTag = NULL;
1060 if (pProfile->m_Header.deviceClass==icSigMaterialIdentificationClass ||
1061 pProfile->m_Header.deviceClass==icSigInputClass) {
1062 bInput = true;
1063 nMCS = icToMCS;
1064 pTag = pProfile->FindTag(icSigAToM0Tag);
1065 }
1066 else if (pProfile->m_Header.deviceClass==icSigMaterialVisualizationClass) {
1067 bInput = true;
1068 nMCS = icFromMCS;
1069
1070 if (pProfile->m_Header.spectralPCS) {
1071 pTag = pProfile->FindTag(icSigMToS0Tag + nTagIntent);
1072
1073 if (!pTag && nTagIntent == icAbsoluteColorimetric) {
1074 pTag = pProfile->FindTag(icSigMToS1Tag);
1075 if (pTag)
1076 nTagIntent = icRelativeColorimetric;
1077 }
1078 else if (!pTag && nTagIntent != icAbsoluteColorimetric) {
1079 pTag = pProfile->FindTag(icSigMToS3Tag);
1080 if (pTag) {
1081 nTagIntent = icAbsoluteColorimetric;
1082 bAbsToRel = true;
1083 }
1084 }
1085
1086 if (!pTag) {
1087 pTag = pProfile->FindTag(icSigMToS0Tag);
1088 }
1089 if (!pTag) {
1090 pTag = pProfile->FindTag(icSigMToS1Tag);
1091 }
1092 if (!pTag) {
1093 pTag = pProfile->FindTag(icSigMToS3Tag);
1094 if (pTag) {
1095 nTagIntent = icAbsoluteColorimetric;
1096 bAbsToRel = true;
1097 }
1098 }
1099
1100 if (pTag)
1101 bUseSpectralPCS = true;
1102 }
1103 if (!pTag && pProfile->m_Header.pcs!=0) {
1104 pTag = pProfile->FindTag(icSigMToB0Tag + nTagIntent);
1105
1106 if (!pTag && nTagIntent == icAbsoluteColorimetric) {
1107 pTag = pProfile->FindTag(icSigMToB1Tag);
1108 if (pTag)
1109 nTagIntent = icRelativeColorimetric;
1110 }
1111 else if (!pTag && nTagIntent != icAbsoluteColorimetric) {
1112 pTag = pProfile->FindTag(icSigMToB3Tag);
1113 if (pTag) {
1114 nTagIntent = icAbsoluteColorimetric;
1115 bAbsToRel = true;
1116 }
1117 }
1118
1119 if (!pTag) {
1120 pTag = pProfile->FindTag(icSigMToB0Tag);
1121 }
1122 if (!pTag) {
1123 pTag = pProfile->FindTag(icSigMToB1Tag);
1124 }
1125 if (!pTag) {
1126 pTag = pProfile->FindTag(icSigMToB3Tag);
1127 if (pTag) {
1128 nTagIntent = icAbsoluteColorimetric;
1129 bAbsToRel = true;
1130 }
1131 }
1132 }
1133
1134 //Unsupported elements cause fall back behavior
1135 if (pTag && !pTag->IsSupported())
1136 pTag = NULL;
1137 }
1138 else if (pProfile->m_Header.deviceClass==icSigMaterialLinkClass) {
1139 bInput = false;
1140 nMCS = icFromMCS;
1141 pTag = pProfile->FindTag(icSigMToA0Tag);
1142 }
1143 if (pTag && pProfile->m_Header.mcs) {
1144 rv = CIccXformCreator::CreateXform(icXformTypeMpe, pTag, pHintManager);
1145 }
1146 else
1147 rv = NULL;
1148 }
1149 break;
1150
1151 }
1152
1153 if (rv) {
1154 if (pPcc)
1155 rv->m_pConnectionConditions = pPcc;
1156 else
1157 rv->m_pConnectionConditions = pProfile;
1158
1159 rv->SetParams(pProfile, bInput, nIntent, nTagIntent, bUseSpectralPCS, nInterp, pHintManager, bAbsToRel, nMCS);
1160 }
1161
1162 return rv;
1163}
1164
1188CIccXform *CIccXform::Create(CIccProfile *pProfile,
1189 CIccTag *pTag,
1190 bool bInput/* =true */,
1191 icRenderingIntent nIntent/* =icUnknownIntent */,
1192 icXformInterp nInterp/* =icInterpLinear */,
1193 IIccProfileConnectionConditions *pPcc/*=NULL*/,
1194 bool bUseSpectralPCS/* =false*/,
1195 CIccCreateXformHintManager *pHintManager/* =NULL */)
1196{
1197 CIccXform *rv = NULL;
1198 icRenderingIntent nTagIntent = nIntent;
1199 bool bAbsToRel = false;
1200 bool bRelToAbs = false;
1202
1203 if (pProfile->m_Header.deviceClass == icSigColorEncodingClass) {
1204 return NULL;
1205 }
1206
1207 if (pProfile->m_Header.deviceClass == icSigLinkClass/* && nIntent==icAbsoluteColorimetric*/) {
1208 nIntent = icPerceptual;
1209 }
1210
1211 if (nTagIntent == icUnknownIntent)
1212 nTagIntent = icPerceptual;
1213
1214 //Unsupported elements cause fall back behavior
1215 if (pTag == NULL)
1216 return NULL;
1217 if (pTag && !pTag->IsSupported())
1218 return NULL;
1219
1220 if (bInput) {
1221 if (pTag->GetType() == icSigMultiProcessElementType) {
1222 rv = CIccXformCreator::CreateXform(icXformTypeMpe, pTag, pHintManager);
1223 }
1224 else {
1225 switch (pProfile->m_Header.colorSpace) {
1226 case icSigXYZData:
1227 case icSigLabData:
1228 case icSigLuvData:
1229 case icSigYCbCrData:
1230 case icSigYxyData:
1231 case icSigRgbData:
1232 case icSigHsvData:
1233 case icSigHlsData:
1234 case icSigCmyData:
1235 case icSig3colorData:
1236 rv = CIccXformCreator::CreateXform(icXformType3DLut, pTag, pHintManager);
1237 break;
1238
1239 case icSigCmykData:
1240 case icSig4colorData:
1241 rv = CIccXformCreator::CreateXform(icXformType4DLut, pTag, pHintManager);
1242 break;
1243
1244 default:
1245 rv = CIccXformCreator::CreateXform(icXformTypeNDLut, pTag, pHintManager);
1246 break;
1247 }
1248 }
1249 }
1250 else {
1251 if (pTag->GetType() == icSigMultiProcessElementType) {
1252 rv = CIccXformCreator::CreateXform(icXformTypeMpe, pTag, pHintManager);
1253 }
1254 else {
1255 switch (pProfile->m_Header.pcs) {
1256 case icSigXYZData:
1257 case icSigLabData:
1258 rv = CIccXformCreator::CreateXform(icXformType3DLut, pTag, pHintManager);
1259 break;
1260
1261 default:
1262 break;
1263 }
1264 }
1265 }
1266
1267 if (rv) {
1268 if (pPcc)
1269 rv->m_pConnectionConditions = pPcc;
1270 else
1271 rv->m_pConnectionConditions = pProfile;
1272
1273 rv->SetParams(pProfile, bInput, nIntent, nTagIntent, bUseSpectralPCS, nInterp, pHintManager, bAbsToRel, nMCS);
1274 }
1275
1276 return rv;
1277}
1278
1292void CIccXform::SetParams(CIccProfile *pProfile, bool bInput, icRenderingIntent nIntent, icRenderingIntent nTagIntent,
1293 bool bUseSpectralPCS, icXformInterp nInterp, CIccCreateXformHintManager *pHintManager/* =NULL */,
1294 bool bAbsToRel/*=false*/, icMCSConnectionType nMCS/*=icNoMCS*/)
1295{
1296 m_pProfile = pProfile;
1297 m_bInput = bInput;
1298 m_nIntent = nIntent;
1299 m_nTagIntent = nTagIntent;
1300 m_nInterp = nInterp;
1301 m_pAdjustPCS = NULL;
1302 m_bUseSpectralPCS = bUseSpectralPCS;
1303 m_bAbsToRel = bAbsToRel;
1304 m_nMCS = nMCS;
1305 m_bLuminanceMatching = false;
1306
1307 if (pHintManager) {
1308 IIccCreateXformHint *pHint=NULL;
1309
1310 pHint = pHintManager->GetHint("CIccCreateAdjustPCSXformHint");
1311 if (pHint) {
1312 CIccCreateAdjustPCSXformHint *pAdjustPCSHint = (CIccCreateAdjustPCSXformHint*)pHint;
1313 m_pAdjustPCS = pAdjustPCSHint->GetNewAdjustPCSXform();
1314 }
1315
1316 pHint = pHintManager->GetHint("CIccCreateCmmEnvVarXformHint");
1317 if (pHint) {
1318 CIccCreateCmmEnvVarXformHint *pCmmEnvVarHint = (CIccCreateCmmEnvVarXformHint*)pHint;
1319 m_pCmmEnvVarLookup = pCmmEnvVarHint->GetNewCmmEnvVarLookup();
1320 }
1321
1322 pHint = pHintManager->GetHint("CIccLuminanceMatchingHint");
1323 if (pHint) {
1324 m_bLuminanceMatching = true;
1325 }
1326 }
1327}
1328
1352CIccXform *CIccXform::Create(CIccProfile &Profile,
1353 bool bInput/* =true */,
1354 icRenderingIntent nIntent/* =icUnknownIntent */,
1355 icXformInterp nInterp/* =icInterpLinear */,
1356 IIccProfileConnectionConditions *pPcc/*=NULL*/,
1357 icXformLutType nLutType/* =icXformLutColor */,
1358 bool bUseD2BxB2DxTags/* =true */,
1359 CIccCreateXformHintManager *pHintManager/* =NULL */)
1360{
1361 CIccProfile *pProfile = new CIccProfile(Profile);
1362 CIccXform *pXform = Create(pProfile, bInput, nIntent, nInterp, pPcc, nLutType, bUseD2BxB2DxTags, pHintManager);
1363
1364 if (!pXform)
1365 delete pProfile;
1366
1367 return pXform;
1368}
1369
1370
1382icStatusCMM CIccXform::Begin()
1383{
1384 IIccProfileConnectionConditions *pCond = GetConnectionConditions();
1385
1386 icFloatNumber mediaXYZ[3];
1387 icFloatNumber illumXYZ[3];
1388
1389 if (m_nIntent==icAbsoluteColorimetric) {
1390 if (pCond) {
1391 pCond->getMediaWhiteXYZ(mediaXYZ);
1392
1393 m_MediaXYZ.X = icFtoF16(mediaXYZ[0]);
1394 m_MediaXYZ.Y = icFtoF16(mediaXYZ[1]);
1395 m_MediaXYZ.Z = icFtoF16(mediaXYZ[2]);
1396 }
1397 else {
1398 CIccTag *pTag = m_pProfile->FindTag(icSigMediaWhitePointTag);
1399
1400 if (!pTag || pTag->GetType()!=icSigXYZType)
1402
1403 CIccTagXYZ *pXyzTag = (CIccTagXYZ*)pTag;
1404
1405 m_MediaXYZ = (*pXyzTag)[0];
1406 mediaXYZ[0] = icFtoD(m_MediaXYZ.X);
1407 mediaXYZ[1] = icFtoD(m_MediaXYZ.Y);
1408 mediaXYZ[2] = icFtoD(m_MediaXYZ.Z);
1409 }
1410 }
1411
1412 icXYZNumber illXYZ;
1413 if (pCond) {
1414 pCond->getNormIlluminantXYZ(illumXYZ);
1415 illXYZ.X = icDtoF(illumXYZ[0]);
1416 illXYZ.Y = icDtoF(illumXYZ[1]);
1417 illXYZ.Z = icDtoF(illumXYZ[2]);
1418 }
1419 else {
1420 illXYZ = m_pProfile->m_Header.illuminant;
1421 illumXYZ[0] = icFtoD(illXYZ.X);
1422 illumXYZ[1] = icFtoD(illXYZ.Y);
1423 illumXYZ[2] = icFtoD(illXYZ.Z);
1424 }
1425
1426 // set up for any needed PCS adjustment
1427 if (m_nIntent == icAbsoluteColorimetric &&
1428 (m_MediaXYZ.X != illXYZ.X ||
1429 m_MediaXYZ.Y != illXYZ.Y ||
1430 m_MediaXYZ.Z != illXYZ.Z)) {
1431
1432 icColorSpaceSignature Space = m_pProfile->m_Header.pcs;
1433
1434 if (IsSpacePCS(Space)) {
1435 m_bAdjustPCS = true; // turn ON PCS adjustment
1436
1437 // scale factors depend upon media white point
1438 // set up for input transform
1439 if (!m_bInput) {
1440 m_PCSScale[0] = illumXYZ[0] / mediaXYZ[0];
1441 m_PCSScale[1] = illumXYZ[1] / mediaXYZ[1];
1442 m_PCSScale[2] = illumXYZ[2] / mediaXYZ[2];
1443 }
1444 else {
1445 m_PCSScale[0] = mediaXYZ[0] / illumXYZ[0];
1446 m_PCSScale[1] = mediaXYZ[1] / illumXYZ[1];
1447 m_PCSScale[2] = mediaXYZ[2] / illumXYZ[2];
1448
1449 }
1450
1451 m_PCSOffset[0] = 0.0;
1452 m_PCSOffset[1] = 0.0;
1453 m_PCSOffset[2] = 0.0;
1454 }
1455 }
1456 else if (m_nIntent == icPerceptual && (IsVersion2() || !HasPerceptualHandling())) {
1457 icColorSpaceSignature Space = m_pProfile->m_Header.pcs;
1458
1459 if (IsSpacePCS(Space) && m_pProfile->m_Header.deviceClass!=icSigAbstractClass) {
1460 m_bAdjustPCS = true; // turn ON PCS adjustment
1461
1462 // set up for input transform, which needs version 2 black point to version 4
1463 m_PCSScale[0] = (icFloatNumber) (1.0 - icPerceptualRefBlackX / icPerceptualRefWhiteX); // scale factors
1464 m_PCSScale[1] = (icFloatNumber) (1.0 - icPerceptualRefBlackY / icPerceptualRefWhiteY);
1465 m_PCSScale[2] = (icFloatNumber) (1.0 - icPerceptualRefBlackZ / icPerceptualRefWhiteZ);
1466
1467 m_PCSOffset[0] = (icFloatNumber) (icPerceptualRefBlackX * 32768.0 / 65535.0); // offset factors
1468 m_PCSOffset[1] = (icFloatNumber) (icPerceptualRefBlackY * 32768.0 / 65535.0);
1469 m_PCSOffset[2] = (icFloatNumber) (icPerceptualRefBlackZ * 32768.0 / 65535.0);
1470
1471 if (!m_bInput) { // output transform must convert version 4 black point to version 2
1472 m_PCSScale[0] = (icFloatNumber) 1.0 / m_PCSScale[0]; // invert scale factors
1473 m_PCSScale[1] = (icFloatNumber) 1.0 / m_PCSScale[1];
1474 m_PCSScale[2] = (icFloatNumber) 1.0 / m_PCSScale[2];
1475
1476 m_PCSOffset[0] = - m_PCSOffset[0] * m_PCSScale[0]; // negate offset factors
1477 m_PCSOffset[1] = - m_PCSOffset[1] * m_PCSScale[1];
1478 m_PCSOffset[2] = - m_PCSOffset[2] * m_PCSScale[2];
1479 }
1480 }
1481 }
1482
1483
1484 if (m_pAdjustPCS) {
1485 CIccProfile ProfileCopy(*m_pProfile);
1486
1487 // need to read in all the tags, so that a copy of the profile can be made
1488 if (!ProfileCopy.ReadTags(m_pProfile)) {
1490 }
1491
1492 if (!m_pAdjustPCS->CalcFactors(&ProfileCopy, this, m_PCSScale, m_PCSOffset)) {
1494 }
1495
1496 m_bAdjustPCS = true;
1497 delete m_pAdjustPCS;
1498 m_pAdjustPCS = NULL;
1499 }
1500
1501 return icCmmStatOk;
1502}
1503
1513CIccApplyXform *CIccXform::GetNewApply(icStatusCMM &status)
1514{
1515 CIccApplyXform *rv = new CIccApplyXform(this);
1516
1517 if (!rv) {
1518 status = icCmmStatAllocErr;
1519 return NULL;
1520 }
1521
1522 status = icCmmStatOk;
1523 return rv;
1524}
1525
1540void CIccXform::AdjustPCS(icFloatNumber *DstPixel, const icFloatNumber *SrcPixel) const
1541{
1542 icColorSpaceSignature Space = m_pProfile->m_Header.pcs;
1543
1544 if (Space==icSigLabData) {
1545 if (UseLegacyPCS()) {
1546 CIccPCSUtil::Lab2ToXyz(DstPixel, SrcPixel, true);
1547 }
1548 else {
1549 CIccPCSUtil::LabToXyz(DstPixel, SrcPixel, true);
1550 }
1551 }
1552 else {
1553 DstPixel[0] = SrcPixel[0];
1554 DstPixel[1] = SrcPixel[1];
1555 DstPixel[2] = SrcPixel[2];
1556 }
1557
1558 DstPixel[0] = DstPixel[0] * m_PCSScale[0] + m_PCSOffset[0];
1559 DstPixel[1] = DstPixel[1] * m_PCSScale[1] + m_PCSOffset[1];
1560 DstPixel[2] = DstPixel[2] * m_PCSScale[2] + m_PCSOffset[2];
1561
1562 if (Space==icSigLabData) {
1563 if (UseLegacyPCS()) {
1564
1565 CIccPCSUtil::XyzToLab2(DstPixel, DstPixel, true);
1566 }
1567 else {
1568 CIccPCSUtil::XyzToLab(DstPixel, DstPixel, true);
1569 }
1570 }
1571#ifndef SAMPLEICC_NOCLIPLABTOXYZ
1572 else {
1573 DstPixel[0] = CIccPCSUtil::NegClip(DstPixel[0]);
1574 DstPixel[1] = CIccPCSUtil::NegClip(DstPixel[1]);
1575 DstPixel[2] = CIccPCSUtil::NegClip(DstPixel[2]);
1576 }
1577#endif
1578}
1579
1596const icFloatNumber *CIccXform::CheckSrcAbs(CIccApplyXform *pApply, const icFloatNumber *Pixel) const
1597{
1598 if (m_bAdjustPCS && !m_bInput) {
1599 icFloatNumber *pAbsLab = pApply->m_AbsLab;
1600 AdjustPCS(pAbsLab, Pixel);
1601 return pAbsLab;
1602 }
1603
1604 return Pixel;
1605}
1606
1621void CIccXform::CheckDstAbs(icFloatNumber *Pixel) const
1622{
1623 if (m_bAdjustPCS && m_bInput) {
1624 AdjustPCS(Pixel, Pixel);
1625 }
1626}
1627
1639icColorSpaceSignature CIccXform::GetSrcSpace() const
1640{
1642 icProfileClassSignature deviceClass = m_pProfile->m_Header.deviceClass;
1643
1644 if (m_bInput) {
1645 if (m_bPcsAdjustXform)
1646 rv = m_pProfile->m_Header.pcs;
1647 else {
1648 rv = m_pProfile->m_Header.colorSpace;
1649
1650 if (deviceClass != icSigAbstractClass) {
1651 //convert signature to device colorspace signature (avoid confusion about encoding).
1652 if (rv == icSigXYZData) {
1653 rv = icSigDevXYZData;
1654 }
1655 else if (rv == icSigLabData) {
1656 rv = icSigDevLabData;
1657 }
1658 }
1659 }
1660 }
1661 else if (!m_bUseSpectralPCS || !m_pProfile->m_Header.spectralPCS) {
1662 rv = m_pProfile->m_Header.pcs;
1663 }
1664 else {
1665 rv = icGetColorSpaceType(m_pProfile->m_Header.spectralPCS);
1666 }
1667
1668 return rv;
1669}
1670
1682icUInt16Number CIccXform::GetNumSrcSamples() const
1683{
1684 icUInt16Number rv;
1685
1686 if (m_nMCS==icFromMCS) {
1687 rv = (icUInt16Number)icGetSpaceSamples((icColorSpaceSignature)m_pProfile->m_Header.mcs);
1688 }
1689 else if (m_bInput) {
1690 rv = (icUInt16Number)icGetSpaceSamples(m_pProfile->m_Header.colorSpace);
1691 }
1692 else if (!m_bUseSpectralPCS || !m_pProfile->m_Header.spectralPCS) {
1693 rv = (icUInt16Number)icGetSpaceSamples(m_pProfile->m_Header.pcs);
1694 }
1695 else {
1696 rv = (icUInt16Number)icGetSpectralSpaceSamples(&m_pProfile->m_Header);
1697 }
1698
1699 return rv;
1700}
1701
1713icColorSpaceSignature CIccXform::GetDstSpace() const
1714{
1716 icProfileClassSignature deviceClass = m_pProfile->m_Header.deviceClass;
1717
1718 if (m_nMCS==icToMCS) {
1719 rv = (icColorSpaceSignature)m_pProfile->m_Header.mcs;
1720 }
1721 else if (m_bInput) {
1722 if (m_bUseSpectralPCS && m_pProfile->m_Header.spectralPCS)
1723 rv = icGetColorSpaceType(m_pProfile->m_Header.spectralPCS);
1724 else
1725 rv = m_pProfile->m_Header.pcs;
1726 }
1727 else {
1728 rv = m_pProfile->m_Header.colorSpace;
1729
1730 //convert signature to device colorspace signature (avoid confusion about encoding).
1731 if (deviceClass != icSigAbstractClass) {
1732 if (rv==icSigXYZData) {
1733 rv = icSigDevXYZData;
1734 }
1735 else if (rv==icSigLabData) {
1736 rv = icSigDevLabData;
1737 }
1738 }
1739 }
1740
1741 return rv;
1742}
1743
1755icUInt16Number CIccXform::GetNumDstSamples() const
1756{
1757 icUInt16Number rv;
1758
1759 if (m_nMCS==icToMCS) {
1760 rv = (icUInt16Number)icGetSpaceSamples((icColorSpaceSignature)m_pProfile->m_Header.mcs);
1761 }
1762 else if (!m_bInput) {
1763 rv = (icUInt16Number)icGetSpaceSamples(m_pProfile->m_Header.colorSpace);
1764 }
1765 else if (!m_bUseSpectralPCS || !m_pProfile->m_Header.spectralPCS) {
1766 rv = (icUInt16Number)icGetSpaceSamples(m_pProfile->m_Header.pcs);
1767 }
1768 else {
1769 rv = (icUInt16Number)icGetSpectralSpaceSamples(&m_pProfile->m_Header);
1770 }
1771
1772 return rv;
1773}
1774
1775
1784CIccApplyXform::CIccApplyXform(CIccXform *pXform) : m_AbsLab{}
1785{
1786 m_pXform = pXform;
1787}
1788
1797CIccApplyXform::~CIccApplyXform()
1798{
1799}
1800
1801
1810CIccApplyNDLutXform::CIccApplyNDLutXform(CIccXformNDLut* pXform, CIccApplyCLUT *pApply) : CIccApplyXform(pXform)
1811{
1812 m_pApply = pApply;
1813}
1814
1815
1824CIccApplyNDLutXform::~CIccApplyNDLutXform()
1825{
1826 if (m_pApply)
1827 delete m_pApply;
1828}
1829
1830
1839CIccApplyPcsXform::CIccApplyPcsXform(CIccXform *pXform) : CIccApplyXform(pXform)
1840{
1841 m_list = new CIccApplyPcsStepList();
1842 m_temp1 = NULL;
1843 m_temp2 = NULL;
1844}
1845
1854CIccApplyPcsXform::~CIccApplyPcsXform()
1855{
1856
1857 if (m_list) {
1858 CIccApplyPcsStepList::iterator i;
1859 for (i=m_list->begin(); i!=m_list->end(); i++) {
1860 if (i->ptr)
1861 delete i->ptr;
1862 }
1863
1864 delete m_list;
1865 }
1866
1867 if (m_temp1)
1868 delete [] m_temp1;
1869 if (m_temp2)
1870 delete [] m_temp2;
1871}
1872
1881bool CIccApplyPcsXform::Init()
1882{
1883 CIccPcsXform *pXform = (CIccPcsXform*)m_pXform;
1884 icUInt16Number nChan = pXform->MaxChannels();
1885
1886 if (nChan) {
1887 m_temp1 = new icFloatNumber[nChan];
1888 m_temp2 = new icFloatNumber[nChan];
1889 }
1890
1891 return m_temp1!=NULL && m_temp2!=NULL;
1892}
1893
1894
1895void CIccApplyPcsXform::AppendApplyStep(CIccApplyPcsStep *pStep)
1896{
1897 CIccApplyPcsStepPtr ptr;
1898
1899 if (pStep && m_list) {
1900 ptr.ptr = pStep;
1901 m_list->push_back(ptr);
1902 }
1903}
1904
1905
1914CIccPcsXform::CIccPcsXform()
1915{
1916 m_list = new CIccPcsStepList();
1917
1918 m_srcSpace = icSigUnknownData;
1919 m_nSrcSamples = 0;
1920
1921 m_dstSpace = icSigUnknownData;
1922 m_nDstSamples = 0;
1923}
1924
1933CIccPcsXform::~CIccPcsXform()
1934{
1935 if (m_list) {
1936 CIccPcsStepList::iterator step;
1937 for (step=m_list->begin(); step!=m_list->end(); step++) {
1938 if (step->ptr) {
1939 delete step->ptr;
1940 step->ptr = NULL;
1941 }
1942 }
1943 delete m_list;
1944 }
1945}
1946
1956icStatusCMM CIccPcsXform::Connect(CIccXform *pFromXform, CIccXform *pToXform)
1957{
1958 icStatusCMM stat;
1959
1960 if (!pFromXform || !pToXform)
1961 return icCmmStatBadXform;
1962
1963 if (pFromXform->IsMCS() && pToXform->IsMCS()) {
1964 CIccProfile *pFromProfile = pFromXform->GetProfilePtr();
1965 CIccProfile *pToProfile = pToXform->GetProfilePtr();
1966
1967 if (!pFromProfile || !pToProfile) {
1968 return icCmmStatBadSpaceLink;
1969 }
1970 CIccTagArray *pFromChannels = (CIccTagArray*)(pFromProfile->FindTagOfType(icSigMaterialTypeArrayTag, icSigTagArrayType));
1971 CIccTagArray *pToChannels = (CIccTagArray*)(pToProfile->FindTagOfType(icSigMaterialTypeArrayTag, icSigTagArrayType));
1972
1973 if (!pFromChannels || !pToChannels) {
1974 return icCmmStatBadSpaceLink;
1975 }
1976 if (pFromChannels->GetTagArrayType()!=icSigUtf8TextTypeArray ||
1977 pToChannels->GetTagArrayType()!=icSigUtf8TextTypeArray ||
1978 !pFromChannels->AreAllOfType(icSigUtf8TextType) ||
1979 !pToChannels->AreAllOfType(icSigUtf8TextType)) {
1980 return icCmmStatBadSpaceLink;
1981 }
1982
1983 m_nSrcSamples = pFromXform->GetNumDstSamples();
1984 m_nDstSamples = pToXform->GetNumSrcSamples();
1985
1986 if (pFromChannels->GetSize() != m_nSrcSamples || pToChannels->GetSize() != m_nDstSamples) {
1987 return icCmmStatBadSpaceLink;
1988 }
1989 int i, j;
1990
1991 if (pFromProfile->m_Header.flags&icMCSNeedsSubsetTrue) {
1992 for (i=0; i<m_nSrcSamples; i++) {
1993 const icUChar *szSrcChan = ((CIccTagUtf8Text*)pFromChannels->GetIndex(i))->GetText();
1994 for (j=0; j<m_nDstSamples; j++) {
1995 const icUChar *szDstChan = ((CIccTagUtf8Text*)pToChannels->GetIndex(i))->GetText();
1996 if (!icUtf8StrCmp(szSrcChan, szDstChan))
1997 break;
1998 }
1999 if (j==m_nDstSamples)
2000 return icCmmStatBadMCSLink;
2001 }
2002 }
2003
2004 if (pToProfile->m_Header.flags&icMCSNeedsSubsetTrue) {
2005 for (i=0; i<m_nDstSamples; i++) {
2006 const icUChar *szDstChan = ((CIccTagUtf8Text*)pToChannels->GetIndex(i))->GetText();
2007 for (j=0; j<m_nSrcSamples; j++) {
2008 const icUChar *szSrcChan = ((CIccTagUtf8Text*)pFromChannels->GetIndex(i))->GetText();
2009 if (!icUtf8StrCmp(szSrcChan, szDstChan))
2010 break;
2011 }
2012 if (j==m_nSrcSamples)
2013 return icCmmStatBadMCSLink;
2014 }
2015 }
2016 CIccTag *pTag = pToProfile->FindTag(icSigMaterialDefaultValuesTag);
2017 CIccTagNumArray *pDefaults = NULL;
2018 if (pTag && pTag->IsNumArrayType()) {
2019 pDefaults = (CIccTagNumArray *)pTag;
2020 }
2021
2022 pushRouteMcs(pFromChannels, pToChannels, pDefaults);
2023 }
2024 else {
2025 if (!pFromXform->IsInput() || (pToXform->IsInput() && !pToXform->IsAbstract())) {
2026 return icCmmStatBadSpaceLink;
2027 }
2028
2029 m_srcSpace = pFromXform->GetDstSpace();
2030 if (IsSpaceSpectralPCS(m_srcSpace))
2031 m_srcSpace = icGetColorSpaceType(m_srcSpace);
2032
2033 m_nSrcSamples = pFromXform->GetNumDstSamples();
2034
2035 m_dstSpace = pToXform->GetSrcSpace();
2036 if (IsSpaceSpectralPCS(m_dstSpace))
2037 m_dstSpace = icGetColorSpaceType(m_dstSpace);
2038
2039 m_nDstSamples = pToXform->GetNumSrcSamples();
2040
2041 switch (m_srcSpace) {
2042 case icSigLabPcsData:
2043 switch (m_dstSpace) {
2044 case icSigLabPcsData:
2045 if (pFromXform->UseLegacyPCS())
2046 pushLab2ToXyz(pFromXform->m_pConnectionConditions);
2047 else
2048 pushLabToXyz(pFromXform->m_pConnectionConditions);
2049 if (pFromXform->NeedAdjustPCS()) {
2050 pushScale3(pFromXform->m_PCSScale[0], pFromXform->m_PCSScale[1], pFromXform->m_PCSScale[2]);
2051 pushOffset3(pFromXform->m_PCSOffset[0], pFromXform->m_PCSOffset[1], pFromXform->m_PCSOffset[2]);
2052 }
2053 if ((stat=pushXYZConvert(pFromXform, pToXform))!=icCmmStatOk) {
2054 return stat;
2055 }
2056 if (pToXform->NeedAdjustPCS()) {
2057 pushOffset3(pToXform->m_PCSOffset[0]/pToXform->m_PCSScale[0],
2058 pToXform->m_PCSOffset[1]/pToXform->m_PCSScale[1],
2059 pToXform->m_PCSOffset[2]/pToXform->m_PCSScale[2]);
2060 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2061 }
2062 if (pToXform->UseLegacyPCS())
2063 pushXyzToLab2(pToXform->m_pConnectionConditions);
2064 else
2065 pushXyzToLab(pToXform->m_pConnectionConditions);
2066 break;
2067
2068 case icSigXYZPcsData:
2069 if (pFromXform->UseLegacyPCS())
2070 pushLab2ToXyz(pFromXform->m_pConnectionConditions);
2071 else
2072 pushLabToXyz(pFromXform->m_pConnectionConditions);
2073 if (pFromXform->NeedAdjustPCS()) {
2074 pushScale3(pFromXform->m_PCSScale[0], pFromXform->m_PCSScale[1], pFromXform->m_PCSScale[2]);
2075 pushOffset3(pFromXform->m_PCSOffset[0], pFromXform->m_PCSOffset[1], pFromXform->m_PCSOffset[2]);
2076 }
2077 if ((stat=pushXYZConvert(pFromXform, pToXform))!=icCmmStatOk) {
2078 return stat;
2079 }
2080 if (pToXform->NeedAdjustPCS()) {
2081 pushOffset3(pToXform->m_PCSOffset[0]/pToXform->m_PCSScale[0],
2082 pToXform->m_PCSOffset[1]/pToXform->m_PCSScale[1],
2083 pToXform->m_PCSOffset[2]/pToXform->m_PCSScale[2]);
2084 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2085 }
2086 pushXyzToXyzIn();
2087 break;
2088
2095 }
2096 break;
2097
2098 case icSigXYZPcsData:
2099 switch (m_dstSpace) {
2100 case icSigLabPcsData:
2101 pushXyzInToXyz();
2102 if (pFromXform->NeedAdjustPCS()) {
2103 pushScale3(pFromXform->m_PCSScale[0], pFromXform->m_PCSScale[1], pFromXform->m_PCSScale[2]);
2104 pushOffset3(pFromXform->m_PCSOffset[0], pFromXform->m_PCSOffset[1], pFromXform->m_PCSOffset[2]);
2105 }
2106 if ((stat=pushXYZConvert(pFromXform, pToXform))!=icCmmStatOk) {
2107 return stat;
2108 }
2109 if (pToXform->NeedAdjustPCS()) {
2110 pushOffset3(pToXform->m_PCSOffset[0]/pToXform->m_PCSScale[0],
2111 pToXform->m_PCSOffset[1]/pToXform->m_PCSScale[1],
2112 pToXform->m_PCSOffset[2]/pToXform->m_PCSScale[2]);
2113 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2114 }
2115 if (pToXform->UseLegacyPCS())
2116 pushXyzToLab2(pToXform->m_pConnectionConditions);
2117 else
2118 pushXyzToLab(pToXform->m_pConnectionConditions);
2119 break;
2120
2121 case icSigXYZPcsData:
2122 pushXyzInToXyz();
2123 if (pFromXform->NeedAdjustPCS()) {
2124 pushScale3(pFromXform->m_PCSScale[0], pFromXform->m_PCSScale[1], pFromXform->m_PCSScale[2]);
2125 pushOffset3(pFromXform->m_PCSOffset[0], pFromXform->m_PCSOffset[1], pFromXform->m_PCSOffset[2]);
2126 }
2127 if ((stat=pushXYZConvert(pFromXform, pToXform))!=icCmmStatOk) {
2128 return stat;
2129 }
2130 if (pToXform->NeedAdjustPCS()) {
2131 pushOffset3(pToXform->m_PCSOffset[0]/pToXform->m_PCSScale[0],
2132 pToXform->m_PCSOffset[1]/pToXform->m_PCSScale[1],
2133 pToXform->m_PCSOffset[2]/pToXform->m_PCSScale[2]);
2134 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2135 }
2136 pushXyzToXyzIn();
2137 break;
2138
2145 }
2146 break;
2147
2150 switch (m_dstSpace) {
2151 case icSigLabPcsData:
2152 pushRef2Xyz(pFromXform->m_pProfile, pFromXform->m_pConnectionConditions);
2153 if ((stat=pushXYZConvert(pFromXform, pToXform))!=icCmmStatOk) {
2154 return stat;
2155 }
2156 if (pToXform->NeedAdjustPCS()) {
2157 pushOffset3(pToXform->m_PCSOffset[0]/pToXform->m_PCSScale[0],
2158 pToXform->m_PCSOffset[1]/pToXform->m_PCSScale[1],
2159 pToXform->m_PCSOffset[2]/pToXform->m_PCSScale[2]);
2160 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2161 }
2162 if (pToXform->UseLegacyPCS())
2163 pushXyzToLab2(pToXform->m_pConnectionConditions);
2164 else
2165 pushXyzToLab(pToXform->m_pConnectionConditions);
2166 break;
2167
2168 case icSigXYZPcsData:
2169 pushRef2Xyz(pFromXform->m_pProfile, pFromXform->m_pConnectionConditions);
2170 if ((stat=pushXYZConvert(pFromXform, pToXform))!=icCmmStatOk) {
2171 return stat;
2172 }
2173 if (pToXform->NeedAdjustPCS()) {
2174 pushOffset3(pToXform->m_PCSOffset[0]/pToXform->m_PCSScale[0],
2175 pToXform->m_PCSOffset[1]/pToXform->m_PCSScale[1],
2176 pToXform->m_PCSOffset[2]/pToXform->m_PCSScale[2]);
2177 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2178 }
2179 pushXyzToXyzIn();
2180 break;
2181
2184 pushSpecToRange(pFromXform->m_pProfile->m_Header.spectralRange,
2185 pToXform->m_pProfile->m_Header.spectralRange);
2186 break;
2187
2189 pushApplyIllum(pFromXform->m_pProfile, pFromXform->m_pConnectionConditions);
2190 pushSpecToRange(pFromXform->m_pProfile->m_Header.spectralRange,
2191 pToXform->m_pProfile->m_Header.spectralRange);
2192 break;
2193
2197 }
2198 break;
2199
2201 CIccProfile *pFromProfile = pFromXform->GetProfilePtr();
2202 CIccProfile *pToProfile = pToXform->GetProfilePtr();
2203
2204 switch (m_dstSpace) {
2205 case icSigLabPcsData:
2206 pushRad2Xyz(pFromProfile, pFromXform->m_pConnectionConditions, false);
2207 if ((stat=pushXYZConvert(pFromXform, pToXform))!=icCmmStatOk) {
2208 return stat;
2209 }
2210 if (pToXform->NeedAdjustPCS()) {
2211 pushOffset3(pToXform->m_PCSOffset[0]/pToXform->m_PCSScale[0],
2212 pToXform->m_PCSOffset[1]/pToXform->m_PCSScale[1],
2213 pToXform->m_PCSOffset[2]/pToXform->m_PCSScale[2]);
2214 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2215 }
2216 if (pToXform->UseLegacyPCS())
2217 pushXyzToLab2(pToXform->m_pConnectionConditions);
2218 else
2219 pushXyzToLab(pToXform->m_pConnectionConditions);
2220 break;
2221
2222 case icSigXYZPcsData:
2223 pushRad2Xyz(pFromProfile, pFromXform->m_pConnectionConditions, false);
2224 if ((stat=pushXYZConvert(pFromXform, pToXform))!=icCmmStatOk) {
2225 return stat;
2226 }
2227 if (pToXform->NeedAdjustPCS()) {
2228 pushOffset3(pToXform->m_PCSOffset[0]/pToXform->m_PCSScale[0],
2229 pToXform->m_PCSOffset[1]/pToXform->m_PCSScale[1],
2230 pToXform->m_PCSOffset[2]/pToXform->m_PCSScale[2]);
2231 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2232 }
2233 pushXyzToXyzIn();
2234 break;
2235
2239
2240
2242 pushSpecToRange(pFromXform->m_pProfile->m_Header.spectralRange,
2243 pToXform->m_pProfile->m_Header.spectralRange);
2244 break;
2245
2249 }
2250 }
2251 break;
2252
2255 switch (m_dstSpace) {
2256 case icSigLabPcsData:
2257 pushBiRef2Xyz(pFromXform->m_pProfile, pFromXform->m_pConnectionConditions);
2258 if ((stat=pushXYZConvert(pFromXform, pToXform))!=icCmmStatOk) {
2259 return stat;
2260 }
2261 if (pToXform->NeedAdjustPCS()) {
2262 pushOffset3(pToXform->m_PCSOffset[0]/pToXform->m_PCSScale[0],
2263 pToXform->m_PCSOffset[1]/pToXform->m_PCSScale[1],
2264 pToXform->m_PCSOffset[2]/pToXform->m_PCSScale[2]);
2265 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2266 }
2267 if (pToXform->UseLegacyPCS())
2268 pushXyzToLab2(pToXform->m_pConnectionConditions);
2269 else
2270 pushXyzToLab(pToXform->m_pConnectionConditions);
2271 break;
2272
2273 case icSigXYZPcsData:
2274 if ((stat=pushBiRef2Xyz(pFromXform->m_pProfile, pFromXform->m_pConnectionConditions))!=icCmmStatOk) {
2275 return stat;
2276 }
2277 if ((stat=pushXYZConvert(pFromXform, pToXform))!=icCmmStatOk) {
2278 return stat;
2279 }
2280 if (pToXform->NeedAdjustPCS()) {
2281 pushOffset3(pToXform->m_PCSOffset[0]/pToXform->m_PCSScale[0],
2282 pToXform->m_PCSOffset[1]/pToXform->m_PCSScale[1],
2283 pToXform->m_PCSOffset[2]/pToXform->m_PCSScale[2]);
2284 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2285 }
2286 pushXyzToXyzIn();
2287 break;
2288
2291 if ((stat=pushBiRef2Ref(pFromXform->m_pProfile, pFromXform->m_pConnectionConditions))!=icCmmStatOk) {
2292 return stat;
2293 }
2294 pushSpecToRange(pFromXform->m_pProfile->m_Header.spectralRange,
2295 pToXform->m_pProfile->m_Header.spectralRange);
2296 break;
2297
2299 if ((stat=pushBiRef2Rad(pFromXform->m_pProfile, pFromXform->m_pConnectionConditions))!=icCmmStatOk) {
2300 return stat;
2301 }
2302 pushSpecToRange(pFromXform->m_pProfile->m_Header.spectralRange,
2303 pToXform->m_pProfile->m_Header.spectralRange);
2304 break;
2305
2307 if (icSameSpectralRange(pFromXform->m_pProfile->m_Header.spectralRange, pToXform->m_pProfile->m_Header.spectralRange) &&
2308 icSameSpectralRange(pFromXform->m_pProfile->m_Header.biSpectralRange, pToXform->m_pProfile->m_Header.biSpectralRange))
2309 break;
2310 else
2312
2315 }
2316 break;
2317 }
2318 }
2319
2320 icStatusCMM rv = Optimize();
2321 if (rv!=icCmmStatOk)
2322 return rv;
2323
2324 if (m_list->begin()==m_list->end())
2326
2327 return icCmmStatOk;
2328}
2329
2330
2340icStatusCMM CIccPcsXform::ConnectFirst(CIccXform* pToXform, icColorSpaceSignature srcSpace)
2341{
2342 if (!pToXform)
2343 return icCmmStatBadXform;
2344
2345
2346 if (srcSpace == icSigXYZData) {
2347 pushXyzInToXyz();
2348 if (pToXform->NeedAdjustPCS()) {
2349 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2350 pushOffset3(pToXform->m_PCSOffset[0], pToXform->m_PCSOffset[1], pToXform->m_PCSOffset[2]);
2351 }
2352
2353 if (pToXform->GetSrcSpace() == icSigLabData) {
2354 if (pToXform->UseLegacyPCS())
2355 pushXyzToLab2(pToXform->m_pConnectionConditions);
2356 else
2357 pushXyzToLab(pToXform->m_pConnectionConditions);
2358 }
2359 }
2360 else if (srcSpace == icSigLabData) {
2361
2362 if (pToXform->GetSrcSpace() == icSigXYZData) {
2363 pushLabToXyz(pToXform->m_pConnectionConditions);
2364 if (pToXform->NeedAdjustPCS()) {
2365 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2366 pushOffset3(pToXform->m_PCSOffset[0], pToXform->m_PCSOffset[1], pToXform->m_PCSOffset[2]);
2367 }
2368 }
2369 else if (pToXform->NeedAdjustPCS()) {
2370 pushLabToXyz(pToXform->m_pConnectionConditions);
2371 pushScale3(pToXform->m_PCSScale[0], pToXform->m_PCSScale[1], pToXform->m_PCSScale[2]);
2372 pushOffset3(pToXform->m_PCSOffset[0], pToXform->m_PCSOffset[1], pToXform->m_PCSOffset[2]);
2373 if (pToXform->UseLegacyPCS())
2374 pushXyzToLab2(pToXform->m_pConnectionConditions);
2375 else
2376 pushXyzToLab(pToXform->m_pConnectionConditions);
2377 }
2378 }
2379
2380 return icCmmStatOk;
2381}
2382
2383
2393icStatusCMM CIccPcsXform::ConnectLast(CIccXform* pFromXform, icColorSpaceSignature dstSpace)
2394{
2395 if (!pFromXform)
2396 return icCmmStatBadXform;
2397 icColorSpaceSignature srcSpace = pFromXform->GetDstSpace();
2398
2399 if (pFromXform->NeedAdjustPCS() && IsSpaceColorimetricPCS(dstSpace)) {
2400 if (srcSpace == icSigLabData) {
2401 if (pFromXform->UseLegacyPCS())
2402 pushLab2ToXyz(pFromXform->m_pConnectionConditions);
2403 else
2404 pushLabToXyz(pFromXform->m_pConnectionConditions);
2405
2406 pushScale3(pFromXform->m_PCSScale[0], pFromXform->m_PCSScale[1], pFromXform->m_PCSScale[2]);
2407 pushOffset3(pFromXform->m_PCSOffset[0], pFromXform->m_PCSOffset[1], pFromXform->m_PCSOffset[2]);
2408
2409 srcSpace = icSigXYZData;
2410 }
2411 }
2412
2413 if (srcSpace == icSigXYZData && dstSpace == icSigLabData) {
2414 pushXyzToLab(pFromXform->m_pConnectionConditions);
2415 }
2416 else if (srcSpace == icSigLabData && dstSpace == icSigXYZData) {
2417 if (pFromXform->UseLegacyPCS())
2418 pushLab2ToXyz(pFromXform->m_pConnectionConditions);
2419 else
2420 pushLabToXyz(pFromXform->m_pConnectionConditions);
2421 if (pFromXform->IsInput())
2422 pushXyzToXyzIn();
2423 }
2424 else if (pFromXform->IsInput() && srcSpace == icSigXYZData && dstSpace == icSigXYZData) {
2425 pushXyzToXyzIn();
2426 }
2427
2428 return icCmmStatOk;
2429}
2430
2431
2440icStatusCMM CIccPcsXform::Optimize()
2441{
2442 if (!m_list)
2443 return icCmmStatBadXform;
2444
2445 CIccPcsStepList steps = *m_list;
2446 CIccPcsStepList::iterator next, last;
2447 bool done=false;
2448
2449#if 0
2450 std::string str;
2451 for (next = steps.begin(); next != steps.end(); next++) {
2452 next->ptr->dump(str);
2453 }
2454 printf("PCS_Steps:\n%s", str.c_str());
2455#endif
2456
2457 while (!done) {
2458 CIccPcsStepList newSteps;
2459 CIccPcsStepPtr ptr;
2460
2461 done = true;
2462
2463 next = steps.begin();
2464 if (next==steps.end()) {
2465 *m_list = steps;
2467 }
2468 last = next;
2469 next++;
2470
2471 ptr.ptr = last->ptr;
2472
2473 for (;next!=steps.end(); next++) {
2474 CIccPcsStep *pStep = ptr.ptr->concat(next->ptr);
2475
2476 if (pStep) {
2477 done = false;
2478
2479 delete ptr.ptr;
2480 delete next->ptr;
2481 ptr.ptr = pStep;
2482 }
2483 else {
2484 if (!ptr.ptr->isIdentity()) {
2485 newSteps.push_back(ptr);
2486 }
2487 ptr.ptr = next->ptr;
2488 }
2489 }
2490 if (!ptr.ptr->isIdentity()) {
2491 newSteps.push_back(ptr);
2492 }
2493
2494 steps = newSteps;
2495
2496// for (next=steps.begin(); next!=steps.end(); next++) {
2497// ptr.ptr = next->ptr;
2498// done = true;
2499// }
2500
2501 }
2502
2503 if (!steps.empty()) {
2504 CIccPcsStepList newSteps;
2505 CIccPcsStepPtr ptr;
2506
2507 for (next=steps.begin(); next != steps.end(); next++) {
2508 ptr.ptr = next->ptr->reduce();
2509 if (ptr.ptr != next->ptr)
2510 delete next->ptr;
2511 newSteps.push_back(ptr);
2512 }
2513 steps = newSteps;
2514 }
2515
2516 *m_list = steps;
2517
2518 return icCmmStatOk;
2519}
2520
2521
2531CIccApplyXform *CIccPcsXform::GetNewApply(icStatusCMM &status)
2532{
2533 CIccApplyPcsXform *pNew = new CIccApplyPcsXform(this);
2534
2535 if (pNew) {
2536 if (!pNew->Init()) {
2537 delete pNew;
2538 status = icCmmStatAllocErr;
2539 return NULL;
2540 }
2541 }
2542 else {
2543 status = icCmmStatAllocErr;
2544 return NULL;
2545 }
2546
2547 CIccPcsStepList::iterator i;
2548 CIccApplyPcsStep *pStep;
2549
2550 for (i=m_list->begin(); i!=m_list->end(); i++) {
2551 pStep = i->ptr->GetNewApply();
2552 if (!pStep || status != icCmmStatOk) {
2553 delete pNew;
2554 return NULL;
2555 }
2556 pNew->AppendApplyStep(pStep);
2557 }
2558
2559 return pNew;
2560}
2561
2562
2571icUInt16Number CIccPcsXform::MaxChannels()
2572{
2573 icUInt16Number nMax = 0;
2574 CIccPcsStepList::const_iterator s = m_list->begin();
2575 if (s==m_list->end())
2576 return nMax;
2577 nMax = s->ptr->GetDstChannels();
2578 s++;
2579 for (; s!= m_list->end(); s++) {
2580 if (s->ptr->GetSrcChannels()>nMax)
2581 nMax = s->ptr->GetSrcChannels();
2582 }
2583 return nMax;
2584}
2585
2594void CIccPcsXform::pushRouteMcs(CIccTagArray *pSrcChannels, CIccTagArray *pDstChannels, CIccTagNumArray *pDefaults)
2595{
2596 CIccPcsStepPtr ptr;
2597
2598 ptr.ptr = new CIccPcsStepRouteMcs(pSrcChannels, pDstChannels, pDefaults);
2599 m_list->push_back(ptr);
2600}
2601
2602
2611void CIccPcsXform::pushLab2ToXyz( IIccProfileConnectionConditions *pPCC)
2612{
2613 icFloatNumber xyzWhite[3];
2614 pPCC->getNormIlluminantXYZ(xyzWhite);
2615
2616 CIccPcsStepPtr ptr;
2617
2618 ptr.ptr = new CIccPcsStepLab2ToXYZ(xyzWhite);
2619 m_list->push_back(ptr);
2620}
2621
2622
2631void CIccPcsXform::pushXyzToLab2(IIccProfileConnectionConditions *pPCC)
2632{
2633 icFloatNumber xyzWhite[3];
2634 pPCC->getNormIlluminantXYZ(xyzWhite);
2635
2636 CIccPcsStepPtr ptr;
2637
2638 ptr.ptr = new CIccPcsStepXYZToLab2(xyzWhite);
2639 m_list->push_back(ptr);
2640}
2641
2642
2651void CIccPcsXform::pushLabToXyz(IIccProfileConnectionConditions *pPCC)
2652{
2653 icFloatNumber xyzWhite[3];
2654 pPCC->getNormIlluminantXYZ(xyzWhite);
2655
2656 CIccPcsStepPtr ptr;
2657
2658 ptr.ptr = new CIccPcsStepLabToXYZ(xyzWhite);
2659 m_list->push_back(ptr);
2660}
2661
2662
2671void CIccPcsXform::pushXyzToLab( IIccProfileConnectionConditions *pPCC)
2672{
2673 icFloatNumber xyzWhite[3];
2674 pPCC->getNormIlluminantXYZ(xyzWhite);
2675
2676 CIccPcsStepPtr ptr;
2677
2678 ptr.ptr = new CIccPcsStepXYZToLab(xyzWhite);
2679 m_list->push_back(ptr);
2680}
2681
2691void CIccPcsXform::pushScale3(icFloatNumber v1, icFloatNumber v2, icFloatNumber v3)
2692{
2693 CIccPcsStepScale *scale;
2694 CIccPcsStepPtr ptr;
2695
2696 scale = new CIccPcsStepScale(3);
2697 icFloatNumber *data = scale->data();
2698 data[0] = v1;
2699 data[1] = v2;
2700 data[2] = v3;
2701
2702 ptr.ptr = scale;
2703 m_list->push_back(ptr);
2704}
2705
2714void CIccPcsXform::pushXyzToXyzIn()
2715{
2716 icFloatNumber scale = (icFloatNumber) (32768.0 / 65535.0);
2717 pushScale3(scale, scale, scale);
2718}
2719
2720
2729void CIccPcsXform::pushXyzInToXyz()
2730{
2731 icFloatNumber scale = (icFloatNumber) (65535.0 / 32768.0);
2732 return pushScale3(scale, scale, scale);
2733}
2734
2735
2744void CIccPcsXform::pushXyzToXyzLum(IIccProfileConnectionConditions *pPCC)
2745{
2746 icFloatNumber XYZLum[3];
2747 pPCC->getLumIlluminantXYZ(&XYZLum[0]);
2748
2749 icFloatNumber scale = XYZLum[1];
2750
2751 return pushScale3(scale, scale, scale);
2752}
2753
2754
2763void CIccPcsXform::pushXyzLumToXyz(IIccProfileConnectionConditions *pPCC)
2764{
2765 icFloatNumber XYZLum[3];
2766 pPCC->getLumIlluminantXYZ(&XYZLum[0]);
2767
2768 icFloatNumber scale = 1.0f / XYZLum[1];
2769
2770 return pushScale3(scale, scale, scale);
2771}
2772
2773
2784void CIccPcsXform::pushOffset3(icFloatNumber v1, icFloatNumber v2, icFloatNumber v3, bool bConvertIntXyzOffset/*=true*/)
2785{
2786 CIccPcsStepOffset *offset;
2787 CIccPcsStepPtr ptr;
2788
2789 offset = new CIccPcsStepOffset(3);
2790 icFloatNumber *data = offset->data();
2791 if (bConvertIntXyzOffset) {
2792 data[0] = v1*65535.0f/32768.0f;
2793 data[1] = v2*65535.0f/32768.0f;
2794 data[2] = v3*65535.0f/32768.0f;
2795 }
2796 else {
2797 data[0] = v1;
2798 data[1] = v2;
2799 data[2] = v3;
2800 }
2801
2802 ptr.ptr = offset;
2803 m_list->push_back(ptr);
2804}
2805
2806
2816void CIccPcsXform::pushScale(icUInt16Number n, const icFloatNumber *vals)
2817{
2818 CIccPcsStepScale *scale = new CIccPcsStepScale(n);
2819 memcpy(scale->data(), vals, n*sizeof(icFloatNumber));
2820
2821 CIccPcsStepPtr ptr;
2822 ptr.ptr = scale;
2823 m_list->push_back(ptr);
2824}
2825
2826
2835void CIccPcsXform::pushMatrix(icUInt16Number nRows, icUInt16Number nCols, const icFloatNumber *vals)
2836{
2837 CIccPcsStepMatrix *mtx = new CIccPcsStepMatrix(nRows, nCols);
2838 memcpy(mtx->entry(0), vals, nRows*nCols*sizeof(icFloatNumber));
2839
2840 CIccPcsStepPtr ptr;
2841 ptr.ptr = mtx;
2842 m_list->push_back(ptr);
2843}
2844
2845
2856icStatusCMM CIccPcsXform::pushXYZConvert(CIccXform *pFromXform, CIccXform *pToXform)
2857{
2858 IIccProfileConnectionConditions *pSrcPcc = pFromXform->GetConnectionConditions();
2859 IIccProfileConnectionConditions *pDstPcc = pToXform->GetConnectionConditions();
2860
2861 if (!pSrcPcc || !pDstPcc)
2863
2864 //If source and dest observer and illuminant are same then no transform is needed
2865 if (pSrcPcc->isEquivalentPcc(*pDstPcc)) {
2866 return icCmmStatOk;
2867 }
2868
2869 CIccPcsStepPtr ptr;
2870
2871 if (!pSrcPcc->isStandardPcc()) {
2872
2874
2875 if (!pMpe || pMpe->NumInputChannels()!=3 || pMpe->NumOutputChannels()!=3)
2876 return icCmmStatBadSpaceLink;
2877
2878 ptr.ptr = NULL;
2879
2880 //push single matrix element as a CIccPcsStepMatrix so it can be optimized
2881 if (pMpe->NumElements()==1) {
2882 CIccMultiProcessElement *pElem = pMpe->GetElement(0);
2883 if (pElem) {
2884 if (pElem->GetType()==icSigMatrixElemType) {
2885 CIccMpeMatrix *pMatElem = (CIccMpeMatrix*)pElem;
2886
2887 icFloatNumber *pMat = pMatElem->GetMatrix();
2888 icFloatNumber *pOffset = pMatElem->GetConstants();
2889
2890 if (pMat && (!pOffset || (pOffset[0]==0.0 && pOffset[1]==0.0 && pOffset[2]==0.0))) {
2891 CIccPcsStepMatrix *pStepMtx = new CIccPcsStepMatrix(3, 3);
2892
2893 if (pStepMtx ) {
2894 memcpy(pStepMtx->entry(0,0), pMat, 9*sizeof(icFloatNumber));
2895 }
2896 ptr.ptr = pStepMtx;
2897 }
2898 }
2899 }
2900 }
2901
2902 if (!ptr.ptr) {
2903 CIccPcsStepMpe *pStepMpe = new CIccPcsStepMpe((CIccTagMultiProcessElement*)pMpe->NewCopy());
2904
2905 if (!pStepMpe)
2906 return icCmmStatAllocErr;
2907
2908 if (!pStepMpe->Begin()) {
2909 delete pStepMpe;
2911 }
2912
2913 ptr.ptr = pStepMpe;
2914 }
2915
2916 m_list->push_back(ptr);
2917 }
2918
2919 if (!pDstPcc->isStandardPcc()) {
2920
2922
2923 if (!pMpe || pMpe->NumInputChannels()!=3 || pMpe->NumOutputChannels()!=3)
2924 return icCmmStatBadSpaceLink;
2925
2926 ptr.ptr = NULL;
2927
2928 //push single matrix element as a CIccPcsStepMatrix so it can be optimized
2929 if (pMpe->NumElements()==1) {
2930 CIccMultiProcessElement *pElem = pMpe->GetElement(0);
2931 if (pElem) {
2932 if (pElem->GetType()==icSigMatrixElemType) {
2933 CIccMpeMatrix *pMatElem = (CIccMpeMatrix*)pElem;
2934
2935 icFloatNumber *pMat = pMatElem->GetMatrix();
2936 icFloatNumber *pOffset = pMatElem->GetConstants();
2937
2938 if (pMat && (!pOffset || (pOffset[0]==0.0 && pOffset[1]==0.0 && pOffset[2]==0.0))) {
2939 CIccPcsStepMatrix *pStepMtx = new CIccPcsStepMatrix(3, 3);
2940
2941 if (pStepMtx ) {
2942 memcpy(pStepMtx->entry(0,0), pMat, 9*sizeof(icFloatNumber));
2943 }
2944 ptr.ptr = pStepMtx;
2945 }
2946 }
2947 }
2948 }
2949
2950 if (!ptr.ptr) {
2951 CIccPcsStepMpe *pStepMpe = new CIccPcsStepMpe((CIccTagMultiProcessElement*)pMpe->NewCopy());
2952
2953 if (!pStepMpe)
2954 return icCmmStatAllocErr;
2955
2956 if (!pStepMpe->Begin()) {
2957 delete pStepMpe;
2959 }
2960
2961 ptr.ptr = pStepMpe;
2962 }
2963
2964 m_list->push_back(ptr);
2965 }
2966
2967 if (pFromXform->LuminanceMatching()) {
2968 pushXyzToXyzLum(pSrcPcc);
2969 }
2970 if (pToXform->LuminanceMatching()) {
2971 pushXyzLumToXyz(pDstPcc);
2972 }
2973
2974 return icCmmStatOk;
2975}
2976
2977void CIccPcsXform::pushXYZNormalize(IIccProfileConnectionConditions *pPcc, const icSpectralRange &srcRange, const icSpectralRange &dstRange)
2978{
2980 CIccPcsXform tmp;
2981
2982 icSpectralRange illuminantRange;
2983 const icFloatNumber *illuminant = pView->getIlluminant(illuminantRange);
2984
2985 icSpectralRange observerRange;
2986 const icFloatNumber *observer = pView->getObserver(observerRange);
2987
2988 //make sure illuminant goes through identical conversion steps
2989 if (!icSameSpectralRange(srcRange, illuminantRange) || !icSameSpectralRange(dstRange, illuminantRange)) {
2990 tmp.pushSpecToRange(illuminantRange, srcRange);
2991 tmp.pushSpecToRange(srcRange, dstRange);
2992 tmp.pushSpecToRange(dstRange, observerRange);
2993 }
2994 else {
2995 tmp.pushSpecToRange(illuminantRange, observerRange);
2996 }
2997 tmp.pushMatrix(3, observerRange.steps, observer);
2998
3000 CIccApplyXform *pApply = tmp.GetNewApply(stat);
3001 if (pApply) {
3002 icFloatNumber xyz[3], normxyz[3], pccxyz[3];
3003
3004 //Get absolute xyz for illuminant and observer
3005 tmp.Apply(pApply, xyz, illuminant);
3006
3007 //calculate normalized XYZ
3008 normxyz[0] = xyz[0] / xyz[1];
3009 normxyz[1] = xyz[1] / xyz[1];
3010 normxyz[2] = xyz[2] / xyz[1];
3011
3012 //get desired XYZ from pcc (might be slightly different from calculated normxyz)
3013 pPcc->getNormIlluminantXYZ(pccxyz);
3014
3015#if 1
3016 //push scale factor to normalize XYZ values and correct for difference between calculated and desired XYZ
3017 pushScale3(pccxyz[0] / (normxyz[0] * xyz[1]),
3018 pccxyz[1] / (normxyz[1] * xyz[1]),
3019 pccxyz[2] / (normxyz[2] * xyz[1]));
3020#else
3021 pushScale3(1.0f/xyz[1], 1.0f/xyz[1], 1.0f/xyz[1]);
3022#endif
3023
3024 delete pApply;
3025 }
3026}
3027
3038void CIccPcsXform::pushRef2Xyz(CIccProfile *pProfile, IIccProfileConnectionConditions *pPcc)
3039{
3041
3042 if (pView) {
3043 icSpectralRange illuminantRange;
3044 const icFloatNumber *illuminant = pView->getIlluminant(illuminantRange);
3045
3046 icSpectralRange observerRange;
3047 const icFloatNumber *observer = pView->getObserver(observerRange);
3048
3049 pushSpecToRange(pProfile->m_Header.spectralRange, illuminantRange);
3050 pushScale(illuminantRange.steps, illuminant);
3051 pushSpecToRange(illuminantRange, observerRange);
3052 pushMatrix(3, observerRange.steps, observer);
3053
3054 pushXYZNormalize(pPcc, illuminantRange, illuminantRange);
3055 }
3056}
3057
3058
3068CIccPcsStepMatrix *CIccPcsXform::rangeMap(const icSpectralRange &srcRange, const icSpectralRange &dstRange)
3069{
3070 if (srcRange.steps != dstRange.steps ||
3071 srcRange.start != dstRange.start ||
3072 srcRange.end != dstRange.end) {
3073 CIccPcsStepMatrix *mtx = new CIccPcsStepMatrix(dstRange.steps, srcRange.steps);
3074 if (!mtx->SetRange(srcRange, dstRange))
3075 {
3076 delete mtx;
3077 return NULL;
3078 }
3079 return mtx;
3080 }
3081
3082 return NULL;
3083}
3084
3085
3095void CIccPcsXform::pushSpecToRange(const icSpectralRange &srcRange, const icSpectralRange &dstRange)
3096{
3097 if (!icSameSpectralRange(srcRange, dstRange)) {
3098 CIccPcsStepPtr ptr;
3099 ptr.ptr = rangeMap(srcRange, dstRange);
3100
3101 if (ptr.ptr)
3102 m_list->push_back(ptr);
3103 }
3104}
3105
3106
3118void CIccPcsXform::pushApplyIllum(CIccProfile *pProfile, IIccProfileConnectionConditions *pPcc)
3119{
3121
3122 if (pView) {
3123 CIccPcsStepPtr ptr;
3124
3125 icSpectralRange illuminantRange;
3126 const icFloatNumber *illuminant = pView->getIlluminant(illuminantRange);
3127
3128 CIccPcsStepScale *pScale = new CIccPcsStepScale(illuminantRange.steps);
3129 memcpy(pScale->data(), illuminant, illuminantRange.steps*sizeof(icFloatNumber));
3130
3131 if (icSameSpectralRange(pProfile->m_Header.spectralRange, illuminantRange)) {
3132 ptr.ptr = pScale;
3133 m_list->push_back(ptr);
3134 }
3135 else {
3136 ptr.ptr = rangeMap(pProfile->m_Header.spectralRange, illuminantRange);
3137 if (ptr.ptr) {
3138 m_list->push_back(ptr);
3139 }
3140
3141 ptr.ptr = pScale;
3142 m_list->push_back(ptr);
3143
3144 ptr.ptr = rangeMap(illuminantRange, pProfile->m_Header.spectralRange);
3145 if (ptr.ptr)
3146 m_list->push_back(ptr);
3147 }
3148 }
3149}
3150
3151
3162void CIccPcsXform::pushRad2Xyz(CIccProfile* pProfile, IIccProfileConnectionConditions *pPcc, bool bAbsoluteCIEColorimetry)
3163{
3164 const CIccTagSpectralViewingConditions *pProfView = pProfile ? pProfile->getPccViewingConditions() : NULL;
3166 if (pProfView && pView) {
3167 icSpectralRange illuminantRange;
3168 const icFloatNumber *illuminant = pView->getIlluminant(illuminantRange);
3169
3170 icSpectralRange observerRange;
3171 const icFloatNumber *observer = pView->getObserver(observerRange);
3172
3173 //Preserve smallest step size
3174 icFloatNumber dPCSStepSize = (icF16toF(pProfile->m_Header.spectralRange.end) - icF16toF(pProfile->m_Header.spectralRange.start))/(icFloatNumber)pProfile->m_Header.spectralRange.steps;
3175 icFloatNumber dObsStepSize = (icF16toF(observerRange.end) - icF16toF(observerRange.start)) / (icFloatNumber) observerRange.steps;
3176
3177 if (dPCSStepSize<dObsStepSize) {
3178 icFloatNumber *obs = pView->applyRangeToObserver(pProfile->m_Header.spectralRange);
3179
3180 pushMatrix(3, pProfile->m_Header.spectralRange.steps, obs);
3181 free(obs);
3182 }
3183 else {
3184 pushSpecToRange(pProfile->m_Header.spectralRange, observerRange);
3185 pushMatrix(3, observerRange.steps, observer);
3186
3187 }
3188 icFloatNumber k;
3189 if (bAbsoluteCIEColorimetry) {
3190 k = 683;
3191 }
3192 else {
3193 k = 1.0f / pPcc->getObserverWhiteScaleFactor(illuminant, illuminantRange);
3194 }
3195 pushScale3(k, k, k);
3196 }
3197}
3198
3199
3209icStatusCMM CIccPcsXform::pushBiRef2Rad(CIccProfile *pProfile, IIccProfileConnectionConditions *pPcc)
3210{
3212
3213 if (pView) {
3214 icSpectralRange illuminantRange;
3215 const icFloatNumber *illuminant = pView->getIlluminant(illuminantRange);
3216
3217 if (icGetColorSpaceType(pProfile->m_Header.spectralPCS)==icSigSparseMatrixSpectralPcsData) {
3218 CIccPcsStepSrcSparseMatrix *pMtx = new CIccPcsStepSrcSparseMatrix(pProfile->m_Header.spectralRange.steps,
3219 pProfile->m_Header.biSpectralRange.steps,
3220 (icUInt16Number)icGetSpaceSamples((icColorSpaceSignature)pProfile->m_Header.spectralPCS));
3221 if (!pMtx)
3222 return icCmmStatAllocErr;
3223
3224 CIccPcsStepMatrix *illumMtx = rangeMap(illuminantRange, pProfile->m_Header.biSpectralRange);
3225 if (illumMtx) {
3226 illumMtx->Apply(NULL, pMtx->data(), illuminant);
3227 delete illumMtx;
3228 }
3229 else {
3230 memcpy(pMtx->data(), illuminant, illuminantRange.steps*sizeof(icFloatNumber));
3231 }
3232
3233 CIccPcsStepPtr ptr;
3234 ptr.ptr = pMtx;
3235 m_list->push_back(ptr);
3236
3237 }
3238 else {
3239 CIccPcsStepSrcMatrix *pMtx = new CIccPcsStepSrcMatrix(pProfile->m_Header.spectralRange.steps, pProfile->m_Header.biSpectralRange.steps);
3240 if (!pMtx)
3241 return icCmmStatAllocErr;
3242
3243 CIccPcsStepMatrix *illumMtx = rangeMap(illuminantRange, pProfile->m_Header.biSpectralRange);
3244 if (illumMtx) {
3245 illumMtx->Apply(NULL, pMtx->data(), illuminant);
3246 delete illumMtx;
3247 }
3248 else {
3249 memcpy(pMtx->data(), illuminant, illuminantRange.steps*sizeof(icFloatNumber));
3250 }
3251
3252 CIccPcsStepPtr ptr;
3253 ptr.ptr = pMtx;
3254 m_list->push_back(ptr);
3255
3256 }
3257 }
3258
3259 return icCmmStatOk;
3260}
3261
3262
3274icStatusCMM CIccPcsXform::pushBiRef2Xyz(CIccProfile *pProfile, IIccProfileConnectionConditions *pPcc)
3275{
3276 icStatusCMM stat = pushBiRef2Rad(pProfile, pPcc);
3277 if (stat!=icCmmStatOk)
3278 return stat;
3279
3281
3282 if (pView) {
3283 icSpectralRange observerRange;
3284 const icFloatNumber *observer = pView->getObserver(observerRange);
3285
3286 pushSpecToRange(pProfile->m_Header.spectralRange, observerRange);
3287 pushMatrix(3, observerRange.steps, observer);
3288 pushXYZNormalize(pPcc, pProfile->m_Header.biSpectralRange, pProfile->m_Header.spectralRange);
3289 }
3290 else {
3292 }
3293
3294 return icCmmStatOk;
3295}
3296
3297
3308icStatusCMM CIccPcsXform::pushBiRef2Ref(CIccProfile *pProfile, IIccProfileConnectionConditions *pPcc)
3309{
3310 icStatusCMM stat = pushBiRef2Rad(pProfile, pPcc);
3311 if (stat!=icCmmStatOk)
3312 return stat;
3313
3315
3316 if (pView) {
3317 icSpectralRange illuminantRange;
3318 const icFloatNumber *illuminant = pView->getIlluminant(illuminantRange);
3319
3320 CIccPcsStepScale *pScale = new CIccPcsStepScale(pProfile->m_Header.spectralRange.steps);
3321
3322 if (pScale) {
3323 icFloatNumber *pData = pScale->data();
3324 CIccPcsStepMatrix *illumMtx = rangeMap(illuminantRange, pProfile->m_Header.spectralRange);
3325 int i;
3326
3327 if (illumMtx) {
3328 illumMtx->Apply(NULL, pData, illuminant);
3329 for (i=0; i<pProfile->m_Header.spectralRange.steps; i++)
3330 pData[i] = 1.0f / pData[i];
3331
3332 delete illumMtx;
3333
3334 }
3335 else {
3336 for (i=0; i<pProfile->m_Header.spectralRange.steps; i++) {
3337 pData[i] = 1.0f / illuminant[i];
3338 }
3339 }
3340
3341 CIccPcsStepPtr ptr;
3342 ptr.ptr = pScale;
3343 m_list->push_back(ptr);
3344 }
3345 else
3346 return icCmmStatAllocErr;
3347 }
3348 else
3350
3351 return icCmmStatOk;
3352}
3353
3354
3355#ifdef _DEBUG
3356//#define DUMPCSSTEPRESULTS
3357#ifdef DUMPCSSTEPRESULTS
3358 #define ICCDUMPPIXEL(n, pix) \
3359 if ((n)<96) { \
3360 printf("["); \
3361 int i; \
3362 for (i=0; i<(n); i++) { \
3363 if (i && !(i%12)) \
3364 printf("...\n"); \
3365 printf(" %.5f", pix[i]); \
3366 } \
3367 printf("]\n"); \
3368 } \
3369 else { \
3370 printf("[ BigAray with %d elements]\n", (n)); \
3371 }
3372#else
3373 #define ICCDUMPPIXEL(n, pix)
3374#endif
3375#else
3376 #define ICCDUMPPIXEL(n, pix)
3377#endif
3378
3379
3388void CIccPcsXform::Apply(CIccApplyXform *pXform, icFloatNumber *DstPixel, const icFloatNumber *SrcPixel) const
3389{
3390 CIccApplyPcsXform *pApplyXform = (CIccApplyPcsXform*)pXform;
3391 CIccApplyPcsStepList *pList = pApplyXform->m_list;
3392
3393 ICCDUMPPIXEL(GetNumSrcSamples(), SrcPixel);
3394
3395 if (!pList) {
3396 memcpy(DstPixel, SrcPixel, GetNumSrcSamples()*sizeof(icFloatNumber));
3397 ICCDUMPPIXEL(GetNumSrcSamples(), DstPixel);
3398 return;
3399 }
3400
3401 CIccApplyPcsStepList::iterator s, n;
3402 s = n =pList->begin();
3403
3404 if (s==pList->end()) {
3405 memcpy(DstPixel, SrcPixel, GetNumSrcSamples()*sizeof(icFloatNumber));
3406 ICCDUMPPIXEL(GetNumSrcSamples(), DstPixel);
3407 return;
3408 }
3409
3410 n++;
3411
3412 if (n==pList->end()) {
3413 s->ptr->Apply(DstPixel, SrcPixel);
3414 ICCDUMPPIXEL(s->ptr->GetStep()->GetDstChannels(), DstPixel);
3415 }
3416 else {
3417 const icFloatNumber *src = SrcPixel;
3418 icFloatNumber *p1 = pApplyXform->m_temp1;
3419 icFloatNumber *p2 = pApplyXform->m_temp2;
3420 icFloatNumber *t;
3421
3422 for (;n!=pList->end(); s=n, n++) {
3423 s->ptr->Apply(p1, src);
3424 ICCDUMPPIXEL(s->ptr->GetStep()->GetDstChannels(), p1);
3425 src=p1;
3426 t=p1; p1=p2; p2=t;
3427 }
3428 s->ptr->Apply(DstPixel, src);
3429 ICCDUMPPIXEL(s->ptr->GetStep()->GetDstChannels(), DstPixel);
3430 }
3431}
3432
3441CIccApplyPcsStep* CIccPcsStep::GetNewApply()
3442{
3443 return new CIccApplyPcsStep(this);
3444}
3445
3446
3455void CIccPcsStepIdentity::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
3456{
3457 if (pDst != pSrc)
3458 memcpy(pDst, pSrc, m_nChannels*sizeof(icFloatNumber));
3459}
3460
3461
3470void CIccPcsStepIdentity::dump(std::string &str) const
3471{
3472 str += "\nCIccPcsStepIdentity\n\n";
3473}
3474
3475
3484CIccPcsStepRouteMcs::CIccPcsStepRouteMcs(CIccTagArray *pSrcChannels, CIccTagArray *pDstChannels, CIccTagNumArray *pDefaults)
3485{
3486 m_nSrcChannels = (icUInt16Number)pSrcChannels->GetSize();
3487 m_nDstChannels = (icUInt16Number)pDstChannels->GetSize();
3488 m_Index = new int[m_nDstChannels];
3489 m_Defaults = new icFloatNumber[m_nDstChannels];
3490
3491 memset(m_Defaults, 0, m_nDstChannels*sizeof(icFloatNumber));
3492
3493 if (pDefaults) {
3494 pDefaults->GetValues(m_Defaults, 0, m_nDstChannels);
3495 }
3496
3497 int i, j;
3498 char *szSrc;
3499
3500 for (i=0; i<m_nDstChannels; i++) {
3501 const icUChar *szDstChan = ((CIccTagUtf8Text*)(pDstChannels->GetIndex(i)))->GetText();
3502 for (j=0; j<m_nSrcChannels; j++) {
3503 const icUChar *szSrcChan = ((CIccTagUtf8Text*)(pSrcChannels->GetIndex(j)))->GetText();
3504 szSrc = (char*)szSrcChan;
3505 if (!icUtf8StrCmp(szDstChan, szSrcChan))
3506 break;
3507 }
3508 if (j==m_nSrcChannels) {
3509 m_Index[i] = -1;
3510 }
3511 else {
3512 m_Index[i] = j;
3513 }
3514 //printf("%d - %d %s\n", m_Index[i], i, szDstChan);
3515 }
3516}
3517
3518
3527CIccPcsStepRouteMcs::~CIccPcsStepRouteMcs()
3528{
3529 if (m_Index)
3530 delete [] m_Index;
3531 if (m_Defaults)
3532 delete [] m_Defaults;
3533}
3534
3535
3544bool CIccPcsStepRouteMcs::isIdentity() const
3545{
3546 if (m_nSrcChannels!=m_nDstChannels)
3547 return false;
3548
3549 int i;
3550 for (i=0; i<m_nDstChannels; i++) {
3551 if (m_Index[i]!=i)
3552 return false;
3553 }
3554
3555 return true;
3556}
3557
3558
3559
3568void CIccPcsStepRouteMcs::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
3569{
3570 if (pDst != pSrc) {
3571 int i;
3572 for (i=0; i<m_nDstChannels; i++) {
3573 if (m_Index[i]>=0)
3574 pDst[i] = pSrc[m_Index[i]];
3575 else
3576 pDst[i] = m_Defaults[i];
3577 }
3578 }
3579}
3580
3581
3590void CIccPcsStepRouteMcs::dump(std::string &str) const
3591{
3592 str += "\nCIccPcsStepRouteMcs\n\n";
3593}
3594
3595extern icFloatNumber icD50XYZ[3];
3596
3605bool CIccPcsLabStep::isSameWhite(const icFloatNumber *xyzWhite)
3606{
3607 return (m_xyzWhite[0]==xyzWhite[0] &&
3608 m_xyzWhite[1]==xyzWhite[1] &&
3609 m_xyzWhite[2]==xyzWhite[2]);
3610}
3611
3612
3613
3622CIccPcsStepLabToXYZ::CIccPcsStepLabToXYZ(const icFloatNumber *xyzWhite/*=NULL*/)
3623{
3624 if (xyzWhite) {
3625 memcpy(m_xyzWhite, xyzWhite, sizeof(m_xyzWhite));
3626 }
3627 else {
3628 memcpy(m_xyzWhite, icD50XYZ, sizeof(m_xyzWhite));
3629 }
3630}
3631
3632
3641void CIccPcsStepLabToXYZ::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
3642{
3643 icFloatNumber Lab[3];
3644
3645 //lab4 to XYZ
3646 Lab[0] = pSrc[0] * 100.0f;
3647 Lab[1] = (icFloatNumber)(pSrc[1]*255.0f - 128.0f);
3648 Lab[2] = (icFloatNumber)(pSrc[2]*255.0f - 128.0f);
3649
3650 icLabtoXYZ(pDst, Lab, m_xyzWhite);
3651}
3652
3653
3662void CIccPcsStepLabToXYZ::dump(std::string &str) const
3663{
3664 str += "\nCIccPcsStepLabToXYZ\n\n";
3665}
3666
3667
3678CIccPcsStep *CIccPcsStepLabToXYZ::concat(CIccPcsStep *pNext) const
3679{
3680 if (pNext) {
3681 if (pNext->GetType() == icPcsStepXYZToLab) {
3682 CIccPcsLabStep* pStep = (CIccPcsLabStep*)pNext;
3683 if (pStep->isSameWhite(m_xyzWhite))
3684 return new CIccPcsStepIdentity(3);
3685 }
3686 else if (pNext->GetType() == icPcsStepXYZToLab2) {
3687 CIccPcsLabStep* pStep = (CIccPcsLabStep*)pNext;
3688 if (pStep->isSameWhite(m_xyzWhite))
3689 return new CIccPcsStepLabToLab2();
3690 }
3691 }
3692 return NULL;
3693}
3694
3695
3704CIccPcsStepXYZToLab::CIccPcsStepXYZToLab(const icFloatNumber *xyzWhite/*=NULL*/)
3705{
3706 if (xyzWhite) {
3707 memcpy(m_xyzWhite, xyzWhite, sizeof(m_xyzWhite));
3708 }
3709 else {
3710 memcpy(m_xyzWhite, icD50XYZ, sizeof(m_xyzWhite));
3711 }
3712}
3713
3714
3723void CIccPcsStepXYZToLab::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
3724{
3725 icFloatNumber Lab[3];
3726 icXYZtoLab(Lab, (icFloatNumber*)pSrc, m_xyzWhite);
3727 //lab4 from XYZ
3728 pDst[0] = Lab[0] / 100.0f;
3729 pDst[1] = (icFloatNumber)((Lab[1] + 128.0f) / 255.0f);
3730 pDst[2] = (icFloatNumber)((Lab[2] + 128.0f) / 255.0f);
3731}
3732
3733
3742void CIccPcsStepXYZToLab::dump(std::string &str) const
3743{
3744 str += "\nCIccPcsStepXYZToLab\n\n";
3745}
3746
3747
3758CIccPcsStep *CIccPcsStepXYZToLab::concat(CIccPcsStep *pNext) const
3759{
3760 if (pNext && pNext->GetType()==icPcsStepLabToXYZ) {
3761 CIccPcsLabStep *pStep = (CIccPcsLabStep *)pNext;
3762 if (pStep->isSameWhite(m_xyzWhite))
3763 return new CIccPcsStepIdentity(3);
3764 }
3765 return NULL;
3766}
3767
3768
3777CIccPcsStepLab2ToXYZ::CIccPcsStepLab2ToXYZ(const icFloatNumber *xyzWhite/*=NULL*/)
3778{
3779 if (xyzWhite) {
3780 memcpy(m_xyzWhite, xyzWhite, sizeof(m_xyzWhite));
3781 }
3782 else {
3783 memcpy(m_xyzWhite, icD50XYZ, sizeof(m_xyzWhite));
3784 }
3785}
3786
3795void CIccPcsStepLab2ToXYZ::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
3796{
3797 icFloatNumber Lab[3];
3798
3799 //lab2 to XYZ
3800 Lab[0] = pSrc[0] * (65535.0f / 65280.0f) * 100.0f;
3801 Lab[1] = (icFloatNumber)(pSrc[1] * 65535.0f / 65280.0f * 255.0f - 128.0f);
3802 Lab[2] = (icFloatNumber)(pSrc[2] * 65535.0f / 65280.0f * 255.0f - 128.0f);
3803
3804 icLabtoXYZ(pDst, Lab, m_xyzWhite);
3805}
3806
3807
3816void CIccPcsStepLab2ToXYZ::dump(std::string &str) const
3817{
3818 str += "\nCIccPcsStepLab2ToXYZ\n\n";
3819}
3820
3821
3832CIccPcsStep *CIccPcsStepLab2ToXYZ::concat(CIccPcsStep *pNext) const
3833{
3834 if (pNext) {
3835 if (pNext->GetType() == icPcsStepXYZToLab2) {
3836 CIccPcsLabStep* pStep = (CIccPcsLabStep*)pNext;
3837 if (pStep->isSameWhite(m_xyzWhite))
3838 return new CIccPcsStepIdentity(3);
3839 }
3840 else if (pNext->GetType() == icPcsStepXYZToLab) {
3841 CIccPcsLabStep* pStep = (CIccPcsLabStep*)pNext;
3842 if (pStep->isSameWhite(m_xyzWhite))
3843 return new CIccPcsStepLab2ToLab();
3844 }
3845 }
3846
3847 return NULL;
3848}
3849
3850
3859CIccPcsStepXYZToLab2::CIccPcsStepXYZToLab2(const icFloatNumber *xyzWhite/*=NULL*/)
3860{
3861 if (xyzWhite) {
3862 memcpy(m_xyzWhite, xyzWhite, sizeof(m_xyzWhite));
3863 }
3864 else {
3865 memcpy(m_xyzWhite, icD50XYZ, sizeof(m_xyzWhite));
3866 }
3867}
3868
3869
3878void CIccPcsStepXYZToLab2::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
3879{
3880 icFloatNumber Lab[3];
3881 icXYZtoLab(Lab, (icFloatNumber*)pSrc, m_xyzWhite);
3882 //lab2 from XYZ
3883 pDst[0] = (Lab[0] / 100.0f) * (65280.0f / 65535.0f);
3884 pDst[1] = (icFloatNumber)((Lab[1] + 128.0f) / 255.0f) * (65280.0f / 65535.0f);
3885 pDst[2] = (icFloatNumber)((Lab[2] + 128.0f) / 255.0f) * (65280.0f / 65535.0f);
3886}
3887
3888
3897void CIccPcsStepXYZToLab2::dump(std::string &str) const
3898{
3899 str += "\nCIccPcsStepXYZToLab2\n\n";
3900}
3901
3902
3913CIccPcsStep *CIccPcsStepXYZToLab2::concat(CIccPcsStep *pNext) const
3914{
3915 if (pNext && pNext->GetType()==icPcsStepLab2ToXYZ) {
3916 CIccPcsLabStep *pStep = (CIccPcsLabStep *)pNext;
3917 if (pStep->isSameWhite(m_xyzWhite))
3918 return new CIccPcsStepIdentity(3);
3919 }
3920 return NULL;
3921}
3922
3923
3932void CIccPcsStepLabToLab2::Apply(CIccApplyPcsStep* pApply, icFloatNumber* pDst, const icFloatNumber* pSrc) const
3933{
3934 pDst[0] = (icFloatNumber)(pSrc[0] * 65280.0f / 65535.0f);
3935 pDst[1] = (icFloatNumber)(pSrc[1] * 65280.0f / 65535.0f);
3936 pDst[2] = (icFloatNumber)(pSrc[2] * 65280.0f / 65535.0f);
3937}
3938
3939
3948void CIccPcsStepLabToLab2::dump(std::string& str) const
3949{
3950 str += "\nCIccPcsStepLabToLab2\n\n";
3951}
3952
3963CIccPcsStep* CIccPcsStepLabToLab2::concat(CIccPcsStep* pNext) const
3964{
3965 if (pNext && pNext->GetType() == icPcsStepLab2ToLab) {
3966 return new CIccPcsStepIdentity(3);
3967 }
3968 return NULL;
3969}
3970
3971
3980void CIccPcsStepLab2ToLab::Apply(CIccApplyPcsStep* pApply, icFloatNumber* pDst, const icFloatNumber* pSrc) const
3981{
3982 pDst[0] = (icFloatNumber)(pSrc[0] * 65535.0f / 65280.0f);
3983 pDst[1] = (icFloatNumber)(pSrc[1] * 65535.0f / 65280.0f);
3984 pDst[2] = (icFloatNumber)(pSrc[2] * 65535.0f / 65280.0f);
3985}
3986
3987
3996void CIccPcsStepLab2ToLab::dump(std::string& str) const
3997{
3998 str += "\nCIccPcsStepLab2ToLab\n\n";
3999}
4000
4001
4012CIccPcsStep* CIccPcsStepLab2ToLab::concat(CIccPcsStep* pNext) const
4013{
4014 if (pNext && pNext->GetType() == icPcsStepLabToLab2) {
4015 return new CIccPcsStepIdentity(3);
4016 }
4017 return NULL;
4018}
4019
4020
4029CIccPcsStepOffset::CIccPcsStepOffset(icUInt16Number nChannels)
4030{
4031 m_nChannels = nChannels;
4032 m_vals = new icFloatNumber[nChannels];
4033}
4034
4035
4044CIccPcsStepOffset::~CIccPcsStepOffset()
4045{
4046 if (m_vals)
4047 delete [] m_vals;
4048}
4049
4050
4059void CIccPcsStepOffset::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
4060{
4061 if (m_nChannels==3) {
4062 pDst[0] = m_vals[0] + pSrc[0];
4063 pDst[1] = m_vals[1] + pSrc[1];
4064 pDst[2] = m_vals[2] + pSrc[2];
4065 }
4066 else {
4067 int i;
4068 for (i=0; i<m_nChannels; i++) {
4069 pDst[i] = m_vals[i] + pSrc[i];
4070 }
4071 }
4072}
4073
4074
4083void CIccPcsStepOffset::dump(std::string &str) const
4084{
4085 str += "\nCIccPcsStepOffset\n\n";
4086 char buf[80];
4087 for (int i=0; i<m_nChannels; i++) {
4088 sprintf(buf, ICCPCSSTEPDUMPFMT, m_vals[i]);
4089 str += buf;
4090 }
4091 str +="\n";
4092}
4093
4094
4104CIccPcsStepOffset *CIccPcsStepOffset::Add(const CIccPcsStepOffset *offset) const
4105{
4106 if (offset->m_nChannels != m_nChannels)
4107 return NULL;
4108
4109 CIccPcsStepOffset *pNew = new CIccPcsStepOffset(m_nChannels);
4110
4111 if (pNew) {
4112 int i;
4113 for (i=0; i<m_nChannels; i++) {
4114 pNew->m_vals[i] = m_vals[i] + offset->m_vals[i];
4115 }
4116 }
4117
4118 return pNew;
4119}
4120
4131CIccPcsStep *CIccPcsStepOffset::concat(CIccPcsStep *pNext) const
4132{
4133 if (pNext && pNext->GetType()==icPcsStepOffset && m_nChannels==pNext->GetSrcChannels())
4134 return Add((const CIccPcsStepOffset*)pNext);
4135
4136 return NULL;
4137}
4138
4139
4148bool CIccPcsStepOffset::isIdentity() const
4149{
4150 int i;
4151 for (i=0; i<m_nChannels; i++) {
4152 if (m_vals[i]<-icNearRange || m_vals[i]>icNearRange)
4153 return false;
4154 }
4155
4156 return true;
4157}
4158
4159
4168CIccPcsStepScale::CIccPcsStepScale(icUInt16Number nChannels)
4169{
4170 m_nChannels = nChannels;
4171 m_vals = new icFloatNumber[nChannels];
4172}
4173
4174
4183CIccPcsStepScale::~CIccPcsStepScale()
4184{
4185 if (m_vals)
4186 delete [] m_vals;
4187}
4188
4197void CIccPcsStepScale::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
4198{
4199 if (m_nChannels==3) {
4200 pDst[0] = m_vals[0] * pSrc[0];
4201 pDst[1] = m_vals[1] * pSrc[1];
4202 pDst[2] = m_vals[2] * pSrc[2];
4203 }
4204 else {
4205 int i;
4206 for (i=0; i<m_nChannels; i++) {
4207 pDst[i] = m_vals[i] * pSrc[i];
4208 }
4209 }
4210}
4211
4212
4221void CIccPcsStepScale::dump(std::string &str) const
4222{
4223 str += "\nCIccPcsStepScale\n\n";
4224 char buf[80];
4225 for (int i=0; i<m_nChannels; i++) {
4226 sprintf(buf, ICCPCSSTEPDUMPFMT, m_vals[i]);
4227 str += buf;
4228 }
4229 str +="\n";
4230}
4231
4232
4242CIccPcsStepScale *CIccPcsStepScale::Mult(const CIccPcsStepScale *scale) const
4243{
4244 if (scale->m_nChannels != m_nChannels)
4245 return NULL;
4246
4247 CIccPcsStepScale *pNew = new CIccPcsStepScale(m_nChannels);
4248
4249 if (pNew) {
4250 int i;
4251 for (i=0; i<m_nChannels; i++) {
4252 pNew->m_vals[i] = m_vals[i] * scale->m_vals[i];
4253 }
4254 }
4255 return pNew;
4256}
4257
4267CIccPcsStepMatrix *CIccPcsStepScale::Mult(const CIccPcsStepMatrix *matrix) const
4268{
4269 if (matrix->GetSrcChannels() != m_nChannels)
4270 return NULL;
4271
4272 CIccPcsStepMatrix *pNew = new CIccPcsStepMatrix(matrix->GetDstChannels(), matrix->GetSrcChannels());
4273
4274 if (pNew) {
4275 int i, j;
4276 for (j=0; j<matrix->GetDstChannels(); j++) {
4277 const icFloatNumber *row = matrix->entry(j);
4278 icFloatNumber *to=pNew->entry(j);
4279
4280 for (i=0; i<m_nChannels; i++) {
4281 to[i] = m_vals[i] * row[i];
4282 }
4283 }
4284 }
4285
4286 return pNew;
4287}
4288
4298CIccPcsStepMatrix *CIccPcsStepScale::Mult(const CIccMpeMatrix *matrix) const
4299{
4300 if (matrix->NumInputChannels() != m_nChannels)
4301 return NULL;
4302
4303 CIccPcsStepMatrix *pNew = new CIccPcsStepMatrix(matrix->NumOutputChannels(), matrix->NumInputChannels());
4304
4305 if (pNew) {
4306 int i, j;
4307 icFloatNumber *mtx = matrix->GetMatrix();
4308 for (j = 0; j < matrix->NumOutputChannels(); j++) {
4309 const icFloatNumber *row = &mtx[j*matrix->NumInputChannels()];
4310 icFloatNumber *to = pNew->entry(j);
4311
4312 for (i = 0; i < m_nChannels; i++) {
4313 to[i] = m_vals[i] * row[i];
4314 }
4315 }
4316 }
4317
4318 return pNew;
4319}
4320
4321
4332CIccPcsStep *CIccPcsStepScale::concat(CIccPcsStep *pNext) const
4333{
4334 if (pNext) {
4335 if (pNext->GetType()==icPcsStepScale && m_nChannels==pNext->GetSrcChannels())
4336 return Mult((const CIccPcsStepScale*)pNext);
4337 if (pNext->GetType()==icPcsStepMatrix && m_nChannels==pNext->GetSrcChannels())
4338 return Mult((const CIccPcsStepMatrix*)pNext);
4339 if (pNext->GetType() == icPcsStepMpe && m_nChannels == pNext->GetSrcChannels()) {
4340 CIccPcsStepMpe *pMpe = (CIccPcsStepMpe*)pNext;
4341 CIccMpeMatrix *pMatrix = pMpe->GetMatrix();
4342 if (pMatrix)
4343 return Mult(pMatrix);
4344 }
4345 }
4346
4347 return NULL;
4348}
4349
4350
4359bool CIccPcsStepScale::isIdentity() const
4360{
4361 int i;
4362 for (i=0; i<m_nChannels; i++) {
4363 if (m_vals[i]<1.0f-icNearRange || m_vals[i]>1.0f+icNearRange)
4364 return false;
4365 }
4366
4367 return true;
4368}
4369
4370
4371
4380void CIccPcsStepMatrix::dump(std::string &str) const
4381{
4382 str += "\nCIccPcsStepMatrix\n\n";
4383 dumpMtx(str);
4384}
4385
4386
4396CIccPcsStepMatrix *CIccPcsStepMatrix::Mult(const CIccPcsStepScale *scale) const
4397{
4398 icUInt16Number mCols = scale->GetSrcChannels();
4399 icUInt16Number mRows = mCols;
4400
4401 if (m_nRows != mCols)
4402 return NULL;
4403
4404 CIccPcsStepMatrix *pNew = new CIccPcsStepMatrix(m_nRows, m_nCols);
4405 const icFloatNumber *data = scale->data();
4406
4407 int i, j;
4408 for (j=0; j<m_nRows; j++) {
4409 const icFloatNumber *row = entry(j);
4410 icFloatNumber *to = pNew->entry(j);
4411 for (i=0; i<m_nCols; i++) {
4412 to[i] = data[j] * row[i];
4413 }
4414 }
4415
4416 return pNew;
4417}
4418
4428CIccPcsStepMatrix *CIccPcsStepMatrix::Mult(const CIccPcsStepMatrix *matrix) const
4429{
4430 icUInt16Number mCols = matrix->m_nCols;
4431 icUInt16Number mRows = matrix->m_nRows;
4432
4433 if (m_nRows != mCols)
4434 return NULL;
4435
4436 CIccPcsStepMatrix *pNew = new CIccPcsStepMatrix(mRows, m_nCols);
4437
4438 int i, j, k;
4439 for (j=0; j<mRows; j++) {
4440 const icFloatNumber *row = matrix->entry(j);
4441 for (i=0; i<m_nCols; i++) {
4442 icFloatNumber *to = pNew->entry(j, i);
4443 const icFloatNumber *from = entry(0, i);
4444
4445 *to = 0.0f;
4446 for (k=0; k<m_nRows; k++) {
4447 *to += row[k] * (*from);
4448 from += m_nCols;
4449 }
4450 }
4451 }
4452
4453 return pNew;
4454}
4455
4456
4467CIccPcsStep *CIccPcsStepMatrix::concat(CIccPcsStep *pNext) const
4468{
4469 if (pNext) {
4470 if (pNext->GetType()==icPcsStepScale && GetDstChannels()==pNext->GetSrcChannels())
4471 return Mult((const CIccPcsStepScale*)pNext);
4472 if (pNext->GetType()==icPcsStepMatrix && GetDstChannels()==pNext->GetSrcChannels())
4473 return Mult((const CIccPcsStepMatrix*)pNext);
4474 }
4475
4476 return NULL;
4477}
4478
4489CIccPcsStep *CIccPcsStepMatrix::reduce() const
4490{
4491 int nVals = m_nRows*m_nCols;
4492 int nNonZeros = 0;
4493 int i;
4494
4495 for (i=0; i<nVals; i++) {
4496 icFloatNumber v = m_vals[i];
4497 if (icNotZero(v))
4498 nNonZeros++;
4499 }
4500 if (nNonZeros<nVals*3/4) {
4501 icUInt32Number nMatrixBytes = CIccSparseMatrix::MemSize(nNonZeros, m_nRows, sizeof(icFloatNumber))+4*sizeof(icFloatNumber);
4502 CIccPcsStepSparseMatrix *pMtx = new CIccPcsStepSparseMatrix(m_nRows, m_nCols, nMatrixBytes);
4503 CIccSparseMatrix mtx(pMtx->data(), nMatrixBytes);
4504 mtx.Init(m_nRows, m_nCols, true);
4505 mtx.FillFromFullMatrix(m_vals);
4506 return pMtx;
4507 }
4508
4509 return (CIccPcsStep*)this;
4510}
4511
4512
4513
4522CIccPcsStepMpe::CIccPcsStepMpe(CIccTagMultiProcessElement *pMpe)
4523{
4524 m_pMpe = pMpe;
4525}
4526
4527
4536CIccPcsStepMpe::~CIccPcsStepMpe()
4537{
4538 if (m_pMpe)
4539 delete m_pMpe;
4540}
4541
4542
4551CIccApplyPcsStep* CIccPcsStepMpe::GetNewApply()
4552{
4553 CIccApplyPcsStepMpe *rv = new CIccApplyPcsStepMpe(this, m_pMpe->GetNewApply());
4554
4555 return rv;
4556}
4557
4558
4567void CIccPcsStepMpe::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
4568{
4569 CIccApplyPcsStepMpe *pMpeApply = (CIccApplyPcsStepMpe*)pApply;
4570
4571 m_pMpe->Apply(pMpeApply->m_pApply, pDst, pSrc);
4572}
4573
4574
4583void CIccPcsStepMpe::dump(std::string &str) const
4584{
4585 str += "\nCIccPcsStepMpe\n\n";
4586 m_pMpe->Describe(str, 100); // TODO propogate nVerboseness
4587}
4588
4589
4598bool CIccPcsStepMpe::isIdentity() const
4599{
4600 if (!m_pMpe || !m_pMpe->NumElements())
4601 return true;
4602 return false;
4603}
4604
4614icUInt16Number CIccPcsStepMpe::GetSrcChannels() const
4615{
4616 return m_pMpe->NumInputChannels();
4617}
4618
4619
4629icUInt16Number CIccPcsStepMpe::GetDstChannels() const
4630{
4631 return m_pMpe->NumOutputChannels();
4632}
4633
4634
4644CIccMpeMatrix *CIccPcsStepMpe::GetMatrix() const
4645{
4646 //Must be single element
4647 if (m_pMpe->NumElements() == 1) {
4648 CIccMultiProcessElement *pElem = m_pMpe->GetElement(0);
4649 //Must be a matrix
4650 if (pElem && pElem->GetType() == icSigMatrixElemType) {
4651 CIccMpeMatrix *pMtx = (CIccMpeMatrix*)pElem;
4652
4653 //Should not apply any constants
4654 if (!pMtx->GetConstants() || !pMtx->GetApplyConstants())
4655 return pMtx;
4656 }
4657 }
4658
4659 return NULL;
4660}
4661
4662
4663
4664
4674bool CIccPcsStepMpe::Begin()
4675{
4676 return m_pMpe->Begin();
4677}
4678
4679
4688CIccPcsStepSrcMatrix::CIccPcsStepSrcMatrix(icUInt16Number nRows, icUInt16Number nCols)
4689{
4690 m_nRows = nRows;
4691 m_nCols = nCols;
4692 m_vals = new icFloatNumber[nCols];
4693}
4694
4695
4704CIccPcsStepSrcMatrix::~CIccPcsStepSrcMatrix()
4705{
4706 if (m_vals)
4707 delete m_vals;
4708}
4709
4710
4720void CIccPcsStepSrcMatrix::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
4721{
4722 int i, j;
4723 const icFloatNumber *row = pSrc;
4724 for (j=0; j<m_nRows; j++) {
4725 pDst[j] = 0.0f;
4726 for (i=0; i<m_nCols; i++) {
4727 pDst[j] += row[i] * m_vals[i];
4728 }
4729 row += m_nCols;
4730 }
4731}
4732
4733
4742void CIccPcsStepSrcMatrix::dump(std::string &str) const
4743{
4744 str += "\nCIccPcsStepSrcMatrix\n\n";
4745 char buf[80];
4746 for (int i=0; i<m_nCols; i++) {
4747 sprintf(buf, ICCPCSSTEPDUMPFMT, m_vals[i]);
4748 str += buf;
4749 }
4750 str += "\n";
4751}
4752
4753
4762CIccPcsStepSparseMatrix::CIccPcsStepSparseMatrix(icUInt16Number nRows, icUInt16Number nCols, icUInt32Number nBytesPerMatrix)
4763{
4764 m_nRows = nRows;
4765 m_nCols = nCols;
4766 m_nBytesPerMatrix = nBytesPerMatrix;
4767 m_nChannels = 0;
4768 m_vals = new icFloatNumber[m_nBytesPerMatrix/sizeof(icFloatNumber)];
4769}
4770
4771
4780CIccPcsStepSparseMatrix::~CIccPcsStepSparseMatrix()
4781{
4782 if (m_vals)
4783 delete [] m_vals;
4784}
4785
4786
4796void CIccPcsStepSparseMatrix::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
4797{
4798 CIccSparseMatrix mtx((icUInt8Number*)m_vals, m_nBytesPerMatrix, icSparseMatrixFloatNum, true);
4799
4800 mtx.MultiplyVector(pDst, pSrc);
4801}
4802
4803
4812void CIccPcsStepSparseMatrix::dump(std::string &str) const
4813{
4814 str += "\nCIccPcsStepSparseMatrix\n\n";
4815// char buf[80];
4816// for (int i=0; i<m_nCols; i++) {
4817// sprintf(buf, ICCPCSSTEPDUMPFMT, m_vals[i]);
4818// str += buf;
4819// }
4820// str += "\n";
4821}
4822
4823
4832CIccPcsStepSrcSparseMatrix::CIccPcsStepSrcSparseMatrix(icUInt16Number nRows, icUInt16Number nCols, icUInt16Number nChannels)
4833{
4834 m_nRows = nRows;
4835 m_nCols = nCols;
4836 m_nChannels = nChannels;
4837 m_nBytesPerMatrix = nChannels * sizeof(icFloatNumber);
4838
4839 m_vals = new icFloatNumber[nCols];
4840}
4841
4842
4851CIccPcsStepSrcSparseMatrix::~CIccPcsStepSrcSparseMatrix()
4852{
4853 if (m_vals)
4854 delete [] m_vals;
4855}
4856
4857
4867void CIccPcsStepSrcSparseMatrix::Apply(CIccApplyPcsStep *pApply, icFloatNumber *pDst, const icFloatNumber *pSrc) const
4868{
4869 CIccSparseMatrix mtx((icUInt8Number*)pSrc, m_nBytesPerMatrix, icSparseMatrixFloatNum, true);
4870
4871 mtx.MultiplyVector(pDst, m_vals);
4872}
4873
4874
4883void CIccPcsStepSrcSparseMatrix::dump(std::string &str) const
4884{
4885 str += "\nCIccPcsStepSrcSparseMatrix\n\n";
4886 char buf[80];
4887 for (int i=0; i<m_nCols; i++) {
4888 sprintf(buf, ICCPCSSTEPDUMPFMT, m_vals[i]);
4889 str += buf;
4890 }
4891 str += "\n";
4892}
4893
4894
4903CIccXformMonochrome::CIccXformMonochrome()
4904{
4905 m_Curve = NULL;
4906 m_ApplyCurvePtr = NULL;
4907 m_bFreeCurve = false;
4908}
4909
4918CIccXformMonochrome::~CIccXformMonochrome()
4919{
4920 if (m_bFreeCurve && m_Curve) {
4921 delete m_Curve;
4922 }
4923}
4924
4935icStatusCMM CIccXformMonochrome::Begin()
4936{
4937 icStatusCMM status;
4938
4939 status = CIccXform::Begin();
4940 if (status != icCmmStatOk)
4941 return status;
4942
4943 m_ApplyCurvePtr = NULL;
4944
4945 if (m_bInput) {
4946 m_Curve = GetCurve(icSigGrayTRCTag);
4947
4948 if (!m_Curve) {
4950 }
4951 }
4952 else {
4953 m_Curve = GetInvCurve(icSigGrayTRCTag);
4954 m_bFreeCurve = true;
4955
4956 if (!m_Curve) {
4958 }
4959 }
4960
4961 m_Curve->Begin();
4962 if (!m_Curve->IsIdentity()) {
4963 m_ApplyCurvePtr = m_Curve;
4964 }
4965
4966 return icCmmStatOk;
4967}
4968
4982void CIccXformMonochrome::Apply(CIccApplyXform* pApply, icFloatNumber *DstPixel, const icFloatNumber *SrcPixel) const
4983{
4984 icFloatNumber Pixel[3];
4985
4986 if (m_bSrcPcsConversion)
4987 SrcPixel = CheckSrcAbs(pApply, SrcPixel);
4988
4989 if (m_bInput) {
4990 Pixel[0] = SrcPixel[0];
4991
4992 if (m_ApplyCurvePtr) {
4993 Pixel[0] = m_ApplyCurvePtr->Apply(Pixel[0]);
4994 }
4995
4996 DstPixel[0] = icFloatNumber(icPerceptualRefWhiteX);
4997 DstPixel[1] = icFloatNumber(icPerceptualRefWhiteY);
4998 DstPixel[2] = icFloatNumber(icPerceptualRefWhiteZ);
4999
5000 icXyzToPcs(DstPixel);
5001
5002 if (m_pProfile->m_Header.pcs==icSigLabData) {
5003 if (UseLegacyPCS()) {
5004 CIccPCSUtil::XyzToLab2(DstPixel, DstPixel, true);
5005 }
5006 else {
5007 CIccPCSUtil::XyzToLab(DstPixel, DstPixel, true);
5008 }
5009 }
5010
5011 DstPixel[0] *= Pixel[0];
5012 DstPixel[1] *= Pixel[0];
5013 DstPixel[2] *= Pixel[0];
5014 }
5015 else {
5019
5020 icXyzToPcs(Pixel);
5021
5022 if (m_pProfile->m_Header.pcs==icSigLabData) {
5023 if (UseLegacyPCS()) {
5024 CIccPCSUtil::XyzToLab2(Pixel, Pixel, true);
5025 }
5026 else {
5027 CIccPCSUtil::XyzToLab(Pixel, Pixel, true);
5028 }
5029 DstPixel[0] = SrcPixel[0]/Pixel[0];
5030 }
5031 else {
5032 DstPixel[0] = SrcPixel[1]/Pixel[1];
5033 }
5034
5035 if (m_ApplyCurvePtr) {
5036 DstPixel[0] = m_ApplyCurvePtr->Apply(DstPixel[0]);
5037 }
5038 }
5039
5040 if (m_bDstPcsConversion)
5041 CheckDstAbs(DstPixel);
5042}
5043
5058CIccCurve *CIccXformMonochrome::GetCurve(icSignature sig) const
5059{
5060 CIccTag *pTag = m_pProfile->FindTag(sig);
5061
5062 if (pTag && (pTag->GetType()==icSigCurveType || pTag->GetType()==icSigParametricCurveType)) {
5063 return (CIccCurve*)pTag;
5064 }
5065
5066 return NULL;
5067}
5068
5083CIccCurve *CIccXformMonochrome::GetInvCurve(icSignature sig) const
5084{
5085 CIccCurve *pCurve;
5086 CIccTagCurve *pInvCurve;
5087
5088 if (!(pCurve = GetCurve(sig)))
5089 return NULL;
5090
5091 pCurve->Begin();
5092
5093 pInvCurve = new CIccTagCurve(2048);
5094
5095 int i;
5096 icFloatNumber x;
5097 icFloatNumber *Lut = &(*pInvCurve)[0];
5098
5099 for (i=0; i<2048; i++) {
5100 x=(icFloatNumber)i / 2047;
5101
5102 Lut[i] = pCurve->Find(x);
5103 }
5104
5105 return pInvCurve;
5106}
5107
5122LPIccCurve* CIccXformMonochrome::ExtractInputCurves()
5123{
5124 if (m_bInput) {
5125 if (m_Curve) {
5126 LPIccCurve* Curve = new LPIccCurve[1];
5127 Curve[0] = (LPIccCurve)(m_Curve->NewCopy());
5128 m_ApplyCurvePtr = NULL;
5129 return Curve;
5130 }
5131 }
5132
5133 return NULL;
5134}
5135
5150LPIccCurve* CIccXformMonochrome::ExtractOutputCurves()
5151{
5152 if (!m_bInput) {
5153 if (m_Curve) {
5154 LPIccCurve* Curve = new LPIccCurve[1];
5155 Curve[0] = (LPIccCurve)(m_Curve->NewCopy());
5156 m_ApplyCurvePtr = NULL;
5157 return Curve;
5158 }
5159 }
5160
5161 return NULL;
5162}
5163
5172CIccXformMatrixTRC::CIccXformMatrixTRC() : m_e{}
5173{
5174 m_Curve[0] = m_Curve[1] = m_Curve[2] = NULL;
5175 m_ApplyCurvePtr = NULL;
5176 m_bFreeCurve = false;
5177}
5178
5187CIccXformMatrixTRC::~CIccXformMatrixTRC()
5188{
5189 if (m_bFreeCurve) {
5190 if (m_Curve[0])
5191 delete m_Curve[0];
5192 if (m_Curve[1])
5193 delete m_Curve[1];
5194 if (m_Curve[2])
5195 delete m_Curve[2];
5196 }
5197}
5198
5209icStatusCMM CIccXformMatrixTRC::Begin()
5210{
5211 icStatusCMM status;
5212 const CIccTagXYZ *pXYZ;
5213
5214 status = CIccXform::Begin();
5215 if (status != icCmmStatOk)
5216 return status;
5217
5218 pXYZ = GetColumn(icSigRedMatrixColumnTag);
5219 if (!pXYZ) {
5221 }
5222
5223 m_e[0] = icFtoD((*pXYZ)[0].X);
5224 m_e[3] = icFtoD((*pXYZ)[0].Y);
5225 m_e[6] = icFtoD((*pXYZ)[0].Z);
5226
5227 pXYZ = GetColumn(icSigGreenMatrixColumnTag);
5228 if (!pXYZ) {
5230 }
5231
5232 m_e[1] = icFtoD((*pXYZ)[0].X);
5233 m_e[4] = icFtoD((*pXYZ)[0].Y);
5234 m_e[7] = icFtoD((*pXYZ)[0].Z);
5235
5236 pXYZ = GetColumn(icSigBlueMatrixColumnTag);
5237 if (!pXYZ) {
5239 }
5240
5241 m_e[2] = icFtoD((*pXYZ)[0].X);
5242 m_e[5] = icFtoD((*pXYZ)[0].Y);
5243 m_e[8] = icFtoD((*pXYZ)[0].Z);
5244
5245 m_ApplyCurvePtr = NULL;
5246
5247 if (m_bInput) {
5248 m_Curve[0] = GetCurve(icSigRedTRCTag);
5249 m_Curve[1] = GetCurve(icSigGreenTRCTag);
5250 m_Curve[2] = GetCurve(icSigBlueTRCTag);
5251
5252 if (!m_Curve[0] || !m_Curve[1] || !m_Curve[2]) {
5254 }
5255
5256 }
5257 else {
5258 if (m_pProfile->m_Header.pcs!=icSigXYZData) {
5259 return icCmmStatBadSpaceLink;
5260 }
5261
5262 m_Curve[0] = GetInvCurve(icSigRedTRCTag);
5263 m_Curve[1] = GetInvCurve(icSigGreenTRCTag);
5264 m_Curve[2] = GetInvCurve(icSigBlueTRCTag);
5265
5266 m_bFreeCurve = true;
5267
5268 if (!m_Curve[0] || !m_Curve[1] || !m_Curve[2]) {
5270 }
5271
5272 if (!icMatrixInvert3x3(m_e)) {
5274 }
5275 }
5276
5277 m_Curve[0]->Begin();
5278 m_Curve[1]->Begin();
5279 m_Curve[2]->Begin();
5280
5281 if (!m_Curve[0]->IsIdentity() || !m_Curve[1]->IsIdentity() || !m_Curve[2]->IsIdentity()) {
5282 m_ApplyCurvePtr = m_Curve;
5283 }
5284
5285 return icCmmStatOk;
5286}
5287
5288
5290{
5291 v = (icFloatNumber)(v * 32768.0 / 65535.0);
5292 return v;
5293}
5294
5296{
5297 return (icFloatNumber)(v * 65535.0 / 32768.0);
5298}
5299
5301{
5302 if (v<=0)
5303 return(pCurve->Apply(0));
5304 else if (v>=1.0)
5305 return (pCurve->Apply(1.0));
5306
5307 return pCurve->Apply(v);
5308}
5309
5323void CIccXformMatrixTRC::Apply(CIccApplyXform* pApply, icFloatNumber *DstPixel, const icFloatNumber *SrcPixel) const
5324{
5325 icFloatNumber Pixel[3];
5326
5327 if (m_bSrcPcsConversion)
5328 SrcPixel = CheckSrcAbs(pApply, SrcPixel);
5329
5330 Pixel[0] = SrcPixel[0];
5331 Pixel[1] = SrcPixel[1];
5332 Pixel[2] = SrcPixel[2];
5333
5334 if (m_bInput) {
5335
5336 double LinR, LinG, LinB;
5337 if (m_ApplyCurvePtr) {
5338 LinR = m_ApplyCurvePtr[0]->Apply(Pixel[0]);
5339 LinG = m_ApplyCurvePtr[1]->Apply(Pixel[1]);
5340 LinB = m_ApplyCurvePtr[2]->Apply(Pixel[2]);
5341 }
5342 else {
5343 LinR = Pixel[0];
5344 LinG = Pixel[1];
5345 LinB = Pixel[2];
5346 }
5347
5348 DstPixel[0] = XYZScale((icFloatNumber)(m_e[0] * LinR + m_e[1] * LinG + m_e[2] * LinB));
5349 DstPixel[1] = XYZScale((icFloatNumber)(m_e[3] * LinR + m_e[4] * LinG + m_e[5] * LinB));
5350 DstPixel[2] = XYZScale((icFloatNumber)(m_e[6] * LinR + m_e[7] * LinG + m_e[8] * LinB));
5351 }
5352 else {
5353 double X = XYZDescale(Pixel[0]);
5354 double Y = XYZDescale(Pixel[1]);
5355 double Z = XYZDescale(Pixel[2]);
5356
5357 if (m_ApplyCurvePtr) {
5358 DstPixel[0] = RGBClip((icFloatNumber)(m_e[0] * X + m_e[1] * Y + m_e[2] * Z), m_ApplyCurvePtr[0]);
5359 DstPixel[1] = RGBClip((icFloatNumber)(m_e[3] * X + m_e[4] * Y + m_e[5] * Z), m_ApplyCurvePtr[1]);
5360 DstPixel[2] = RGBClip((icFloatNumber)(m_e[6] * X + m_e[7] * Y + m_e[8] * Z), m_ApplyCurvePtr[2]);
5361 }
5362 else {
5363 DstPixel[0] = (icFloatNumber)(m_e[0] * X + m_e[1] * Y + m_e[2] * Z);
5364 DstPixel[1] = (icFloatNumber)(m_e[3] * X + m_e[4] * Y + m_e[5] * Z);
5365 DstPixel[2] = (icFloatNumber)(m_e[6] * X + m_e[7] * Y + m_e[8] * Z);
5366 }
5367 }
5368
5369 if (m_bDstPcsConversion)
5370 CheckDstAbs(DstPixel);
5371}
5372
5387CIccCurve *CIccXformMatrixTRC::GetCurve(icSignature sig) const
5388{
5389 CIccTag *pTag = m_pProfile->FindTag(sig);
5390
5391 if (pTag && (pTag->GetType()==icSigCurveType || pTag->GetType()==icSigParametricCurveType)) {
5392 return (CIccCurve*)pTag;
5393 }
5394
5395 return NULL;
5396}
5397
5412CIccTagXYZ *CIccXformMatrixTRC::GetColumn(icSignature sig) const
5413{
5414 CIccTag *pTag = m_pProfile->FindTag(sig);
5415
5416 if (!pTag || pTag->GetType()!=icSigXYZType) {
5417 return NULL;
5418 }
5419
5420 return (CIccTagXYZ*)pTag;
5421}
5422
5437CIccCurve *CIccXformMatrixTRC::GetInvCurve(icSignature sig) const
5438{
5439 CIccCurve *pCurve;
5440 CIccTagCurve *pInvCurve;
5441
5442 if (!(pCurve = GetCurve(sig)))
5443 return NULL;
5444
5445 pCurve->Begin();
5446
5447 pInvCurve = new CIccTagCurve(2048);
5448
5449 int i;
5450 icFloatNumber x;
5451 icFloatNumber *Lut = &(*pInvCurve)[0];
5452
5453 for (i=0; i<2048; i++) {
5454 x=(icFloatNumber)i / 2047;
5455
5456 Lut[i] = pCurve->Find(x);
5457 }
5458
5459 return pInvCurve;
5460}
5461
5476LPIccCurve* CIccXformMatrixTRC::ExtractInputCurves()
5477{
5478 if (m_bInput) {
5479 if (m_Curve[0]) {
5480 LPIccCurve* Curve = new LPIccCurve[3];
5481 Curve[0] = (LPIccCurve)(m_Curve[0]->NewCopy());
5482 Curve[1] = (LPIccCurve)(m_Curve[1]->NewCopy());
5483 Curve[2] = (LPIccCurve)(m_Curve[2]->NewCopy());
5484 m_ApplyCurvePtr = NULL;
5485 return Curve;
5486 }
5487 }
5488
5489 return NULL;
5490}
5491
5506LPIccCurve* CIccXformMatrixTRC::ExtractOutputCurves()
5507{
5508 if (!m_bInput) {
5509 if (m_Curve[0]) {
5510 LPIccCurve* Curve = new LPIccCurve[3];
5511 Curve[0] = (LPIccCurve)(m_Curve[0]->NewCopy());
5512 Curve[1] = (LPIccCurve)(m_Curve[1]->NewCopy());
5513 Curve[2] = (LPIccCurve)(m_Curve[2]->NewCopy());
5514 m_ApplyCurvePtr = NULL;
5515 return Curve;
5516 }
5517 }
5518
5519 return NULL;
5520}
5521
5533CIccXform3DLut::CIccXform3DLut(CIccTag *pTag)
5534{
5535 if (pTag && pTag->IsMBBType()) {
5536 m_pTag = (CIccMBB*)pTag;
5537 }
5538 else
5539 m_pTag = NULL;
5540
5541 m_ApplyCurvePtrA = m_ApplyCurvePtrB = m_ApplyCurvePtrM = NULL;
5542 m_ApplyMatrixPtr = NULL;
5543}
5544
5553CIccXform3DLut::~CIccXform3DLut()
5554{
5555}
5556
5567 icStatusCMM CIccXform3DLut::Begin()
5568{
5569 icStatusCMM status;
5570 CIccCurve **Curve;
5571 int i;
5572
5573 status = CIccXform::Begin();
5574 if (status != icCmmStatOk)
5575 return status;
5576
5577 if (!m_pTag ||
5578 m_pTag->InputChannels()!=3) {
5579 return icCmmStatInvalidLut;
5580 }
5581
5582 m_ApplyCurvePtrA = NULL;
5583 m_ApplyCurvePtrB = NULL;
5584 m_ApplyCurvePtrM = NULL;
5585
5586 if (m_pTag->m_bInputMatrix) {
5587 if (m_pTag->m_CurvesB) {
5588 Curve = m_pTag->m_CurvesB;
5589
5590 Curve[0]->Begin();
5591 Curve[1]->Begin();
5592 Curve[2]->Begin();
5593
5594 if (!Curve[0]->IsIdentity() || !Curve[1]->IsIdentity() || !Curve[2]->IsIdentity()) {
5595 m_ApplyCurvePtrB = Curve;
5596 }
5597 }
5598
5599 if (m_pTag->m_CurvesM) {
5600 Curve = m_pTag->m_CurvesM;
5601
5602 Curve[0]->Begin();
5603 Curve[1]->Begin();
5604 Curve[2]->Begin();
5605
5606 if (!Curve[0]->IsIdentity() || !Curve[1]->IsIdentity() || !Curve[2]->IsIdentity()) {
5607 m_ApplyCurvePtrM = Curve;
5608 }
5609 }
5610
5611 if (m_pTag->m_CLUT) {
5612 m_pTag->m_CLUT->Begin();
5613 }
5614
5615 if (m_pTag->m_CurvesA) {
5616 Curve = m_pTag->m_CurvesA;
5617
5618 for (i=0; i<m_pTag->m_nOutput; i++) {
5619 Curve[i]->Begin();
5620 }
5621
5622 for (i=0; i<m_pTag->m_nOutput; i++) {
5623 if (!Curve[i]->IsIdentity()) {
5624 m_ApplyCurvePtrA = Curve;
5625 break;
5626 }
5627 }
5628 }
5629
5630 }
5631 else {
5632 if (m_pTag->m_CurvesA) {
5633 Curve = m_pTag->m_CurvesA;
5634
5635 Curve[0]->Begin();
5636 Curve[1]->Begin();
5637 Curve[2]->Begin();
5638
5639 if (!Curve[0]->IsIdentity() || !Curve[1]->IsIdentity() || !Curve[2]->IsIdentity()) {
5640 m_ApplyCurvePtrA = Curve;
5641 }
5642 }
5643
5644 if (m_pTag->m_CLUT) {
5645 m_pTag->m_CLUT->Begin();
5646 }
5647
5648 if (m_pTag->m_CurvesM) {
5649 Curve = m_pTag->m_CurvesM;
5650
5651 for (i=0; i<m_pTag->m_nOutput; i++) {
5652 Curve[i]->Begin();
5653 }
5654
5655 for (i=0; i<m_pTag->m_nOutput; i++) {
5656 if (!Curve[i]->IsIdentity()) {
5657 m_ApplyCurvePtrM = Curve;
5658 break;
5659 }
5660 }
5661 }
5662
5663 if (m_pTag->m_CurvesB) {
5664 Curve = m_pTag->m_CurvesB;
5665
5666 for (i=0; i<m_pTag->m_nOutput; i++) {
5667 Curve[i]->Begin();
5668 }
5669
5670 for (i=0; i<m_pTag->m_nOutput; i++) {
5671 if (!Curve[i]->IsIdentity()) {
5672 m_ApplyCurvePtrB = Curve;
5673 break;
5674 }
5675 }
5676 }
5677 }
5678
5679 m_ApplyMatrixPtr = NULL;
5680 if (m_pTag->m_Matrix) {
5681 if (m_pTag->m_bInputMatrix) {
5682 if (m_pTag->m_nInput!=3) {
5684 }
5685 }
5686 else {
5687 if (m_pTag->m_nOutput!=3) {
5689 }
5690 }
5691
5692 if (!m_pTag->m_Matrix->IsIdentity()) {
5693 m_ApplyMatrixPtr = m_pTag->m_Matrix;
5694 }
5695 }
5696
5697 return icCmmStatOk;
5698}
5699
5713void CIccXform3DLut::Apply(CIccApplyXform* pApply, icFloatNumber *DstPixel, const icFloatNumber *SrcPixel) const
5714{
5715 icFloatNumber Pixel[16];
5716 for (int j = 0; j < m_pTag->m_nOutput && j < 16; ++j)
5717 Pixel[j] = 0.0f;
5718
5719 int i;
5720
5721 if (m_bSrcPcsConversion)
5722 SrcPixel = CheckSrcAbs(pApply, SrcPixel);
5723
5724 Pixel[0] = SrcPixel[0];
5725 Pixel[1] = SrcPixel[1];
5726 Pixel[2] = SrcPixel[2];
5727
5728 if (m_pTag->m_bInputMatrix) {
5729 if (m_ApplyCurvePtrB) {
5730 Pixel[0] = m_ApplyCurvePtrB[0]->Apply(Pixel[0]);
5731 Pixel[1] = m_ApplyCurvePtrB[1]->Apply(Pixel[1]);
5732 Pixel[2] = m_ApplyCurvePtrB[2]->Apply(Pixel[2]);
5733 }
5734
5735 if (m_ApplyMatrixPtr) {
5736 m_ApplyMatrixPtr->Apply(Pixel);
5737 }
5738
5739 if (m_ApplyCurvePtrM) {
5740 Pixel[0] = m_ApplyCurvePtrM[0]->Apply(Pixel[0]);
5741 Pixel[1] = m_ApplyCurvePtrM[1]->Apply(Pixel[1]);
5742 Pixel[2] = m_ApplyCurvePtrM[2]->Apply(Pixel[2]);
5743 }
5744
5745 if (m_pTag->m_CLUT) {
5746 if (m_nInterp==icInterpLinear)
5747 m_pTag->m_CLUT->Interp3d(Pixel, Pixel);
5748 else
5749 m_pTag->m_CLUT->Interp3dTetra(Pixel, Pixel);
5750 }
5751
5752 if (m_ApplyCurvePtrA) {
5753 for (i=0; i<m_pTag->m_nOutput; i++) {
5754 Pixel[i] = m_ApplyCurvePtrA[i]->Apply(Pixel[i]);
5755 }
5756 }
5757
5758 }
5759 else {
5760 if (m_ApplyCurvePtrA) {
5761 Pixel[0] = m_ApplyCurvePtrA[0]->Apply(Pixel[0]);
5762 Pixel[1] = m_ApplyCurvePtrA[1]->Apply(Pixel[1]);
5763 Pixel[2] = m_ApplyCurvePtrA[2]->Apply(Pixel[2]);
5764 }
5765
5766 if (m_pTag->m_CLUT) {
5767 if (m_nInterp==icInterpLinear)
5768 m_pTag->m_CLUT->Interp3d(Pixel, Pixel);
5769 else
5770 m_pTag->m_CLUT->Interp3dTetra(Pixel, Pixel);
5771 }
5772
5773 if (m_ApplyCurvePtrM) {
5774 for (i=0; i<m_pTag->m_nOutput; i++) {
5775 Pixel[i] = m_ApplyCurvePtrM[i]->Apply(Pixel[i]);
5776 }
5777 }
5778
5779 if (m_ApplyMatrixPtr) {
5780 m_ApplyMatrixPtr->Apply(Pixel);
5781 }
5782
5783 if (m_ApplyCurvePtrB) {
5784 for (i=0; i<m_pTag->m_nOutput; i++) {
5785 Pixel[i] = m_ApplyCurvePtrB[i]->Apply(Pixel[i]);
5786 }
5787 }
5788 }
5789
5790 for (i = 0; i < m_pTag->m_nOutput && i < 16; i++) {
5791 DstPixel[i] = Pixel[i];
5792 }
5793
5794 if (m_bDstPcsConversion)
5795 CheckDstAbs(DstPixel);
5796}
5797
5812LPIccCurve* CIccXform3DLut::ExtractInputCurves()
5813{
5814 if (m_bInput) {
5815 if (m_pTag->m_bInputMatrix) {
5816 if (m_pTag->m_CurvesB) {
5817 LPIccCurve* Curve = new LPIccCurve[3];
5818 Curve[0] = (LPIccCurve)(m_pTag->m_CurvesB[0]->NewCopy());
5819 Curve[1] = (LPIccCurve)(m_pTag->m_CurvesB[1]->NewCopy());
5820 Curve[2] = (LPIccCurve)(m_pTag->m_CurvesB[2]->NewCopy());
5821 m_ApplyCurvePtrB = NULL;
5822 return Curve;
5823 }
5824 }
5825 else {
5826 if (m_pTag->m_CurvesA) {
5827 LPIccCurve* Curve = new LPIccCurve[3];
5828 Curve[0] = (LPIccCurve)(m_pTag->m_CurvesA[0]->NewCopy());
5829 Curve[1] = (LPIccCurve)(m_pTag->m_CurvesA[1]->NewCopy());
5830 Curve[2] = (LPIccCurve)(m_pTag->m_CurvesA[2]->NewCopy());
5831 m_ApplyCurvePtrA = NULL;
5832 return Curve;
5833 }
5834 }
5835 }
5836
5837 return NULL;
5838}
5839
5854LPIccCurve* CIccXform3DLut::ExtractOutputCurves()
5855{
5856 if (!m_bInput) {
5857 if (m_pTag->m_bInputMatrix) {
5858 if (m_pTag->m_CurvesA) {
5859 LPIccCurve* Curve = new LPIccCurve[m_pTag->m_nOutput];
5860 for (int i=0; i<m_pTag->m_nOutput; i++) {
5861 Curve[i] = (LPIccCurve)(m_pTag->m_CurvesA[i]->NewCopy());
5862 }
5863 m_ApplyCurvePtrA = NULL;
5864 return Curve;
5865 }
5866 }
5867 else {
5868 if (m_pTag->m_CurvesB) {
5869 LPIccCurve* Curve = new LPIccCurve[m_pTag->m_nOutput];
5870 for (int i=0; i<m_pTag->m_nOutput; i++) {
5871 Curve[i] = (LPIccCurve)(m_pTag->m_CurvesB[i]->NewCopy());
5872 }
5873 m_ApplyCurvePtrB = NULL;
5874 return Curve;
5875 }
5876 }
5877 }
5878
5879 return NULL;
5880}
5881
5893CIccXform4DLut::CIccXform4DLut(CIccTag *pTag)
5894{
5895 if (pTag && pTag->IsMBBType()) {
5896 m_pTag = (CIccMBB*)pTag;
5897 }
5898 else
5899 m_pTag = NULL;
5900
5901 m_ApplyCurvePtrA = m_ApplyCurvePtrB = m_ApplyCurvePtrM = NULL;
5902 m_ApplyMatrixPtr = NULL;
5903}
5904
5905
5914CIccXform4DLut::~CIccXform4DLut()
5915{
5916}
5917
5918
5929icStatusCMM CIccXform4DLut::Begin()
5930{
5931 icStatusCMM status;
5932 CIccCurve **Curve;
5933 int i;
5934
5935 status = CIccXform::Begin();
5936 if (status != icCmmStatOk) {
5937 return status;
5938 }
5939
5940 if (!m_pTag ||
5941 m_pTag->InputChannels()!=4) {
5942 return icCmmStatInvalidLut;
5943 }
5944
5945 m_ApplyCurvePtrA = m_ApplyCurvePtrB = m_ApplyCurvePtrM = NULL;
5946
5947 if (m_pTag->m_bInputMatrix) {
5948 if (m_pTag->m_CurvesB) {
5949 Curve = m_pTag->m_CurvesB;
5950
5951 Curve[0]->Begin();
5952 Curve[1]->Begin();
5953 Curve[2]->Begin();
5954 Curve[3]->Begin();
5955
5956 if (!Curve[0]->IsIdentity() || !Curve[1]->IsIdentity() ||
5957 !Curve[2]->IsIdentity() || !Curve[3]->IsIdentity())
5958 {
5959 m_ApplyCurvePtrB = Curve;
5960 }
5961 }
5962
5963 if (m_pTag->m_CLUT) {
5964 m_pTag->m_CLUT->Begin();
5965 }
5966
5967 if (m_pTag->m_CurvesA) {
5968 Curve = m_pTag->m_CurvesA;
5969
5970 for (i=0; i<m_pTag->m_nOutput; i++) {
5971 Curve[i]->Begin();
5972 }
5973
5974 for (i=0; i<m_pTag->m_nOutput; i++) {
5975 if (!Curve[i]->IsIdentity()) {
5976 m_ApplyCurvePtrA = Curve;
5977 break;
5978 }
5979 }
5980 }
5981
5982 }
5983 else {
5984 if (m_pTag->m_CurvesA) {
5985 Curve = m_pTag->m_CurvesA;
5986
5987 Curve[0]->Begin();
5988 Curve[1]->Begin();
5989 Curve[2]->Begin();
5990 Curve[3]->Begin();
5991
5992 if (!Curve[0]->IsIdentity() || !Curve[1]->IsIdentity() ||
5993 !Curve[2]->IsIdentity() || !Curve[3]->IsIdentity())
5994 {
5995 m_ApplyCurvePtrA = Curve;
5996 }
5997 }
5998
5999 if (m_pTag->m_CLUT) {
6000 m_pTag->m_CLUT->Begin();
6001 }
6002
6003 if (m_pTag->m_CurvesM) {
6004 Curve = m_pTag->m_CurvesM;
6005
6006 for (i=0; i<m_pTag->m_nOutput; i++) {
6007 Curve[i]->Begin();
6008 }
6009
6010 for (i=0; i<m_pTag->m_nOutput; i++) {
6011 if (!Curve[i]->IsIdentity()) {
6012 m_ApplyCurvePtrM = Curve;
6013 break;
6014 }
6015 }
6016 }
6017
6018 if (m_pTag->m_CurvesB) {
6019 Curve = m_pTag->m_CurvesB;
6020
6021 for (i=0; i<m_pTag->m_nOutput; i++) {
6022 Curve[i]->Begin();
6023 }
6024
6025 for (i=0; i<m_pTag->m_nOutput; i++) {
6026 if (!Curve[i]->IsIdentity()) {
6027 m_ApplyCurvePtrB = Curve;
6028 break;
6029 }
6030 }
6031 }
6032 }
6033
6034 m_ApplyMatrixPtr = NULL;
6035 if (m_pTag->m_Matrix) {
6036 if (m_pTag->m_bInputMatrix) {
6038 }
6039 else {
6040 if (m_pTag->m_nOutput!=3) {
6042 }
6043 }
6044
6045 if (!m_pTag->m_Matrix->IsIdentity()) {
6046 m_ApplyMatrixPtr = m_pTag->m_Matrix;
6047 }
6048 }
6049
6050 return icCmmStatOk;
6051}
6052
6053
6067void CIccXform4DLut::Apply(CIccApplyXform* pApply, icFloatNumber *DstPixel, const icFloatNumber *SrcPixel) const
6068{
6069 icFloatNumber Pixel[16];
6070 int i;
6071
6072 if (m_bSrcPcsConversion)
6073 SrcPixel = CheckSrcAbs(pApply, SrcPixel);
6074
6075 Pixel[0] = SrcPixel[0];
6076 Pixel[1] = SrcPixel[1];
6077 Pixel[2] = SrcPixel[2];
6078 Pixel[3] = SrcPixel[3];
6079
6080 if (m_pTag->m_bInputMatrix) {
6081 if (m_ApplyCurvePtrB) {
6082 Pixel[0] = m_ApplyCurvePtrB[0]->Apply(Pixel[0]);
6083 Pixel[1] = m_ApplyCurvePtrB[1]->Apply(Pixel[1]);
6084 Pixel[2] = m_ApplyCurvePtrB[2]->Apply(Pixel[2]);
6085 Pixel[3] = m_ApplyCurvePtrB[3]->Apply(Pixel[3]);
6086 }
6087
6088 if (m_pTag->m_CLUT) {
6089 m_pTag->m_CLUT->Interp4d(Pixel, Pixel);
6090 }
6091
6092 if (m_ApplyCurvePtrA) {
6093 for (i=0; i<m_pTag->m_nOutput; i++) {
6094 Pixel[i] = m_ApplyCurvePtrA[i]->Apply(Pixel[i]);
6095 }
6096 }
6097
6098 }
6099 else {
6100 if (m_ApplyCurvePtrA) {
6101 Pixel[0] = m_ApplyCurvePtrA[0]->Apply(Pixel[0]);
6102 Pixel[1] = m_ApplyCurvePtrA[1]->Apply(Pixel[1]);
6103 Pixel[2] = m_ApplyCurvePtrA[2]->Apply(Pixel[2]);
6104 Pixel[3] = m_ApplyCurvePtrA[3]->Apply(Pixel[3]);
6105 }
6106
6107 if (m_pTag->m_CLUT) {
6108 m_pTag->m_CLUT->Interp4d(Pixel, Pixel);
6109 }
6110
6111 if (m_ApplyCurvePtrM) {
6112 for (i=0; i<m_pTag->m_nOutput; i++) {
6113 Pixel[i] = m_ApplyCurvePtrM[i]->Apply(Pixel[i]);
6114 }
6115 }
6116
6117 if (m_ApplyMatrixPtr) {
6118 m_ApplyMatrixPtr->Apply(Pixel);
6119 }
6120
6121 if (m_ApplyCurvePtrB) {
6122 for (i=0; i<m_pTag->m_nOutput; i++) {
6123 Pixel[i] = m_ApplyCurvePtrB[i]->Apply(Pixel[i]);
6124 }
6125 }
6126 }
6127
6128 for (i=0; i<m_pTag->m_nOutput; i++) {
6129 DstPixel[i] = Pixel[i];
6130 }
6131
6132 if (m_bDstPcsConversion)
6133 (DstPixel);
6134}
6135
6150LPIccCurve* CIccXform4DLut::ExtractInputCurves()
6151{
6152 if (m_bInput) {
6153 if (m_pTag->m_bInputMatrix) {
6154 if (m_pTag->m_CurvesB) {
6155 LPIccCurve* Curve = new LPIccCurve[4];
6156 Curve[0] = (LPIccCurve)(m_pTag->m_CurvesB[0]->NewCopy());
6157 Curve[1] = (LPIccCurve)(m_pTag->m_CurvesB[1]->NewCopy());
6158 Curve[2] = (LPIccCurve)(m_pTag->m_CurvesB[2]->NewCopy());
6159 Curve[3] = (LPIccCurve)(m_pTag->m_CurvesB[3]->NewCopy());
6160 m_ApplyCurvePtrB = NULL;
6161 return Curve;
6162 }
6163 }
6164 else {
6165 if (m_pTag->m_CurvesA) {
6166 LPIccCurve* Curve = new LPIccCurve[4];
6167 Curve[0] = (LPIccCurve)(m_pTag->m_CurvesA[0]->NewCopy());
6168 Curve[1] = (LPIccCurve)(m_pTag->m_CurvesA[1]->NewCopy());
6169 Curve[2] = (LPIccCurve)(m_pTag->m_CurvesA[2]->NewCopy());
6170 Curve[3] = (LPIccCurve)(m_pTag->m_CurvesA[3]->NewCopy());
6171 m_ApplyCurvePtrA = NULL;
6172 return Curve;
6173 }
6174 }
6175 }
6176
6177 return NULL;
6178}
6179
6194LPIccCurve* CIccXform4DLut::ExtractOutputCurves()
6195{
6196 if (!m_bInput) {
6197 if (m_pTag->m_bInputMatrix) {
6198 if (m_pTag->m_CurvesA) {
6199 LPIccCurve* Curve = new LPIccCurve[m_pTag->m_nOutput];
6200 for (int i=0; i<m_pTag->m_nOutput; i++) {
6201 Curve[i] = (LPIccCurve)(m_pTag->m_CurvesA[i]->NewCopy());
6202 }
6203 m_ApplyCurvePtrA = NULL;
6204 return Curve;
6205 }
6206 }
6207 else {
6208 if (m_pTag->m_CurvesB) {
6209 LPIccCurve* Curve = new LPIccCurve[m_pTag->m_nOutput];
6210 for (int i=0; i<m_pTag->m_nOutput; i++) {
6211 Curve[i] = (LPIccCurve)(m_pTag->m_CurvesB[i]->NewCopy());
6212 }
6213 m_ApplyCurvePtrB = NULL;
6214 return Curve;
6215 }
6216 }
6217 }
6218
6219 return NULL;
6220}
6221
6222
6234CIccXformNDLut::CIccXformNDLut(CIccTag *pTag)
6235{
6236 if (pTag && pTag->IsMBBType()) {
6237 m_pTag = (CIccMBB*)pTag;
6238 }
6239 else
6240 m_pTag = NULL;
6241
6242 m_ApplyCurvePtrA = m_ApplyCurvePtrB = m_ApplyCurvePtrM = NULL;
6243 m_ApplyMatrixPtr = NULL;
6244 m_nNumInput = 0;
6245}
6246
6247
6256CIccXformNDLut::~CIccXformNDLut()
6257{
6258}
6259
6260
6271icStatusCMM CIccXformNDLut::Begin()
6272{
6273 icStatusCMM status;
6274 CIccCurve **Curve;
6275 int i;
6276
6277 status = CIccXform::Begin();
6278 if (status != icCmmStatOk) {
6279 return status;
6280 }
6281
6282 if (!m_pTag || (m_pTag->InputChannels()>2 && m_pTag->InputChannels()<5)) {
6283 return icCmmStatInvalidLut;
6284 }
6285
6286 m_nNumInput = m_pTag->m_nInput;
6287
6288 m_ApplyCurvePtrA = m_ApplyCurvePtrB = m_ApplyCurvePtrM = NULL;
6289
6290 if (m_pTag->m_bInputMatrix) {
6291 if (m_pTag->m_CurvesB) {
6292 Curve = m_pTag->m_CurvesB;
6293
6294 for (i=0; i<m_nNumInput; i++)
6295 Curve[i]->Begin();
6296
6297 for (i=0; i<m_nNumInput; i++) {
6298 if (!Curve[i]->IsIdentity()) {
6299 m_ApplyCurvePtrB = Curve;
6300 break;
6301 }
6302 }
6303 }
6304
6305 if (m_pTag->m_CLUT) {
6306 m_pTag->m_CLUT->Begin();
6307 }
6308
6309 if (m_pTag->m_CurvesA) {
6310 Curve = m_pTag->m_CurvesA;
6311
6312 for (i=0; i<m_pTag->m_nOutput; i++) {
6313 Curve[i]->Begin();
6314 }
6315
6316 for (i=0; i<m_pTag->m_nOutput; i++) {
6317 if (!Curve[i]->IsIdentity()) {
6318 m_ApplyCurvePtrA = Curve;
6319 break;
6320 }
6321 }
6322 }
6323
6324 }
6325 else {
6326 if (m_pTag->m_CurvesA) {
6327 Curve = m_pTag->m_CurvesA;
6328
6329 for (i=0; i<m_nNumInput; i++)
6330 Curve[i]->Begin();
6331
6332 for (i=0; i<m_nNumInput; i++) {
6333 if (!Curve[i]->IsIdentity()) {
6334 m_ApplyCurvePtrA = Curve;
6335 break;
6336 }
6337 }
6338 }
6339
6340 if (m_pTag->m_CLUT) {
6341 m_pTag->m_CLUT->Begin();
6342 }
6343
6344 if (m_pTag->m_CurvesM) {
6345 Curve = m_pTag->m_CurvesM;
6346
6347 for (i=0; i<m_pTag->m_nOutput; i++) {
6348 Curve[i]->Begin();
6349 }
6350
6351 for (i=0; i<m_pTag->m_nOutput; i++) {
6352 if (!Curve[i]->IsIdentity()) {
6353 m_ApplyCurvePtrM = Curve;
6354 break;
6355 }
6356 }
6357 }
6358
6359 if (m_pTag->m_CurvesB) {
6360 Curve = m_pTag->m_CurvesB;
6361
6362 for (i=0; i<m_pTag->m_nOutput; i++) {
6363 Curve[i]->Begin();
6364 }
6365
6366 for (i=0; i<m_pTag->m_nOutput; i++) {
6367 if (!Curve[i]->IsIdentity()) {
6368 m_ApplyCurvePtrB = Curve;
6369 break;
6370 }
6371 }
6372 }
6373 }
6374
6375 m_ApplyMatrixPtr = NULL;
6376 if (m_pTag->m_Matrix) {
6377 if (m_pTag->m_bInputMatrix) {
6379 }
6380 else {
6381 if (m_pTag->m_nOutput!=3) {
6383 }
6384 }
6385
6386 if (!m_pTag->m_Matrix->IsIdentity()) {
6387 m_ApplyMatrixPtr = m_pTag->m_Matrix;
6388 }
6389 }
6390
6391 return icCmmStatOk;
6392}
6393
6394
6406CIccApplyXform* CIccXformNDLut::GetNewApply(icStatusCMM& status)
6407{
6408 if (!m_pTag)
6409 return NULL;
6410
6411 CIccCLUT* pCLUT = m_pTag->GetCLUT();
6412 CIccApplyCLUT* pApply = NULL;
6413
6414 if (pCLUT && m_nNumInput > 6) {
6415 pApply = pCLUT->GetNewApply();
6416 if (!pApply) {
6417 status = icCmmStatAllocErr;
6418 return NULL;
6419 }
6420 }
6421
6422 CIccApplyNDLutXform* rv = new CIccApplyNDLutXform(this, pApply);
6423
6424 if (!rv) {
6425 if (pApply)
6426 delete pApply;
6427 status = icCmmStatAllocErr;
6428 return NULL;
6429 }
6430
6431 status = icCmmStatOk;
6432 return rv;
6433}
6434
6448void CIccXformNDLut::Apply(CIccApplyXform* pApply, icFloatNumber *DstPixel, const icFloatNumber *SrcPixel) const
6449{
6450 icFloatNumber Pixel[16] = {0};
6451 int i;
6452
6453 if (m_bSrcPcsConversion)
6454 SrcPixel = CheckSrcAbs(pApply, SrcPixel);
6455
6456 for (i=0; i<m_nNumInput; i++)
6457 Pixel[i] = SrcPixel[i];
6458
6459 if (m_pTag->m_bInputMatrix) {
6460 if (m_ApplyCurvePtrB) {
6461 for (i=0; i<m_nNumInput; i++)
6462 Pixel[i] = m_ApplyCurvePtrB[i]->Apply(Pixel[i]);
6463 }
6464
6465 if (m_pTag->m_CLUT) {
6466 switch(m_nNumInput) {
6467 case 5:
6468 m_pTag->m_CLUT->Interp5d(Pixel, Pixel);
6469 break;
6470 case 6:
6471 m_pTag->m_CLUT->Interp6d(Pixel, Pixel);
6472 break;
6473 default:
6474 {
6475 CIccApplyNDLutXform* pNDApply = (CIccApplyNDLutXform*)pApply;
6476 m_pTag->m_CLUT->InterpND(Pixel, Pixel, pNDApply->m_pApply);
6477 break;
6478 }
6479 }
6480 }
6481
6482 if (m_ApplyCurvePtrA) {
6483 for (i=0; i<m_pTag->m_nOutput; i++) {
6484 Pixel[i] = m_ApplyCurvePtrA[i]->Apply(Pixel[i]);
6485 }
6486 }
6487
6488 }
6489 else {
6490 if (m_ApplyCurvePtrA) {
6491 for (i=0; i<m_nNumInput; i++)
6492 Pixel[i] = m_ApplyCurvePtrA[i]->Apply(Pixel[i]);
6493 }
6494
6495 if (m_pTag->m_CLUT) {
6496 switch(m_nNumInput) {
6497 case 5:
6498 m_pTag->m_CLUT->Interp5d(Pixel, Pixel);
6499 break;
6500 case 6:
6501 m_pTag->m_CLUT->Interp6d(Pixel, Pixel);
6502 break;
6503 default:
6504 {
6505 CIccApplyNDLutXform* pNDApply = (CIccApplyNDLutXform*)pApply;
6506 m_pTag->m_CLUT->InterpND(Pixel, Pixel, pNDApply->m_pApply);
6507 break;
6508 }
6509 break;
6510 }
6511 }
6512
6513 if (m_ApplyCurvePtrM) {
6514 for (i=0; i<m_pTag->m_nOutput; i++) {
6515 Pixel[i] = m_ApplyCurvePtrM[i]->Apply(Pixel[i]);
6516 }
6517 }
6518
6519 if (m_ApplyMatrixPtr) {
6520 m_ApplyMatrixPtr->Apply(Pixel);
6521 }
6522
6523 if (m_ApplyCurvePtrB) {
6524 for (i=0; i<m_pTag->m_nOutput; i++) {
6525 Pixel[i] = m_ApplyCurvePtrB[i]->Apply(Pixel[i]);
6526 }
6527 }
6528 }
6529
6530 for (i=0; i<m_pTag->m_nOutput; i++) {
6531 DstPixel[i] = Pixel[i];
6532 }
6533
6534 if (m_bDstPcsConversion)
6535 CheckDstAbs(DstPixel);
6536}
6537
6552LPIccCurve* CIccXformNDLut::ExtractInputCurves()
6553{
6554 if (m_bInput) {
6555 if (m_pTag->m_bInputMatrix) {
6556 if (m_pTag->m_CurvesB) {
6557 LPIccCurve* Curve = new LPIccCurve[m_pTag->m_nInput];
6558 for (int i=0; i<m_pTag->m_nInput; i++) {
6559 Curve[i] = (LPIccCurve)(m_pTag->m_CurvesB[i]->NewCopy());
6560 }
6561 m_ApplyCurvePtrB = NULL;
6562 return Curve;
6563 }
6564 }
6565 else {
6566 if (m_pTag->m_CurvesA) {
6567 LPIccCurve* Curve = new LPIccCurve[m_pTag->m_nInput];
6568 for (int i=0; i<m_pTag->m_nInput; i++) {
6569 Curve[i] = (LPIccCurve)(m_pTag->m_CurvesA[i]->NewCopy());
6570 }
6571 m_ApplyCurvePtrA = NULL;
6572 return Curve;
6573 }
6574 }
6575 }
6576
6577 return NULL;
6578}
6579
6594LPIccCurve* CIccXformNDLut::ExtractOutputCurves()
6595{
6596 if (!m_bInput) {
6597 if (m_pTag->m_bInputMatrix) {
6598 if (m_pTag->m_CurvesA) {
6599 LPIccCurve* Curve = new LPIccCurve[m_pTag->m_nOutput];
6600 for (int i=0; i<m_pTag->m_nOutput; i++) {
6601 Curve[i] = (LPIccCurve)(m_pTag->m_CurvesA[i]->NewCopy());
6602 }
6603 m_ApplyCurvePtrA = NULL;
6604 return Curve;
6605 }
6606 }
6607 else {
6608 if (m_pTag->m_CurvesB) {
6609 LPIccCurve* Curve = new LPIccCurve[m_pTag->m_nOutput];
6610 for (int i=0; i<m_pTag->m_nOutput; i++) {
6611 Curve[i] = (LPIccCurve)(m_pTag->m_CurvesB[i]->NewCopy());
6612 }
6613 m_ApplyCurvePtrB = NULL;
6614 return Curve;
6615 }
6616 }
6617 }
6618
6619 return NULL;
6620}
6621
6635CIccXformNamedColor::CIccXformNamedColor(CIccTag *pTag, icColorSpaceSignature csPcs, icColorSpaceSignature csDevice,
6636 icSpectralColorSignature csSpectralPcs/* =icSigNoSpectralData */,
6637 const icSpectralRange *pSpectralRange /* = NULL */,
6638 const icSpectralRange *pBiSpectralRange /* = NULL */)
6639{
6640 m_nApplyInterface = icApplyPixel2Pixel; // was uninitialized
6641 m_pTag = NULL;
6642 if (pTag) {
6643 if (pTag->GetType()==icSigNamedColor2Type) {
6644 m_pTag = (CIccTagNamedColor2*)pTag;
6645 m_pArray = NULL;
6646
6647 m_pTag->SetColorSpaces(csPcs, csDevice);
6648 }
6649 else if (pTag->GetTagArrayType()==icSigNamedColorArray) {
6650 CIccTagArray *pArray = (CIccTagArray*)pTag;
6652
6653 if (pNamed) {
6654 m_pTag = NULL;
6655 m_pArray = pNamed;
6656 pNamed->SetColorSpaces(csPcs, csDevice, csSpectralPcs, pSpectralRange, pBiSpectralRange);
6657 }
6658 }
6659 }
6660
6661 m_nSrcSpace = icSigUnknownData;
6662 m_nDestSpace = icSigUnknownData;
6663 m_pArray = NULL;
6664}
6665
6666
6675CIccXformNamedColor::~CIccXformNamedColor()
6676{
6677}
6678
6689icStatusCMM CIccXformNamedColor::Begin()
6690{
6691 icStatusCMM status;
6692
6693 status = CIccXform::Begin();
6694 if (status != icCmmStatOk)
6695 return status;
6696
6697 if (m_pTag==NULL && m_pArray==NULL) {
6699 }
6700
6701 if (m_nSrcSpace==icSigUnknownData ||
6702 m_nDestSpace==icSigUnknownData) {
6704 }
6705
6706 if (m_nSrcSpace != icSigNamedData) {
6707 if (m_nDestSpace != icSigNamedData) {
6708 m_nApplyInterface = icApplyPixel2Pixel;
6709 }
6710 else {
6711 m_nApplyInterface = icApplyPixel2Named;
6712 }
6713 }
6714 else {
6715 if (m_nDestSpace != icSigNamedData) {
6716 m_nApplyInterface = icApplyNamed2Pixel;
6717 }
6718 else {
6720 }
6721 }
6722
6723 if (m_pTag && !m_pTag->InitFindCachedPCSColor())
6724 return icCmmStatAllocErr;
6725 else if (m_pArray && !m_pArray->Begin())
6726 return icCmmStatAllocErr;
6727
6728 return icCmmStatOk;
6729}
6730
6731
6732
6746icStatusCMM CIccXformNamedColor::Apply(CIccApplyXform* pApply, icChar *DstColorName, const icFloatNumber *SrcPixel) const
6747{
6748
6749 if (m_pArray) {
6750 const CIccArrayNamedColor *pArray = m_pArray;
6751 CIccStructNamedColor *pColor;
6752
6753 std::string NamedColor;
6754
6755 if (IsSrcPCS()) {
6756 if (IsSpaceSpectralPCS(m_nSrcSpace)) {
6757 pColor = pArray->FindSpectralColor(SrcPixel);
6758 if (pColor)
6759 NamedColor = pColor->getName();
6760 else
6762 }
6763 else {
6764 if (m_bSrcPcsConversion)
6765 SrcPixel = CheckSrcAbs(pApply, SrcPixel);
6766
6767 icFloatNumber pix[3];
6768 memcpy(pix, SrcPixel, 3*sizeof(icFloatNumber));
6769
6770 if (m_nSrcSpace == icSigLabPcsData)
6771 icLabFromPcs(pix);
6772 else {
6773 icXyzFromPcs(pix);
6774 icXYZtoLab(pix, pix);
6775 }
6776
6777 pColor = pArray->FindPcsColor(pix);
6778 if (pColor)
6779 NamedColor = pColor->getName();
6780 else
6782 }
6783 }
6784 else {
6785 pColor = pArray->FindDeviceColor(SrcPixel);
6786 if (pColor)
6787 NamedColor = pColor->getName();
6788 else
6790 }
6791
6792 sprintf(DstColorName, "%s", NamedColor.c_str());
6793 }
6794 else if (m_pTag) {
6795 const CIccTagNamedColor2 *pTag = m_pTag;
6796
6797 icFloatNumber DevicePix[16], PCSPix[3];
6798 std::string NamedColor;
6799 icUInt32Number i, j;
6800
6801 if (IsSrcPCS()) {
6802 if (m_bSrcPcsConversion)
6803 SrcPixel = CheckSrcAbs(pApply, SrcPixel);
6804
6805 for(i=0; i<3; i++)
6806 PCSPix[i] = SrcPixel[i];
6807
6808 j = pTag->FindCachedPCSColor(PCSPix);
6809 pTag->GetColorName(NamedColor, j);
6810 }
6811 else {
6812 for(i=0; i<m_pTag->GetDeviceCoords(); i++)
6813 DevicePix[i] = SrcPixel[i];
6814
6815 j = pTag->FindDeviceColor(DevicePix);
6816 pTag->GetColorName(NamedColor, j);
6817 }
6818
6819 sprintf(DstColorName, "%s", NamedColor.c_str());
6820 }
6821 else
6822 return icCmmStatBadXform;
6823
6824 return icCmmStatOk;
6825}
6826
6827
6841icStatusCMM CIccXformNamedColor::Apply(CIccApplyXform* pApply, icFloatNumber *DstPixel, const icChar *SrcColorName, icFloatNumber tint) const
6842{
6843
6844 if (m_pArray) {
6845 const CIccArrayNamedColor *pArray = m_pArray;
6846
6847 CIccStructNamedColor *pColor;
6848
6849 if (m_nSrcSpace != icSigNamedData)
6850 return icCmmStatBadSpaceLink;
6851
6852 pColor = pArray->FindColor(SrcColorName);
6853 if (!pColor)
6855
6856 if (IsDestPCS()) {
6857 if (IsSpaceSpectralPCS(m_nDestSpace)) {
6858 if (!pArray->GetSpectralTint(DstPixel, pColor, tint))
6859 return icCmmStatBadTintXform;
6860 }
6861 else {
6862 if (!pArray->GetPcsTint(DstPixel, pColor, tint))
6863 return icCmmStatBadTintXform;
6864
6865 if (m_nDestSpace == icSigLabData) {
6866 icLabToPcs(DstPixel);
6867 }
6868 else {
6869 icXyzToPcs(DstPixel);
6870 }
6871 if (m_bDstPcsConversion)
6872 CheckDstAbs(DstPixel);
6873 }
6874 }
6875 else {
6876 if (!pArray->GetDeviceTint(DstPixel, pColor, tint))
6877 return icCmmStatBadTintXform;
6878 }
6879 }
6880 else if (m_pTag) {
6881 const CIccTagNamedColor2 *pTag = m_pTag;
6882
6883 icInt32Number j;
6884
6885 if (m_nSrcSpace != icSigNamedData)
6886 return icCmmStatBadSpaceLink;
6887
6888 if (IsDestPCS()) {
6889
6890 j = pTag->FindColor(SrcColorName);
6891 if (j<0)
6893
6894 if (m_nDestSpace == icSigLabData) {
6895 memcpy(DstPixel, pTag->GetEntry(j)->pcsCoords, 3*sizeof(icFloatNumber));
6896 }
6897 else {
6898 memcpy(DstPixel, pTag->GetEntry(j)->pcsCoords, 3*sizeof(icFloatNumber));
6899 }
6900 if (m_bDstPcsConversion)
6901 CheckDstAbs(DstPixel);
6902 }
6903 else {
6904 j = pTag->FindColor(SrcColorName);
6905 if (j<0)
6907 memcpy(DstPixel, pTag->GetEntry(j)->deviceCoords, pTag->GetDeviceCoords()*sizeof(icFloatNumber));
6908 }
6909 }
6910
6911 return icCmmStatOk;
6912}
6913
6925icStatusCMM CIccXformNamedColor::SetSrcSpace(icColorSpaceSignature nSrcSpace)
6926{
6927 if (m_pArray) {
6928
6929 }
6930 else if (m_pTag) {
6931 CIccTagNamedColor2 *pTag = m_pTag;
6932
6933 if (nSrcSpace!=pTag->GetPCS())
6934 if (nSrcSpace!=pTag->GetDeviceSpace())
6935 if (nSrcSpace!=icSigNamedData)
6936 return icCmmStatBadSpaceLink;
6937 }
6938
6939 m_nSrcSpace = nSrcSpace;
6940
6941 return icCmmStatOk;
6942}
6943
6955icStatusCMM CIccXformNamedColor::SetDestSpace(icColorSpaceSignature nDestSpace)
6956{
6957 if (m_nSrcSpace == nDestSpace)
6958 return icCmmStatBadSpaceLink;
6959
6960 if (m_pArray) {
6961
6962 }
6963 else if (m_pTag) {
6964 CIccTagNamedColor2 *pTag = (CIccTagNamedColor2*)m_pTag;
6965
6966 if (nDestSpace!=pTag->GetPCS())
6967 if (nDestSpace!=pTag->GetDeviceSpace())
6968 if (nDestSpace!=icSigNamedData)
6969 return icCmmStatBadSpaceLink;
6970 }
6971
6972 m_nDestSpace = nDestSpace;
6973
6974 return icCmmStatOk;
6975}
6976
6985bool CIccXformNamedColor::IsSrcPCS() const
6986{
6987 if (m_pTag) {
6988 return m_nSrcSpace == m_pTag->GetPCS();
6989 }
6990 else if (m_pArray) {
6991 return IsSpacePCS(m_nSrcSpace);
6992 }
6993 else
6994 return false;
6995}
6996
6997
7006bool CIccXformNamedColor::IsDestPCS() const
7007{
7008 if (m_pTag) {
7009 return m_nDestSpace == m_pTag->GetPCS();
7010 }
7011 else if (m_pArray) {
7012 return IsSpacePCS(m_nDestSpace);
7013 }
7014 else
7015 return false;
7016}
7017
7018
7027CIccXformMpe::CIccXformMpe(CIccTag *pTag)
7028{
7029 if (pTag && pTag->GetType()==icSigMultiProcessElementType)
7030 m_pTag = (CIccTagMultiProcessElement*)pTag;
7031 else
7032 m_pTag = NULL;
7033
7034 m_bUsingAcs = false;
7035 m_pAppliedPCC = NULL;
7036 m_bDeleteAppliedPCC = false;
7037}
7038
7047CIccXformMpe::~CIccXformMpe()
7048{
7049 if (m_pAppliedPCC && m_bDeleteAppliedPCC)
7050 delete m_pAppliedPCC;
7051}
7052
7075CIccXform *CIccXformMpe::Create(CIccProfile *pProfile, bool bInput/* =true */, icRenderingIntent nIntent/* =icUnknownIntent */,
7076 icXformInterp nInterp/* =icInterpLinear */, icXformLutType nLutType/* =icXformLutColor */,
7077 CIccCreateXformHintManager *pHintManager/* =NULL */)
7078{
7079 CIccXform *rv = NULL;
7080 icRenderingIntent nTagIntent = nIntent;
7081 bool bUseSpectralPCS = false;
7082 bool bAbsToRel = false;
7083 icXformLutType nUseLutType = nLutType;
7084 bool bUseColorimeticTags = true;
7085 bool bUseDToB = true;
7086
7087 if (nLutType == icXformLutSpectral) {
7088 nUseLutType = icXformLutColor;
7089 bUseColorimeticTags = false;
7090 }
7091 else if (nLutType == icXformLutColorimetric) {
7092 nUseLutType = icXformLutColor;
7093 bUseDToB = false;
7094 }
7095
7096 if (nTagIntent == icUnknownIntent)
7097 nTagIntent = icPerceptual;
7098
7099 switch (nUseLutType) {
7100 case icXformLutColor:
7101 if (bInput) {
7102 CIccTag *pTag = NULL;
7103 if (bUseDToB) {
7104 pTag = pProfile->FindTag(icSigDToB0Tag + nTagIntent);
7105
7106 if (!pTag && nTagIntent == icAbsoluteColorimetric) {
7107 pTag = pProfile->FindTag(icSigDToB1Tag);
7108 if (pTag)
7109 nTagIntent = icRelativeColorimetric;
7110 }
7111 else if (!pTag && nTagIntent != icAbsoluteColorimetric) {
7112 pTag = pProfile->FindTag(icSigDToB3Tag);
7113 if (pTag) {
7114 nTagIntent = icAbsoluteColorimetric;
7115 bAbsToRel = true;
7116 }
7117 }
7118
7119 if (!pTag) {
7120 pTag = pProfile->FindTag(icSigDToB0Tag);
7121 }
7122 }
7123
7124 //Unsupported elements cause fall back behavior
7125 if (pTag && !pTag->IsSupported())
7126 pTag = NULL;
7127
7128 if (pTag && pProfile->m_Header.spectralPCS) {
7129 bUseSpectralPCS = true;
7130 }
7131
7132 if (bUseColorimeticTags) {
7133 if (!pTag) {
7134 if (nTagIntent == icAbsoluteColorimetric)
7135 nTagIntent = icRelativeColorimetric;
7136 pTag = pProfile->FindTag(icSigAToB0Tag + nTagIntent);
7137 }
7138
7139 if (!pTag) {
7140 pTag = pProfile->FindTag(icSigAToB0Tag);
7141 }
7142 }
7143
7144 if (!pTag) {
7145 if (bUseColorimeticTags && pProfile->m_Header.colorSpace == icSigRgbData && pProfile->m_Header.version < icVersionNumberV5) {
7146 rv = new CIccXformMatrixTRC();
7147 }
7148 else
7149 return NULL;
7150 }
7151 else if (pTag->GetType()==icSigMultiProcessElementType) {
7152 rv = new CIccXformMpe(pTag);
7153 }
7154 else {
7155 switch(pProfile->m_Header.colorSpace) {
7156 case icSigXYZData:
7157 case icSigLabData:
7158 case icSigLuvData:
7159 case icSigYCbCrData:
7160 case icSigYxyData:
7161 case icSigRgbData:
7162 case icSigHsvData:
7163 case icSigHlsData:
7164 case icSigCmyData:
7165 case icSig3colorData:
7166 rv = new CIccXform3DLut(pTag);
7167 break;
7168
7169 case icSigCmykData:
7170 case icSig4colorData:
7171 rv = new CIccXform4DLut(pTag);
7172 break;
7173
7174 default:
7175 rv = new CIccXformNDLut(pTag);
7176 break;
7177 }
7178 }
7179 }
7180 else {
7181 CIccTag *pTag = NULL;
7182
7183 if (bUseDToB) {
7184 pTag = pProfile->FindTag(icSigBToD0Tag + nTagIntent);
7185
7186 if (!pTag && nTagIntent == icAbsoluteColorimetric) {
7187 pTag = pProfile->FindTag(icSigBToD1Tag);
7188 if (pTag)
7189 nTagIntent = icRelativeColorimetric;
7190 }
7191 else if (!pTag && nTagIntent != icAbsoluteColorimetric) {
7192 pTag = pProfile->FindTag(icSigBToD3Tag);
7193 if (pTag) {
7194 nTagIntent = icAbsoluteColorimetric;
7195 bAbsToRel = true;
7196 }
7197 }
7198
7199 if (!pTag) {
7200 pTag = pProfile->FindTag(icSigBToD0Tag);
7201 }
7202 }
7203
7204 //Unsupported elements cause fall back behavior
7205 if (pTag && !pTag->IsSupported())
7206 pTag = NULL;
7207
7208 if (bUseColorimeticTags) {
7209 if (!pTag) {
7210 if (nTagIntent == icAbsoluteColorimetric)
7211 nTagIntent = icRelativeColorimetric;
7212 pTag = pProfile->FindTag(icSigBToA0Tag + nTagIntent);
7213 }
7214
7215 if (!pTag) {
7216 pTag = pProfile->FindTag(icSigBToA0Tag);
7217 }
7218 }
7219
7220 if (!pTag) {
7221 if (bUseColorimeticTags && pProfile->m_Header.colorSpace == icSigRgbData && pProfile->m_Header.version<icVersionNumberV5) {
7222 rv = new CIccXformMatrixTRC();
7223 }
7224 else
7225 return NULL;
7226 }
7227
7228 if (pTag && pTag->GetType()==icSigMultiProcessElementType) {
7229 rv = new CIccXformMpe(pTag);
7230 }
7231 else {
7232 switch(pProfile->m_Header.pcs) {
7233 case icSigXYZData:
7234 case icSigLabData:
7235 rv = new CIccXform3DLut(pTag);
7236
7237 default:
7238 break;
7239 }
7240 }
7241 }
7242 break;
7243
7245 {
7246 CIccTag *pTag = pProfile->FindTag(icSigNamedColor2Tag);
7247 if (!pTag)
7248 return NULL;
7249
7250 rv = new CIccXformNamedColor(pTag, pProfile->m_Header.pcs, pProfile->m_Header.colorSpace,
7251 pProfile->m_Header.spectralPCS,
7252 &pProfile->m_Header.spectralRange,
7253 &pProfile->m_Header.biSpectralRange);
7254 }
7255 break;
7256
7257 case icXformLutPreview:
7258 {
7259 bInput = false;
7260 CIccTag *pTag = pProfile->FindTag(icSigPreview0Tag + nTagIntent);
7261 if (!pTag) {
7262 pTag = pProfile->FindTag(icSigPreview0Tag);
7263 }
7264 if (!pTag) {
7265 return NULL;
7266 }
7267 else {
7268 switch(pProfile->m_Header.pcs) {
7269 case icSigXYZData:
7270 case icSigLabData:
7271 rv = new CIccXform3DLut(pTag);
7272
7273 default:
7274 break;
7275 }
7276 }
7277 }
7278 break;
7279
7280 case icXformLutGamut:
7281 {
7282 bInput = false;
7283 CIccTag *pTag = pProfile->FindTag(icSigGamutTag);
7284 if (!pTag) {
7285 return NULL;
7286 }
7287 else {
7288 switch(pProfile->m_Header.pcs) {
7289 case icSigXYZData:
7290 case icSigLabData:
7291 rv = new CIccXform3DLut(pTag);
7292
7293 default:
7294 break;
7295 }
7296 }
7297 }
7298 break;
7299 }
7300
7301 if (rv) {
7302 rv->SetParams(pProfile, bInput, nIntent, nTagIntent, bUseSpectralPCS, nInterp, pHintManager, bAbsToRel);
7303 }
7304
7305 return rv;
7306}
7307
7317bool CIccXformMpe::IsLateBinding() const
7318{
7319 if (m_pTag)
7320 return m_pTag->IsLateBinding();
7321
7322 return false;
7323}
7324
7334bool CIccXformMpe::IsLateBindingReflectance() const
7335{
7336 if (m_pTag)
7337 return m_pTag->IsLateBindingReflectance();
7338
7339 return false;
7340}
7341
7350IIccProfileConnectionConditions *CIccXformMpe::GetConnectionConditions() const
7351{
7352 if (m_pAppliedPCC)
7353 return m_pAppliedPCC;
7354
7355 return m_pConnectionConditions;
7356}
7357
7368void CIccXformMpe::SetAppliedCC(IIccProfileConnectionConditions *pPCC)
7369{
7370 if (!pPCC) {
7371 if (m_pAppliedPCC && m_bDeleteAppliedPCC) {
7372 delete m_pAppliedPCC;
7373 }
7374 m_pAppliedPCC = NULL;
7375 m_bDeleteAppliedPCC = false;
7376 return;
7377 }
7378
7379 if (m_pTag) {
7380 bool bReflectance = m_pTag->IsLateBindingReflectance();
7381
7382 if (pPCC != (IIccProfileConnectionConditions *)m_pProfile) {
7383 if (!bReflectance) {
7384 const CIccTagSpectralViewingConditions *pViewPCC = pPCC ? pPCC->getPccViewingConditions() : NULL;
7385 const CIccTagSpectralViewingConditions *pViewProfile = m_pProfile ? m_pProfile->getPccViewingConditions() : NULL;
7386
7387 if (pViewPCC && pViewProfile &&
7388 pViewPCC->getStdIllumiant() == pViewProfile->getStdIllumiant() &&
7389 pViewPCC->getIlluminantCCT() == pViewProfile->getIlluminantCCT() &&
7390 pViewPCC->getStdIllumiant() != icIlluminantUnknown) {
7391 m_pAppliedPCC = pPCC;
7392 m_bDeleteAppliedPCC = false;
7393 }
7394 else {
7395 m_pAppliedPCC = new CIccCombinedConnectionConditions(m_pProfile, pPCC, bReflectance);
7396 m_bDeleteAppliedPCC = true;
7397 }
7398 }
7399 else {
7400 m_pAppliedPCC = new CIccCombinedConnectionConditions(m_pProfile, pPCC, bReflectance);
7401 m_bDeleteAppliedPCC = true;
7402 }
7403 }
7404 else {
7405 m_pAppliedPCC = NULL;
7406 }
7407 }
7408 else {
7409 m_pAppliedPCC = pPCC;
7410 m_bDeleteAppliedPCC = false;
7411 }
7412}
7413
7414
7426icStatusCMM CIccXformMpe::Begin()
7427{
7428 icStatusCMM status;
7429 status = CIccXform::Begin();
7430
7431 if (status != icCmmStatOk)
7432 return status;
7433
7434 if (!m_pTag) {
7435 return icCmmStatInvalidLut;
7436 }
7437
7438 if (!m_pTag->Begin(icElemInterpLinear, GetProfileCC(), GetConnectionConditions(), GetCmmEnvVarLookup())) {
7440 }
7441
7442 return icCmmStatOk;
7443}
7444
7445
7455CIccApplyXform *CIccXformMpe::GetNewApply(icStatusCMM &status)
7456{
7457 if (!m_pTag)
7458 return NULL;
7459
7460 CIccApplyXformMpe *rv= new CIccApplyXformMpe(this);
7461
7462 if (!rv) {
7463 status = icCmmStatAllocErr;
7464 return NULL;
7465 }
7466
7467 rv->m_pApply = m_pTag->GetNewApply();
7468 if (!rv->m_pApply) {
7469 status = icCmmStatAllocErr;
7470 delete rv;
7471 return NULL;
7472 }
7473
7474 status = icCmmStatOk;
7475 return rv;
7476}
7477
7478
7492void CIccXformMpe::Apply(CIccApplyXform* pApply, icFloatNumber *DstPixel, const icFloatNumber *SrcPixel) const
7493{
7494 const CIccTagMultiProcessElement *pTag = m_pTag;
7495
7496 icFloatNumber temp[3];
7497 if (!m_bInput || m_bPcsAdjustXform) { //PCS comming in?
7498 if (m_nIntent != icAbsoluteColorimetric || m_nIntent != m_nTagIntent) { //B2D3 tags don't need abs conversion
7499 if (m_bSrcPcsConversion)
7500 SrcPixel = CheckSrcAbs(pApply, SrcPixel);
7501 }
7502
7503 //Since MPE tags use "real" values for PCS we need to convert from
7504 //internal encoding used by IccProfLib
7505 switch (GetSrcSpace()) {
7506 case icSigXYZData:
7507 memcpy(&temp[0], SrcPixel, 3*sizeof(icFloatNumber));
7508 icXyzFromPcs(temp);
7509 SrcPixel = &temp[0];
7510 break;
7511
7512 case icSigLabData:
7513 memcpy(&temp[0], SrcPixel, 3*sizeof(icFloatNumber));
7514 icLabFromPcs(temp);
7515 SrcPixel = &temp[0];
7516 break;
7517
7518 default:
7519 break;
7520 }
7521 }
7522
7523 //Note: pApply should be a CIccApplyXformMpe type here
7524 CIccApplyXformMpe *pApplyMpe = (CIccApplyXformMpe *)pApply;
7525
7526 pTag->Apply(pApplyMpe->m_pApply, DstPixel, SrcPixel);
7527
7528 if (m_bInput) { //PCS going out?
7529 //Since MPE tags use "real" values for PCS we need to convert to
7530 //internal encoding used by IccProfLib
7531 switch(GetDstSpace()) {
7532 case icSigXYZData:
7533 icXyzToPcs(DstPixel);
7534 break;
7535
7536 case icSigLabData:
7537 icLabToPcs(DstPixel);
7538 break;
7539
7540 default:
7541 break;
7542 }
7543
7544 if (m_nIntent != icAbsoluteColorimetric || m_nIntent != m_nTagIntent) { //D2B3 tags don't need abs conversion
7545 if (m_bDstPcsConversion)
7546 CheckDstAbs(DstPixel);
7547 }
7548 }
7549}
7550
7559CIccApplyXformMpe::CIccApplyXformMpe(CIccXformMpe *pXform) : CIccApplyXform(pXform)
7560{
7561 m_pApply = NULL;
7562}
7563
7572CIccApplyXformMpe::~CIccApplyXformMpe()
7573{
7574}
7575
7576
7588CIccApplyCmm::CIccApplyCmm(CIccCmm *pCmm)
7589{
7590 m_pCmm = pCmm;
7591 //m_pPCS = m_pCmm->GetPCS();
7592
7593 m_Xforms = new CIccApplyXformList;
7594 m_Xforms->clear();
7595
7596 m_Pixel = NULL;
7597 m_Pixel2 = NULL;
7598}
7599
7608CIccApplyCmm::~CIccApplyCmm()
7609{
7610 if (m_Xforms) {
7611 CIccApplyXformList::iterator i;
7612
7613 for (i=m_Xforms->begin(); i!=m_Xforms->end(); i++) {
7614 if (i->ptr)
7615 delete i->ptr;
7616 }
7617
7618 delete m_Xforms;
7619 }
7620
7621// if (m_pPCS)
7622// delete m_pPCS;
7623
7624 if (m_Pixel)
7625 free(m_Pixel);
7626 if (m_Pixel2)
7627 free(m_Pixel2);
7628}
7629
7630bool CIccApplyCmm::InitPixel()
7631{
7632 if (m_Pixel && m_Pixel2)
7633 return true;
7634
7635 icUInt16Number nSamples = 16;
7636 CIccApplyXformList::iterator i;
7637
7638 for (i=m_Xforms->begin(); i!=m_Xforms->end(); i++) {
7639 if (i->ptr->GetXform()) {
7640 icUInt16Number nXformSamples = i->ptr->GetXform()->GetNumDstSamples();
7641 if (nXformSamples>nSamples)
7642 nSamples=nXformSamples;
7643 }
7644 }
7645 m_Pixel = (icFloatNumber*)malloc(nSamples*sizeof(icFloatNumber));
7646 m_Pixel2 = (icFloatNumber*)malloc(nSamples*sizeof(icFloatNumber));
7647
7648 if (!m_Pixel || !m_Pixel2)
7649 return false;
7650
7651 return true;
7652}
7653
7654//#define DEBUG_CMM_APPLY
7655
7656#ifdef DEBUG_CMM_APPLY
7657static void DumpCmmApplyPixel(int nCount, const icFloatNumber* pPixel, icUInt16Number nSamples)
7658{
7659 printf("Xfm%d:", nCount);
7660 for (icUInt16Number i = 0; i < nSamples; i++) {
7661 if (i)
7662 printf(",");
7663 printf(" %.3f", pPixel[i]);
7664 }
7665 printf("\n");
7666
7667}
7668#endif
7669
7682icStatusCMM CIccApplyCmm::Apply(icFloatNumber *DstPixel, const icFloatNumber *SrcPixel)
7683{
7684 icFloatNumber *pDst, *pTmp;
7685 const icFloatNumber *pSrc;
7686 CIccApplyXformList::iterator i;
7687 const CIccXform *pLastXform;
7688 int j, n = (int)m_Xforms->size();
7689 bool bNoClip;
7690
7691 if (!n)
7692 return icCmmStatBadXform;
7693
7694 if (!m_Pixel && !InitPixel())
7695 return icCmmStatAllocErr;
7696
7697 pSrc = SrcPixel;
7698 pDst = m_Pixel;
7699
7700#ifdef DEBUG_CMM_APPLY
7701 int nCount = 0;
7702 printf("Start ApplyCmm\n");
7703 DumpCmmApplyPixel(nCount++, pSrc, icGetSpaceSamples(m_pCmm->m_nSrcSpace));
7704#endif
7705
7706 if (n > 1) {
7707 for (j = 0, i = m_Xforms->begin(); j < n - 1 && i != m_Xforms->end(); i++, j++) {
7708 i->ptr->Apply(pDst, pSrc);
7709
7710#ifdef DEBUG_CMM_APPLY
7711 DumpCmmApplyPixel(nCount++, pDst, i->ptr->GetXform()->GetNumDstSamples());
7712#endif
7713
7714 pTmp = (icFloatNumber*)pSrc;
7715 pSrc = pDst;
7716 pDst = (pTmp == SrcPixel) ? m_Pixel2 : pTmp;
7717 }
7718
7719 pLastXform = i->ptr->GetXform();
7720 i->ptr->Apply(DstPixel, pSrc);
7721 bNoClip = pLastXform->NoClipPCS();
7722 }
7723 else { // n == 1
7724 i = m_Xforms->begin();
7725
7726 pLastXform = i->ptr->GetXform();
7727 i->ptr->Apply(DstPixel, SrcPixel);
7728
7729#ifdef DEBUG_CMM_APPLY
7730 DumpCmmApplyPixel(nCount++, DstPixel, pLastXform->GetNumDstSamples());
7731#endif
7732
7733 bNoClip = pLastXform->NoClipPCS();
7734 }
7735
7736 CIccPCSUtil::CheckLast(DstPixel, m_pCmm->m_nDestSpace, bNoClip);
7737
7738#ifdef DEBUG_CMM_APPLY
7739 DumpCmmApplyPixel(nCount, DstPixel, icGetSpaceSamples(m_pCmm->m_nDestSpace));
7740 printf("End ApplyCmm\n\n");
7741#endif
7742
7743 return icCmmStatOk;
7744}
7745
7758
7759void CIccPCSUtil::CheckLast(icFloatNumber* Dst, icColorSpaceSignature destSpace, bool bNoClip)
7760{
7761 switch (destSpace) {
7762 case icSigLabData:
7763 CIccPCSUtil::XyzToLab(Dst, Dst, bNoClip);
7764 break;
7765
7766 case icSigLab2Data:
7767 CIccPCSUtil::XyzToLab2(Dst, Dst, bNoClip);
7768 break;
7769
7770 case icSigLuvData:
7771 // Uncomment and implement if needed
7772 // CIccPCSUtil::XyzToLuv(Dst, Dst, bNoClip);
7773 break;
7774
7775 default:
7776 // No transformation or clipping needed
7777 break;
7778 }
7779}
7780
7793icStatusCMM CIccApplyCmm::Apply(icFloatNumber *DstPixel, const icFloatNumber *SrcPixel, icUInt32Number nPixels)
7794{
7795 icFloatNumber *pDst, *pTmp;
7796 const icFloatNumber *pSrc;
7797 CIccApplyXformList::iterator i;
7798 int j, n = (int)m_Xforms->size();
7800
7801 if (!n)
7802 return icCmmStatBadXform;
7803
7804 if (!m_Pixel && !InitPixel()) {
7805 return icCmmStatAllocErr;
7806 }
7807
7808 for (k=0; k<nPixels; k++) {
7809 pSrc = SrcPixel;
7810 pDst = m_Pixel;
7811
7812 if (n>1) {
7813 for (j=0, i=m_Xforms->begin(); j<n-1 && i!=m_Xforms->end(); i++, j++) {
7814
7815 i->ptr->Apply(pDst, pSrc);
7816 pTmp = (icFloatNumber*)pSrc;
7817 pSrc = pDst;
7818 if (pTmp==SrcPixel)
7819 pDst = m_Pixel2;
7820 else
7821 pDst = pTmp;
7822 }
7823
7824 i->ptr->Apply(DstPixel, pSrc);
7825 }
7826 else if (n==1) {
7827 i = m_Xforms->begin();
7828 i->ptr->Apply(DstPixel, SrcPixel);
7829 }
7830
7831 DstPixel += m_pCmm->GetDestSamples();
7832 SrcPixel += m_pCmm->GetSourceSamples();
7833 }
7834
7835 return icCmmStatOk;
7836}
7837
7838void CIccApplyCmm::AppendApplyXform(CIccApplyXform *pApplyXform)
7839{
7840 CIccApplyXformPtr ptr;
7841 ptr.ptr = pApplyXform;
7842
7843 m_Xforms->push_back(ptr);
7844}
7845
7859CIccCmm::CIccCmm(icColorSpaceSignature nSrcSpace /*=icSigUnknownData*/,
7860 icColorSpaceSignature nDestSpace /*=icSigUnknownData*/,
7861 bool bFirstInput /*=true*/)
7862{
7863 m_bValid = false;
7864
7865 m_bLastInput = !bFirstInput;
7866 m_nSrcSpace = nSrcSpace;
7867 m_nDestSpace = nDestSpace;
7868
7869 m_nLastSpace = nSrcSpace;
7870 m_nLastIntent = icUnknownIntent;
7871
7872 m_Xforms = new CIccXformList;
7873 m_Xforms->clear();
7874
7875 m_pApply = NULL;
7876}
7877
7886CIccCmm::~CIccCmm()
7887{
7888 if (m_Xforms) {
7889 CIccXformList::iterator i;
7890
7891 for (i=m_Xforms->begin(); i!=m_Xforms->end(); i++) {
7892 if (i->ptr)
7893 delete i->ptr;
7894 }
7895
7896 delete m_Xforms;
7897 }
7898
7899 if (m_pApply)
7900 delete m_pApply;
7901}
7902
7903const icChar* CIccCmm::GetStatusText(icStatusCMM stat)
7904{
7905 switch (stat) {
7906 case icCmmStatBad:
7907 return "Bad CMM";
7908 case icCmmStatOk:
7909 return "OK";
7911 return "Cannot open profile";
7913 return "Invalid space link";
7915 return "Invalid profile";
7916 case icCmmStatBadXform:
7917 return "Invalid profile transform";
7919 return "Invalid Look-Up Table";
7921 return "Missing tag in profile";
7923 return "Color not found";
7925 return "Incorrect Apply object";
7927 return "Invalid color encoding used";
7928 case icCmmStatAllocErr:
7929 return "Memory allocation error";
7931 return "Invalid Look-Up Table type";
7933 return "Identity transform used";
7935 return "Unsupported PCS Link used";
7937 return "Invalid profile connection";
7939 return "Invalid tint transform";
7941 return "Too many samples used";
7943 return "Invalid MCS link connection";
7944 default:
7945 return "Unknown CMM Status value";
7946
7947 }
7948}
7949
7968icStatusCMM CIccCmm::AddXform(const icChar *szProfilePath,
7969 icRenderingIntent nIntent /*=icUnknownIntent*/,
7970 icXformInterp nInterp /*icXformInterp*/,
7971 IIccProfileConnectionConditions *pPcc/*=NULL*/,
7972 icXformLutType nLutType /*=icXformLutColor*/,
7973 bool bUseD2BxB2DxTags /*=true*/,
7974 CIccCreateXformHintManager *pHintManager /*=NULL*/,
7975 bool bUseSubProfile /*=false*/)
7976{
7977 CIccProfile *pProfile = OpenIccProfile(szProfilePath, bUseSubProfile);
7978
7979 if (!pProfile)
7981
7982 icStatusCMM rv = AddXform(pProfile, nIntent, nInterp, pPcc, nLutType, bUseD2BxB2DxTags, pHintManager);
7983
7984 if (rv != icCmmStatOk)
7985 delete pProfile;
7986
7987 return rv;
7988}
7989
7990
8012icStatusCMM CIccCmm::AddXform(icUInt8Number *pProfileMem,
8013 icUInt32Number nProfileLen,
8014 icRenderingIntent nIntent /*=icUnknownIntent*/,
8015 icXformInterp nInterp /*icXformInterp*/,
8016 IIccProfileConnectionConditions *pPcc/*=NULL*/,
8017 icXformLutType nLutType /*=icXformLutColor*/,
8018 bool bUseD2BxB2DxTags /*=true*/,
8019 CIccCreateXformHintManager *pHintManager /*=NULL*/,
8020 bool bUseSubProfile /*=false*/)
8021{
8022 CIccMemIO *pFile = new CIccMemIO;
8023
8024 if (!pFile || !pFile->Attach(pProfileMem, nProfileLen, bUseSubProfile))
8026
8027 CIccProfile *pProfile = new CIccProfile;
8028
8029 if (!pProfile)
8031
8032 if (!pProfile->Attach(pFile)) {
8033 delete pFile;
8034 delete pProfile;
8036 }
8037
8038 icStatusCMM rv = AddXform(pProfile, nIntent, nInterp, pPcc, nLutType, bUseD2BxB2DxTags, pHintManager);
8039
8040 if (rv != icCmmStatOk)
8041 delete pProfile;
8042
8043 return rv;
8044}
8045
8046
8066icStatusCMM CIccCmm::AddXform(CIccProfile *pProfile,
8067 icRenderingIntent nIntent /*=icUnknownIntent*/,
8068 icXformInterp nInterp /*=icInterpLinear*/,
8069 IIccProfileConnectionConditions *pPcc/*=NULL*/,
8070 icXformLutType nLutType /*=icXformLutColor*/,
8071 bool bUseD2BxB2DxTags /*=true*/,
8072 CIccCreateXformHintManager *pHintManager /*=NULL*/)
8073{
8074 icColorSpaceSignature nSrcSpace, nDstSpace;
8075 bool bInput = !m_bLastInput;
8076
8077 if (!pProfile)
8079
8080 switch(pProfile->m_Header.deviceClass) {
8084 nIntent = icPerceptual;
8085 nLutType = icXformLutMCS;
8086
8087 default:
8088 break;
8089 }
8090
8091 switch (nLutType) {
8092 case icXformLutColor:
8094 case icXformLutSpectral:
8095 {
8096 //Check pProfile if nIntent and input can be found.
8097 if (bInput) {
8098 nSrcSpace = pProfile->m_Header.colorSpace;
8099
8100 if (nLutType == icXformLutSpectral || (bUseD2BxB2DxTags && pProfile->m_Header.spectralPCS && nLutType != icXformLutColorimetric))
8101 nDstSpace = (icColorSpaceSignature)pProfile->m_Header.spectralPCS;
8102 else
8103 nDstSpace = pProfile->m_Header.pcs;
8104 }
8105 else {
8106 if (pProfile->m_Header.deviceClass == icSigLinkClass) {
8107 return icCmmStatBadSpaceLink;
8108 }
8109 if (pProfile->m_Header.deviceClass == icSigAbstractClass) {
8110 bInput = true;
8111 nIntent = icPerceptual; // Note: icPerceptualIntent = 0
8112 }
8113
8114 if (nLutType == icXformLutSpectral || (bUseD2BxB2DxTags && pProfile->m_Header.spectralPCS && nLutType != icXformLutColorimetric))
8115 nSrcSpace = (icColorSpaceSignature)pProfile->m_Header.spectralPCS;
8116 else
8117 nSrcSpace = pProfile->m_Header.pcs;
8118
8119 nDstSpace = pProfile->m_Header.colorSpace;
8120 }
8121 }
8122 break;
8123
8124 case icXformLutPreview:
8125 nSrcSpace = pProfile->m_Header.pcs;
8126 nDstSpace = pProfile->m_Header.pcs;
8127 bInput = false;
8128 break;
8129
8130 case icXformLutGamut:
8131 nSrcSpace = pProfile->m_Header.pcs;
8132 nDstSpace = icSigGamutData;
8133 bInput = true;
8134 break;
8135
8137 if (!bInput)
8138 return icCmmStatBadSpaceLink;
8139 nSrcSpace = pProfile->m_Header.colorSpace;
8140 nDstSpace = icSigBRDFParameters;
8141 bInput = true;
8142 break;
8143
8145 if (!bInput)
8146 return icCmmStatBadSpaceLink;
8147 nSrcSpace = icSigBRDFDirect;
8148 nDstSpace = pProfile->m_Header.pcs;
8149 bInput = true;
8150 break;
8151
8153 if (!bInput)
8154 return icCmmStatBadSpaceLink;
8155 nSrcSpace = (icColorSpaceSignature)pProfile->m_Header.mcs;
8156 nDstSpace = icSigBRDFParameters;
8157 break;
8158
8159 case icXformLutMCS:
8160 if (bInput) {
8161 nSrcSpace = pProfile->m_Header.colorSpace;
8162 nDstSpace = (icColorSpaceSignature)pProfile->m_Header.mcs;
8163 }
8164 else {
8165 if (m_Xforms->size()) {
8166 CIccXformList::iterator prev = --(m_Xforms->end());
8167
8168 //Make sure previous profile connects with an icXformLutMCS
8169 if (prev->ptr->GetXformType()!=icXformLutMCS) {
8170 //check to see if we can convert previous xform to connect via an MCS
8171 if (!prev->ptr->GetProfile()->m_Header.mcs) {
8172 return icCmmStatBadMCSLink;
8173 }
8174
8175 CIccXform *pPrev = prev->ptr;
8176 CIccXform *pNew = CIccXform::Create(pPrev->GetProfilePtr(), pPrev->IsInput(), pPrev->GetIntent(), pPrev->GetInterp(),
8177 pPrev->GetConnectionConditions(), icXformLutMCS, bUseD2BxB2DxTags, pHintManager);
8178
8179 if (pNew) {
8180 pPrev->DetachAll();
8181 delete pPrev;
8182 }
8183
8184 prev->ptr = pNew;
8185
8186 }
8187 }
8188 else {
8189 return icCmmStatBadMCSLink;
8190 }
8191
8192 nSrcSpace = (icColorSpaceSignature)pProfile->m_Header.mcs;
8193 if (pProfile->m_Header.deviceClass==icSigMaterialVisualizationClass) {
8194 if (bUseD2BxB2DxTags && pProfile->m_Header.spectralPCS) {
8195 nDstSpace = (icColorSpaceSignature)pProfile->m_Header.spectralPCS;
8196 }
8197 else {
8198 nDstSpace = pProfile->m_Header.pcs;
8199 }
8200 }
8201 else if (pProfile->m_Header.deviceClass==icSigMaterialLinkClass) {
8202 nDstSpace = pProfile->m_Header.colorSpace;
8203 }
8204 else {
8205 return icCmmStatBadSpaceLink;
8206 }
8207 }
8208 break;
8209
8210 default:
8211 return icCmmStatBadLutType;
8212 }
8213
8214 //Make sure colorspaces match with previous xforms
8215 if (!m_Xforms->size()) {
8216 if (m_nSrcSpace == icSigUnknownData) {
8217 m_nLastSpace = nSrcSpace;
8218 m_nSrcSpace = nSrcSpace;
8219 }
8220 else if (!IsCompatSpace(m_nSrcSpace, nSrcSpace)) {
8221 return icCmmStatBadSpaceLink;
8222 }
8223 }
8224 else if (!IsCompatSpace(m_nLastSpace, nSrcSpace)) {
8225 return icCmmStatBadSpaceLink;
8226 }
8227
8228 if (nSrcSpace==icSigNamedData)
8229 return icCmmStatBadSpaceLink;
8230
8231 //Automatic creation of intent from header/last profile
8232 if (nIntent==icUnknownIntent) {
8233 if (bInput) {
8234 nIntent = (icRenderingIntent)pProfile->m_Header.renderingIntent;
8235 }
8236 else {
8237 nIntent = m_nLastIntent;
8238 }
8239 if (nIntent == icUnknownIntent)
8240 nIntent = icPerceptual;
8241 }
8242
8243 CIccXformPtr Xform;
8244
8245 Xform.ptr = CIccXform::Create(pProfile, bInput, nIntent, nInterp, pPcc, nLutType, bUseD2BxB2DxTags, pHintManager);
8246
8247 if (!Xform.ptr) {
8248 return icCmmStatBadXform;
8249 }
8250
8251 if (pProfile->m_Header.deviceClass==icSigMaterialVisualizationClass) {
8252 bInput = true;
8253 }
8254
8255 m_nLastSpace = nDstSpace;
8256 m_nLastIntent = nIntent;
8257 m_bLastInput = bInput;
8258
8259 m_Xforms->push_back(Xform);
8260
8261 return icCmmStatOk;
8262}
8263
8283icStatusCMM CIccCmm::AddXform(CIccProfile *pProfile,
8284 CIccTag *pXformTag,
8285 icRenderingIntent nIntent/*= icUnknownIntent*/,
8286 icXformInterp nInterp /*=icInterpLinear*/,
8287 IIccProfileConnectionConditions *pPcc/*=NULL*/,
8288 bool bUseSpectralPCS /*=false*/,
8289 CIccCreateXformHintManager *pHintManager /*=NULL*/)
8290{
8291 icColorSpaceSignature nSrcSpace, nDstSpace;
8292 bool bInput = !m_bLastInput;
8293
8294 if (!pProfile)
8296
8297 switch (pProfile->m_Header.deviceClass) {
8301 return icCmmStatBadLutType;
8302
8303 default:
8304 break;
8305 }
8306
8307 //Check pProfile if nIntent and input can be found.
8308 if (bInput) {
8309 nSrcSpace = pProfile->m_Header.colorSpace;
8310
8311 if (bUseSpectralPCS && pProfile->m_Header.spectralPCS)
8312 nDstSpace = (icColorSpaceSignature)pProfile->m_Header.spectralPCS;
8313 else {
8314 nDstSpace = pProfile->m_Header.pcs;
8315 bUseSpectralPCS = false;
8316 }
8317 }
8318 else {
8319 if (pProfile->m_Header.deviceClass == icSigLinkClass) {
8320 return icCmmStatBadSpaceLink;
8321 }
8322 if (pProfile->m_Header.deviceClass == icSigAbstractClass) {
8323 bInput = true;
8324 nIntent = icPerceptual; // Note: icPerceptualIntent = 0
8325 }
8326
8327 if (bUseSpectralPCS && pProfile->m_Header.spectralPCS)
8328 nSrcSpace = (icColorSpaceSignature)pProfile->m_Header.spectralPCS;
8329 else {
8330 nSrcSpace = pProfile->m_Header.pcs;
8331 bUseSpectralPCS = false;
8332 }
8333
8334 nDstSpace = pProfile->m_Header.colorSpace;
8335 }
8336
8337 //Make sure colorspaces match with previous xforms
8338 if (!m_Xforms->size()) {
8339 if (m_nSrcSpace == icSigUnknownData) {
8340 m_nLastSpace = nSrcSpace;
8341 m_nSrcSpace = nSrcSpace;
8342 }
8343 else if (!IsCompatSpace(m_nSrcSpace, nSrcSpace)) {
8344 return icCmmStatBadSpaceLink;
8345 }
8346 }
8347 else if (!IsCompatSpace(m_nLastSpace, nSrcSpace)) {
8348 return icCmmStatBadSpaceLink;
8349 }
8350
8351 if (nSrcSpace == icSigNamedData)
8352 return icCmmStatBadSpaceLink;
8353
8354 //Automatic creation of intent from header/last profile
8355 if (nIntent == icUnknownIntent) {
8356 if (bInput) {
8357 nIntent = (icRenderingIntent)pProfile->m_Header.renderingIntent;
8358 }
8359 else {
8360 nIntent = m_nLastIntent;
8361 }
8362 if (nIntent == icUnknownIntent)
8363 nIntent = icPerceptual;
8364 }
8365
8366 CIccXformPtr Xform;
8367
8368 Xform.ptr = CIccXform::Create(pProfile, pXformTag, bInput, nIntent, nInterp, pPcc, bUseSpectralPCS, pHintManager);
8369
8370 if (!Xform.ptr) {
8371 return icCmmStatBadXform;
8372 }
8373
8374 m_nLastSpace = nDstSpace;
8375 m_nLastIntent = nIntent;
8376 m_bLastInput = bInput;
8377
8378 m_Xforms->push_back(Xform);
8379
8380 return icCmmStatOk;
8381}
8382
8402icStatusCMM CIccCmm::AddXform(CIccProfile &Profile,
8403 icRenderingIntent nIntent /*=icUnknownIntent*/,
8404 icXformInterp nInterp /*=icInterpLinear*/,
8405 IIccProfileConnectionConditions *pPcc/*=NULL*/,
8406 icXformLutType nLutType /*=icXformLutColor*/,
8407 bool bUseD2BxB2DxTags /*=true*/,
8408 CIccCreateXformHintManager *pHintManager /*=NULL*/)
8409{
8410 CIccProfile *pProfile = new CIccProfile(Profile);
8411
8412 if (!pProfile)
8413 return icCmmStatAllocErr;
8414
8415 icStatusCMM stat = AddXform(pProfile, nIntent, nInterp, pPcc, nLutType, bUseD2BxB2DxTags, pHintManager);
8416
8417 if (stat != icCmmStatOk)
8418 delete pProfile;
8419
8420 return stat;
8421}
8422
8423icStatusCMM CIccCmm::CheckPCSConnections(bool bUsePCSConversions/*=false*/)
8424{
8426
8427 CIccXformList::iterator last, next;
8428 CIccXformList xforms;
8429 CIccXformPtr ptr;
8430 bool bUsesPcsXforms = false;
8431
8432 next=m_Xforms->begin();
8433
8434 if (next!=m_Xforms->end()) {
8435 last = next;
8436 next++;
8437
8438 icColorSpaceSignature lastSpace = last->ptr->GetSrcSpace();
8439 if (!last->ptr->IsInput() && IsSpaceColorimetricPCS(lastSpace) && GetSourceSpace() !=lastSpace) {
8440 CIccPcsXform* pPcs = new CIccPcsXform();
8441
8442 if (!pPcs) {
8443 return icCmmStatAllocErr;
8444 }
8445
8446 rv = pPcs->ConnectFirst(last->ptr, GetSourceSpace());
8447
8448 if (rv != icCmmStatOk && rv != icCmmStatIdentityXform) {
8449 delete pPcs;
8450 return rv;
8451 }
8452
8453 if (rv != icCmmStatIdentityXform) {
8454 ptr.ptr = pPcs;
8455 xforms.push_back(ptr);
8456
8457 bUsesPcsXforms = true;
8458 }
8459 else {
8460 delete pPcs;
8461 }
8462 }
8463
8464 xforms.push_back(*last);
8465
8466 for (;next!=m_Xforms->end(); last=next, next++) {
8467 if ((last->ptr->IsInput() && last->ptr->IsMCS() && next->ptr->IsMCS()) ||
8468 (IsSpaceSpectralPCS(last->ptr->GetDstSpace()) || IsSpaceSpectralPCS(next->ptr->GetSrcSpace())) ||
8469 (!bUsePCSConversions &&
8470 (IsSpaceColorimetricPCS(last->ptr->GetDstSpace()) || IsSpaceColorimetricPCS(next->ptr->GetSrcSpace())))) {
8471 last->ptr->SetDstPCSConversion(false);
8472 next->ptr->SetSrcPCSConversion(false);
8473 CIccPcsXform *pPcs = new CIccPcsXform();
8474
8475 if (!pPcs) {
8476 return icCmmStatAllocErr;
8477 }
8478
8479 rv = pPcs->Connect(last->ptr, next->ptr);
8480
8481 if (rv!=icCmmStatOk && rv!=icCmmStatIdentityXform)
8482 return rv;
8483
8484 if (rv!=icCmmStatIdentityXform) {
8485 ptr.ptr = pPcs;
8486 xforms.push_back(ptr);
8487
8488 bUsesPcsXforms = true;
8489 }
8490 else {
8491 delete pPcs;
8492 }
8493 }
8494 xforms.push_back(*next);
8495 }
8496
8497 lastSpace = last->ptr->GetDstSpace();
8498 if (last->ptr->IsInput() && IsSpaceColorimetricPCS(lastSpace) &&
8499 (last->ptr->NeedAdjustPCS() || GetDestSpace() != lastSpace)) {
8500 CIccPcsXform* pPcs = new CIccPcsXform();
8501
8502 if (!pPcs) {
8503 return icCmmStatAllocErr;
8504 }
8505 rv = pPcs->ConnectLast(last->ptr, GetDestSpace());
8506
8507 if (rv != icCmmStatOk && rv != icCmmStatIdentityXform)
8508 return rv;
8509
8510 if (rv != icCmmStatIdentityXform) {
8511 ptr.ptr = pPcs;
8512 xforms.push_back(ptr);
8513
8514 bUsesPcsXforms = true;
8515 }
8516 else {
8517 delete pPcs;
8518 }
8519 }
8520 }
8521
8522
8523 if (bUsesPcsXforms) {
8524 *m_Xforms = xforms;
8525 }
8526
8527 return rv;
8528}
8529
8530icStatusCMM CIccCmm::CheckPCSRangeConversions()
8531{
8533
8534 CIccXformList::iterator last, next;
8535 CIccXformList xforms;
8536 CIccXformPtr ptr;
8537 bool bUsesRangeConversion = false;
8538
8539 next = m_Xforms->begin();
8540
8541 if (next != m_Xforms->end()) {
8542 last = next;
8543 next++;
8544
8545 xforms.push_back(*last);
8546
8547 for (; next != m_Xforms->end(); last = next, next++) {
8548 //Add extended PCS to standard PCS conversion as needed
8549 if (last->ptr->IsInput() && last->ptr->IsExtendedPCS() && IsSpaceColorimetricPCS(last->ptr->GetDstSpace()) &&
8550 !next->ptr->IsExtendedPCS()) {
8551 CIccProfile* pProfile = last->ptr->GetProfilePtr();
8552 CIccTag* pTag = pProfile->FindTag(icSigHToS0Tag + last->ptr->GetIntent());
8553 if (!pTag) {
8554 pTag = pProfile->FindTag(icSigHToS0Tag);
8555 if (!pTag) {
8556 pTag = pProfile->FindTag(icSigHToS1Tag);
8557 }
8558 }
8559 //If we find the HToSxTag then create a transform for it and inject it into the transform list
8560 if (pTag) {
8561 ptr.ptr = CIccXform::Create(pProfile, pTag, true, last->ptr->GetIntent(), last->ptr->GetInterp(),
8562 last->ptr->GetConnectionConditions(), false);
8563 if (ptr.ptr) {
8564 ptr.ptr->ShareProfile(); //Indicate that profile is shared (so it won't be deleted)
8565 ptr.ptr->SetPcsAdjustXform(); // Indicates that transform should be treated as abstract
8566 ptr.ptr->AttachCmmEnvVarLookup(last->ptr->GetCmmEnvVarLookup());
8567 xforms.push_back(ptr);
8568 bUsesRangeConversion = true;
8569 }
8570 }
8571 }
8572
8573 xforms.push_back(*next);
8574 }
8575 }
8576
8577 if (bUsesRangeConversion) {
8578 *m_Xforms = xforms;
8579 }
8580
8581 return rv;
8582}
8583
8584
8595void CIccCmm::SetLateBindingCC()
8596{
8597 CIccXformList::iterator i;
8598 CIccXform *pLastXform = NULL;
8599
8600 for (i=m_Xforms->begin(); i!=m_Xforms->end(); i++) {
8601 if (i->ptr->IsInput()) {
8602 if (i->ptr->IsLateBinding()) {
8603 CIccXformList::iterator j=i;
8604 j++;
8605 if (j!=m_Xforms->end()) {
8606 if (j->ptr->IsLateBinding()) {
8607 i->ptr->SetAppliedCC(i->ptr->GetConnectionConditions());
8608 j->ptr->SetAppliedCC(i->ptr->GetConnectionConditions());
8609 pLastXform = i->ptr;
8610 }
8611 else {
8612 i->ptr->SetAppliedCC(i->ptr->GetConnectionConditions());
8613 j->ptr->SetAppliedCC(j->ptr->GetConnectionConditions());
8614 pLastXform = NULL;
8615 }
8616 }
8617 else {
8618 i->ptr->SetAppliedCC(i->ptr->GetConnectionConditions());
8619 pLastXform = NULL;
8620 }
8621 }
8622 else if (IsSpaceSpectralPCS(i->ptr->GetDstSpace())) {
8623 CIccXformList::iterator j=i;
8624 j++;
8625 if (j!=m_Xforms->end()) {
8626 if (j->ptr->IsLateBinding()) {
8627 j->ptr->SetAppliedCC(i->ptr->GetConnectionConditions());
8628 pLastXform = i->ptr;
8629 }
8630 else if (!j->ptr->IsAbstract()){
8631 j->ptr->SetAppliedCC(j->ptr->GetConnectionConditions());
8632 pLastXform = NULL;
8633 }
8634 }
8635 }
8636 else {
8637 pLastXform = NULL;
8638 }
8639 }
8640 else {
8641 if (!pLastXform)
8642 i->ptr->SetAppliedCC(i->ptr->GetConnectionConditions());
8643 else
8644 pLastXform = NULL;
8645 }
8646 }
8647}
8648
8649
8660icStatusCMM CIccCmm::Begin(bool bAllocApplyCmm/*=true*/, bool bUsePCSConversions/*=false*/)
8661{
8662 if (m_pApply)
8663 return icCmmStatOk;
8664
8665 if (m_nDestSpace==icSigUnknownData) {
8666 m_nDestSpace = m_nLastSpace;
8667 }
8668 else if (!IsCompatSpace(m_nDestSpace, m_nLastSpace)) {
8669 return icCmmStatBadSpaceLink;
8670 }
8671
8672 if (m_nSrcSpace==icSigNamedData || m_nDestSpace==icSigNamedData) {
8673 return icCmmStatBadSpaceLink;
8674 }
8675
8676 CheckPCSRangeConversions();
8677 SetLateBindingCC();
8678
8679 icStatusCMM rv;
8680 CIccXformList::iterator i;
8681
8682 for (i=m_Xforms->begin(); i!=m_Xforms->end(); i++) {
8683
8684 rv = i->ptr->Begin();
8685
8686 if (rv!= icCmmStatOk)
8687 return rv;
8688 }
8689
8690 rv = CheckPCSConnections(bUsePCSConversions);
8691 if (rv != icCmmStatOk && rv!=icCmmStatIdentityXform)
8692 return rv;
8693
8694 if (bAllocApplyCmm) {
8695 m_pApply = GetNewApplyCmm(rv);
8696 }
8697 else
8698 rv = icCmmStatOk;
8699
8700 return rv;
8701}
8702
8703
8715CIccApplyCmm *CIccCmm::GetNewApplyCmm(icStatusCMM &status)
8716{
8717 CIccApplyCmm *pApply = new CIccApplyCmm(this);
8718
8719 if (!pApply) {
8720 status = icCmmStatAllocErr;
8721 return NULL;
8722 }
8723
8724 CIccXformList::iterator i;
8725 CIccApplyXform *pXform;
8726
8727 for (i=m_Xforms->begin(); i!=m_Xforms->end(); i++) {
8728 pXform = i->ptr->GetNewApply(status);
8729 if (!pXform || status != icCmmStatOk) {
8730 delete pApply;
8731 return NULL;
8732 }
8733 pApply->AppendApplyXform(pXform);
8734 }
8735
8736 m_bValid = true;
8737
8738 status = icCmmStatOk;
8739
8740 return pApply;
8741}
8742
8743
8754icStatusCMM CIccCmm::Apply(icFloatNumber *DstPixel, const icFloatNumber *SrcPixel)
8755{
8756 return m_pApply->Apply(DstPixel, SrcPixel);
8757}
8758
8759
8770icStatusCMM CIccCmm::Apply(icFloatNumber *DstPixel, const icFloatNumber *SrcPixel, icUInt32Number nPixels)
8771{
8772 return m_pApply->Apply(DstPixel, SrcPixel, nPixels);
8773}
8774
8775
8790icStatusCMM CIccCmm::RemoveAllIO()
8791{
8792 if (!Valid())
8793 return icCmmStatBadXform;
8794
8795 CIccXformList::iterator i;
8796
8797 for (i=m_Xforms->begin(); i!=m_Xforms->end(); i++) {
8798 i->ptr->RemoveIO();
8799 }
8800
8801 return icCmmStatOk;
8802}
8803
8820bool CIccCmm::IsInGamut(icFloatNumber *pInternal)
8821{
8822 if (!((unsigned int)((*pInternal)*255.0)))
8823 return true;
8824 return false;
8825}
8826
8827
8843icStatusCMM CIccCmm::ToInternalEncoding(icColorSpaceSignature nSpace, icFloatColorEncoding nEncode,
8844 icFloatNumber *pInternal, const icFloatNumber *pData,
8845 bool bClip)
8846{
8847 int nSamples = icGetSpaceSamples(nSpace);
8848 if (!nSamples)
8850
8851
8853 CIccPixelBuf pInput(nSamples);
8854
8855 if (!pInput.get())
8856 return icCmmStatAllocErr;
8857
8858 memcpy(pInput, pData, nSamples*sizeof(icFloatNumber));
8859 bool bCLRspace = icIsSpaceCLR(nSpace);
8860
8861 switch(icGetColorSpaceType(nSpace))
8862 {
8867 bCLRspace = true;
8868 break;
8869 }
8870
8871 switch(nSpace) {
8872
8873 case icSigLabData:
8874 {
8875 switch(nEncode) {
8876 case icEncodeValue:
8877 {
8878 icLabToPcs(pInput);
8879 break;
8880 }
8881 case icEncodeFloat:
8882 {
8883 break;
8884 }
8885 case icEncode8Bit:
8886 {
8887 pInput[0] = icU8toF((icUInt8Number)pInput[0])*100.0f;
8888 pInput[1] = icU8toAB((icUInt8Number)pInput[1]);
8889 pInput[2] = icU8toAB((icUInt8Number)pInput[2]);
8890
8891 icLabToPcs(pInput);
8892 break;
8893 }
8894 case icEncode16Bit:
8895 {
8896 pInput[0] = icU16toF((icUInt16Number)pInput[0]);
8897 pInput[1] = icU16toF((icUInt16Number)pInput[1]);
8898 pInput[2] = icU16toF((icUInt16Number)pInput[2]);
8899 break;
8900 }
8901 case icEncode16BitV2:
8902 {
8903 pInput[0] = icU16toF((icUInt16Number)pInput[0]);
8904 pInput[1] = icU16toF((icUInt16Number)pInput[1]);
8905 pInput[2] = icU16toF((icUInt16Number)pInput[2]);
8906
8907 CIccPCSUtil::Lab2ToLab4(pInput, pInput);
8908 break;
8909 }
8910 default:
8912 break;
8913 }
8914 break;
8915 }
8916
8917 case icSigXYZData:
8918 {
8919 switch(nEncode) {
8920 case icEncodeValue:
8921 {
8922 pInput[0] = (icFloatNumber)pInput[0];
8923 pInput[1] = (icFloatNumber)pInput[1];
8924 pInput[2] = (icFloatNumber)pInput[2];
8925 icXyzToPcs(pInput);
8926 break;
8927 }
8928 case icEncodePercent:
8929 {
8930 pInput[0] = (icFloatNumber)(pInput[0] / 100.0);
8931 pInput[1] = (icFloatNumber)(pInput[1] / 100.0);
8932 pInput[2] = (icFloatNumber)(pInput[2] / 100.0);
8933 icXyzToPcs(pInput);
8934 break;
8935 }
8936 case icEncodeFloat:
8937 {
8938 icXyzToPcs(pInput);
8939 break;
8940 }
8941
8942 case icEncode16Bit:
8943 case icEncode16BitV2:
8944 {
8945 pInput[0] = icUSFtoD((icU1Fixed15Number)pInput[0]);
8946 pInput[1] = icUSFtoD((icU1Fixed15Number)pInput[1]);
8947 pInput[2] = icUSFtoD((icU1Fixed15Number)pInput[2]);
8948 break;
8949 }
8950
8951 default:
8953 break;
8954 }
8955 break;
8956 }
8957
8958 case icSigNamedData:
8960
8961 default:
8962 {
8963 switch(nEncode) {
8964 case icEncodeValue:
8965 {
8966 if (!bCLRspace || nSamples<3) {
8968 }
8969 if (nSamples==3)
8970 icLabToPcs(pInput);
8971 break;
8972 }
8973
8974 case icEncodePercent:
8975 {
8976 if (bClip) {
8977 for(i=0; i<nSamples; i++) {
8978 pInput[i] = (icFloatNumber)(pInput[i]/100.0);
8979 if (pInput[i] < 0.0) pInput[i] = 0.0;
8980 if (pInput[i] > 1.0) pInput[i] = 1.0;
8981 }
8982 }
8983 else {
8984 for(i=0; i<nSamples; i++) {
8985 pInput[i] = (icFloatNumber)(pInput[i]/100.0);
8986 }
8987 }
8988 break;
8989 }
8990
8991 case icEncodeFloat:
8992 {
8993 if (bClip) {
8994 for(i=0; i<nSamples; i++) {
8995 if (pInput[i] < 0.0) pInput[i] = 0.0;
8996 if (pInput[i] > 1.0) pInput[i] = 1.0;
8997 }
8998 }
8999 break;
9000 }
9001
9002 case icEncode8Bit:
9003 {
9004 for(i=0; i<nSamples; i++) {
9005 pInput[i] = icU8toF((icUInt8Number)pInput[i]);
9006 }
9007 break;
9008 }
9009
9010 case icEncode16Bit:
9011 case icEncode16BitV2:
9012 {
9013 for(i=0; i<nSamples; i++) {
9014 pInput[i] = icU16toF((icUInt16Number)pInput[i]);
9015 }
9016 break;
9017 }
9018
9019 default:
9021 break;
9022 }
9023 break;
9024 }
9025 }
9026
9027 memcpy(pInternal, pInput, nSamples*sizeof(icFloatNumber));
9028 return icCmmStatOk;
9029}
9030
9031
9047icStatusCMM CIccCmm::ToInternalEncoding(icColorSpaceSignature nSpace, icFloatNumber *pInternal,
9048 const icUInt8Number *pData)
9049{
9050 switch(nSpace) {
9051 case icSigRgbData:
9052 {
9053 pInternal[0] = (icFloatNumber)((icFloatNumber)pData[0] / 255.0);
9054 pInternal[1] = (icFloatNumber)((icFloatNumber)pData[1] / 255.0);
9055 pInternal[2] = (icFloatNumber)((icFloatNumber)pData[2] / 255.0);
9056
9057 return icCmmStatOk;
9058 }
9059 case icSigCmykData:
9060 {
9061 pInternal[0] = (icFloatNumber)((icFloatNumber)pData[0] / 255.0);
9062 pInternal[1] = (icFloatNumber)((icFloatNumber)pData[1] / 255.0);
9063 pInternal[2] = (icFloatNumber)((icFloatNumber)pData[2] / 255.0);
9064 pInternal[3] = (icFloatNumber)((icFloatNumber)pData[3] / 255.0);
9065 return icCmmStatOk;
9066 }
9067 default:
9068 {
9070 icUInt32Number nSamples = icGetSpaceSamples(nSpace);
9071 CIccPixelBuf FloatPixel(nSamples);
9072 if (!FloatPixel.get())
9073 return icCmmStatAllocErr;
9074
9075 for(i=0; i<nSamples; i++) {
9076 FloatPixel[i] = (icFloatNumber)pData[i];
9077 }
9078 return ToInternalEncoding(nSpace, icEncode8Bit, pInternal, FloatPixel);
9079 }
9080 }
9081
9082}
9083
9084
9100icStatusCMM CIccCmm::ToInternalEncoding(icColorSpaceSignature nSpace, icFloatNumber *pInternal,
9101 const icUInt16Number *pData)
9102{
9103 switch(nSpace) {
9104 case icSigRgbData:
9105 {
9106 pInternal[0] = (icFloatNumber)((icFloatNumber)pData[0] / 65535.0);
9107 pInternal[1] = (icFloatNumber)((icFloatNumber)pData[1] / 65535.0);
9108 pInternal[2] = (icFloatNumber)((icFloatNumber)pData[2] / 65535.0);
9109
9110 return icCmmStatOk;
9111 }
9112 case icSigCmykData:
9113 {
9114 pInternal[0] = (icFloatNumber)((icFloatNumber)pData[0] / 65535.0);
9115 pInternal[1] = (icFloatNumber)((icFloatNumber)pData[1] / 65535.0);
9116 pInternal[2] = (icFloatNumber)((icFloatNumber)pData[2] / 65535.0);
9117 pInternal[3] = (icFloatNumber)((icFloatNumber)pData[3] / 65535.0);
9118 return icCmmStatOk;
9119 }
9120 default:
9121 {
9123 icUInt32Number nSamples = icGetSpaceSamples(nSpace);
9124 CIccPixelBuf pFloatPixel(nSamples);
9125 if (!pFloatPixel.get())
9126 return icCmmStatAllocErr;
9127
9128 for(i=0; i<nSamples; i++) {
9129 pFloatPixel[i] = (icFloatNumber)pData[i];
9130 }
9131 return ToInternalEncoding(nSpace, icEncode16Bit, pInternal, pFloatPixel);
9132 }
9133 }
9134}
9135
9136
9152icStatusCMM CIccCmm::FromInternalEncoding(icColorSpaceSignature nSpace, icFloatColorEncoding nEncode,
9153 icFloatNumber *pData, const icFloatNumber *pInternal, bool bClip)
9154{
9155 int nSamples = icGetSpaceSamples(nSpace);
9156 if (!nSamples)
9158
9160 CIccPixelBuf pInput(nSamples);
9161
9162 if (!pInput.get())
9163 return icCmmStatAllocErr;
9164
9165 memcpy(pInput, pInternal, nSamples*sizeof(icFloatNumber));
9166 bool bCLRspace = (icIsSpaceCLR(nSpace) || (nSpace == icSigDevLabData) || (nSpace==icSigDevXYZData));
9167
9168 switch(nSpace) {
9169
9170 case icSigLabData:
9171 {
9172 switch(nEncode) {
9173 case icEncodeValue:
9174 {
9175 icLabFromPcs(pInput);
9176 break;
9177 }
9178 case icEncodeUnitFloat:
9179 case icEncodeFloat:
9180 {
9181 break;
9182 }
9183 case icEncode8Bit:
9184 {
9185 icLabFromPcs(pInput);
9186
9187 pInput[0] = (icUInt8Number)(pInput[0]/100.0 * 255.0 + 0.5);
9188 pInput[1] = icABtoU8(pInput[1]);
9189 pInput[2] = icABtoU8(pInput[2]);
9190 break;
9191 }
9192 case icEncode16Bit:
9193 {
9194 pInput[0] = icFtoU16(pInput[0]);
9195 pInput[1] = icFtoU16(pInput[1]);
9196 pInput[2] = icFtoU16(pInput[2]);
9197 break;
9198 }
9199 case icEncode16BitV2:
9200 {
9201 CIccPCSUtil::Lab4ToLab2(pInput, pInput);
9202
9203 pInput[0] = icFtoU16(pInput[0]);
9204 pInput[1] = icFtoU16(pInput[1]);
9205 pInput[2] = icFtoU16(pInput[2]);
9206 break;
9207 }
9208 default:
9210 break;
9211 }
9212 break;
9213 }
9214
9215 case icSigXYZData:
9216 {
9217 switch(nEncode) {
9218 case icEncodeValue:
9219 {
9220 icXyzFromPcs(pInput);
9221 break;
9222 }
9223 case icEncodePercent:
9224 {
9225 icXyzFromPcs(pInput);
9226 pInput[0] = (icFloatNumber)(pInput[0] * 100.0);
9227 pInput[1] = (icFloatNumber)(pInput[1] * 100.0);
9228 pInput[2] = (icFloatNumber)(pInput[2] * 100.0);
9229 break;
9230 }
9231 case icEncodeFloat:
9232 case icEncodeUnitFloat:
9233 {
9234 icXyzFromPcs(pInput);
9235 break;
9236 }
9237
9238 case icEncode16Bit:
9239 case icEncode16BitV2:
9240 {
9241 icXyzFromPcs(pInput);
9242 pInput[0] = icDtoUSF(pInput[0]);
9243 pInput[1] = icDtoUSF(pInput[1]);
9244 pInput[2] = icDtoUSF(pInput[2]);
9245 break;
9246 }
9247
9248 default:
9250 break;
9251 }
9252 break;
9253 }
9254
9255 case icSigNamedData:
9257
9258 default:
9259 {
9260 switch(nEncode) {
9261 case icEncodeValue:
9262 {
9263 if (nSpace == icSigDevXYZData) {
9264 icXyzFromPcs(pInput);
9265 }
9266 else if (bCLRspace && nSamples >=3) {
9267 icLabFromPcs(pInput);
9268 }
9269 break;
9270 }
9271 case icEncodePercent:
9272 {
9273 if (bClip) {
9274 for(i=0; i<nSamples; i++) {
9275 if (pInput[i] < 0.0) pInput[i] = 0.0;
9276 if (pInput[i] > 1.0) pInput[i] = 1.0;
9277 pInput[i] = (icFloatNumber)(pInput[i]*100.0);
9278 }
9279 }
9280 else {
9281 for(i=0; i<nSamples; i++) {
9282 pInput[i] = (icFloatNumber)(pInput[i]*100.0);
9283 }
9284 }
9285 break;
9286 }
9287
9288 case icEncodeFloat:
9289 break;
9290
9291 case icEncodeUnitFloat:
9292 {
9293 if (bClip) {
9294 for(i=0; i<nSamples; i++) {
9295 if (pInput[i] < 0.0) pInput[i] = 0.0;
9296 if (pInput[i] > 1.0) pInput[i] = 1.0;
9297 }
9298 }
9299 break;
9300 }
9301
9302 case icEncode8Bit:
9303 {
9304 for(i=0; i<nSamples; i++) {
9305 pInput[i] = icFtoU8(pInput[i]);
9306 }
9307 break;
9308 }
9309
9310 case icEncode16Bit:
9311 case icEncode16BitV2:
9312 {
9313 for(i=0; i<nSamples; i++) {
9314 pInput[i] = icFtoU16(pInput[i]);
9315 }
9316 break;
9317 }
9318
9319 default:
9321 break;
9322 }
9323 break;
9324 }
9325 }
9326
9327 memcpy(pData, pInput, nSamples*sizeof(icFloatNumber));
9328 return icCmmStatOk;
9329}
9330
9331
9347icStatusCMM CIccCmm::FromInternalEncoding(icColorSpaceSignature nSpace, icUInt8Number *pData,
9348 const icFloatNumber *pInternal)
9349{
9350 switch(nSpace) {
9351 case icSigRgbData:
9352 {
9353 pData[0] = icFtoU8(pInternal[0]);
9354 pData[1] = icFtoU8(pInternal[1]);
9355 pData[2] = icFtoU8(pInternal[2]);
9356
9357 return icCmmStatOk;
9358 }
9359 case icSigCmykData:
9360 {
9361 pData[0] = icFtoU8(pInternal[0]);
9362 pData[1] = icFtoU8(pInternal[1]);
9363 pData[2] = icFtoU8(pInternal[2]);
9364 pData[3] = icFtoU8(pInternal[3]);
9365
9366 return icCmmStatOk;
9367 }
9368 default:
9369 {
9371 icUInt32Number nSamples = icGetSpaceSamples(nSpace);
9372
9373 CIccPixelBuf pFloatPixel(nSamples);
9374 icStatusCMM convertStat;
9375
9376 if (!pFloatPixel.get())
9377 return icCmmStatAllocErr;
9378
9379 convertStat = FromInternalEncoding(nSpace, icEncode8Bit, pFloatPixel, pInternal);
9380 if (convertStat)
9381 return convertStat;
9382 for(i=0; i<nSamples; i++) {
9383 pData[i] = (icUInt8Number)(pFloatPixel[i] + 0.5);
9384 }
9385
9386 return icCmmStatOk;
9387 }
9388 }
9389}
9390
9391
9407icStatusCMM CIccCmm::FromInternalEncoding(icColorSpaceSignature nSpace, icUInt16Number *pData,
9408 const icFloatNumber *pInternal)
9409{
9410 switch(nSpace) {
9411 case icSigRgbData:
9412 {
9413 pData[0] = icFtoU16(pInternal[0]);
9414 pData[1] = icFtoU16(pInternal[1]);
9415 pData[2] = icFtoU16(pInternal[2]);
9416
9417 return icCmmStatOk;
9418 }
9419 case icSigCmykData:
9420 {
9421 pData[0] = icFtoU16(pInternal[0]);
9422 pData[1] = icFtoU16(pInternal[1]);
9423 pData[2] = icFtoU16(pInternal[2]);
9424 pData[3] = icFtoU16(pInternal[3]);
9425
9426 return icCmmStatOk;
9427 }
9428 default:
9429 {
9431 icUInt32Number nSamples = icGetSpaceSamples(nSpace);
9432 CIccPixelBuf pFloatPixel(nSamples);
9433 icStatusCMM convertStat;
9434
9435 if (!pFloatPixel.get())
9436 return icCmmStatAllocErr;
9437
9438 convertStat = FromInternalEncoding(nSpace, icEncode16Bit, pFloatPixel, pInternal);
9439 if (convertStat)
9440 return convertStat;
9441 for(i=0; i<nSamples; i++) {
9442 pData[i] = (icUInt16Number)(pFloatPixel[i] + 0.5);
9443 }
9444
9445 return icCmmStatOk;
9446 }
9447 }
9448}
9449
9450
9465const icChar* CIccCmm::GetFloatColorEncoding(icFloatColorEncoding val)
9466{
9467 switch(val) {
9468
9469 case icEncodeValue:
9470 return "icEncodeValue";
9471
9472 case icEncodeFloat:
9473 return "icEncodeFloat";
9474
9475 case icEncodeUnitFloat:
9476 return "icEncodeUnitFloat";
9477
9478 case icEncodePercent:
9479 return "icEncodePercent";
9480
9481 case icEncode8Bit:
9482 return "icEncode8Bit";
9483
9484 case icEncode16Bit:
9485 return "icEncode16Bit";
9486
9487 case icEncode16BitV2:
9488 return "icEncode16BitV2";
9489
9490 default:
9491 return "icEncodeUnknown";
9492 }
9493}
9494
9509icFloatColorEncoding CIccCmm::GetFloatColorEncoding(const icChar* val)
9510{
9511 if (!stricmp(val, "icEncodePercent")) {
9512 return icEncodePercent;
9513 }
9514 else if (!stricmp(val, "icEncodeUnitFloat")) {
9515 return icEncodeUnitFloat;
9516 }
9517 else if (!stricmp(val, "icEncodeFloat")) {
9518 return icEncodeFloat;
9519 }
9520 else if (!stricmp(val, "icEncode8Bit")) {
9521 return icEncode8Bit;
9522 }
9523 else if (!stricmp(val, "icEncode16Bit")) {
9524 return icEncode16Bit;
9525 }
9526 else if (!stricmp(val, "icEncode16BitV2")) {
9527 return icEncode16BitV2;
9528 }
9529 else if (!stricmp(val, "icEncodeValue")) {
9530 return icEncodeValue;
9531 }
9532 else {
9533 return icEncodeUnknown;
9534 }
9535
9536}
9537
9549icUInt32Number CIccCmm::GetNumXforms() const
9550{
9551 return (icUInt32Number)m_Xforms->size();
9552}
9553
9554
9564void CIccCmm::IterateXforms( IXformIterator* pIterater) const
9565{
9566 for (auto x = m_Xforms->begin(); x != m_Xforms->end(); x++) {
9567 pIterater->iterate(x->ptr);
9568 }
9569}
9570
9571
9583icColorSpaceSignature CIccCmm::GetFirstXformSource()
9584{
9585 if (!m_Xforms->size())
9586 return m_nSrcSpace;
9587
9588 return m_Xforms->begin()->ptr->GetSrcSpace();
9589}
9590
9602icColorSpaceSignature CIccCmm::GetLastXformDest()
9603{
9604 if (!m_Xforms->size())
9605 return m_nDestSpace;
9606
9607 return m_Xforms->rbegin()->ptr->GetDstSpace();
9608}
9609
9621CIccApplyNamedColorCmm::CIccApplyNamedColorCmm(CIccNamedColorCmm *pCmm) : CIccApplyCmm(pCmm)
9622{
9623}
9624
9625
9634CIccApplyNamedColorCmm::~CIccApplyNamedColorCmm()
9635{
9636}
9637
9638
9651icStatusCMM CIccApplyNamedColorCmm::Apply(icFloatNumber *DstPixel, const icFloatNumber *SrcPixel)
9652{
9653 icFloatNumber *pDst, *pTmp;
9654 const icFloatNumber *pSrc;
9655 CIccApplyXformList::iterator i;
9656 int j, n = (int)m_Xforms->size();
9657 CIccApplyXform *pApply;
9658 const CIccXform *pApplyXform;
9659 CIccXformNamedColor *pXform;
9660
9661 if (!n)
9662 return icCmmStatBadXform;
9663
9664 if (!m_Pixel && !InitPixel()) {
9665 return icCmmStatAllocErr;
9666 }
9667
9668 icChar NamedColor[256];
9669 icStatusCMM rv;
9670
9671 pSrc = SrcPixel;
9672 pDst = m_Pixel;
9673
9674#ifdef DEBUG_CMM_APPLY
9675 int nCount = 0;
9676 printf("Start ApplyNamedCmm\n");
9677 DumpCmmApplyPixel(nCount++, pSrc, icGetSpaceSamples(m_pCmm->GetSourceSpace()));
9678#endif
9679
9680
9681 if (n>1) {
9682 for (j=0, i=m_Xforms->begin(); j<n-1 && i!=m_Xforms->end(); i++, j++) {
9683
9684 pApply = i->ptr;
9685 pApplyXform = pApply->GetXform();
9686 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
9687 pXform = (CIccXformNamedColor*)pApplyXform;
9688
9689 switch(pXform->GetInterface()) {
9690 case icApplyPixel2Pixel:
9691 pXform->Apply(pApply, pDst, pSrc);
9692#ifdef DEBUG_CMM_APPLY
9693 DumpCmmApplyPixel(nCount++, pDst, pXform->GetNumDstSamples());
9694#endif
9695 break;
9696
9697 case icApplyPixel2Named:
9698 pXform->Apply(pApply, NamedColor, pSrc);
9699#ifdef DEBUG_CMM_APPLY
9700 printf("Xfm%d: \"%s\"\n", nCount++, NamedColor);
9701#endif
9702 break;
9703
9704 case icApplyNamed2Pixel:
9705 if (j==0) {
9707 }
9708
9709 rv = pXform->Apply(pApply, pDst, NamedColor);
9710#ifdef DEBUG_CMM_APPLY
9711 DumpCmmApplyPixel(nCount++, pDst, pXform->GetNumDstSamples());
9712#endif
9713
9714 if (rv) {
9715 return rv;
9716 }
9717 break;
9718
9719 default:
9720 break;
9721 }
9722 }
9723 else {
9724 pApplyXform->Apply(pApply, pDst, pSrc);
9725#ifdef DEBUG_CMM_APPLY
9726 DumpCmmApplyPixel(nCount++, pDst, pApplyXform->GetNumDstSamples());
9727#endif
9728 }
9729 pTmp = (icFloatNumber*)pSrc;
9730 pSrc = pDst;
9731 if (pTmp==SrcPixel)
9732 pDst = m_Pixel2;
9733 else
9734 pDst = pTmp;
9735 }
9736
9737 pApply = i->ptr;
9738 pApplyXform = pApply->GetXform();
9739 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
9740 pXform = (CIccXformNamedColor*)pApplyXform;
9741
9742 switch(pXform->GetInterface()) {
9743 case icApplyPixel2Pixel:
9744 pXform->Apply(pApply, DstPixel, pSrc);
9745#ifdef DEBUG_CMM_APPLY
9746 DumpCmmApplyPixel(nCount++, DstPixel, pXform->GetNumDstSamples());
9747#endif
9748 break;
9749
9750 case icApplyPixel2Named:
9751 default:
9753 break;
9754
9755 case icApplyNamed2Pixel:
9756 rv = pXform->Apply(pApply, DstPixel, NamedColor);
9757#ifdef DEBUG_CMM_APPLY
9758 DumpCmmApplyPixel(nCount++, DstPixel, pXform->GetNumDstSamples());
9759#endif
9760 if (rv) {
9761 return rv;
9762 }
9763 break;
9764
9765 }
9766 }
9767 else {
9768 pApplyXform->Apply(pApply, DstPixel, pSrc);
9769#ifdef DEBUG_CMM_APPLY
9770 DumpCmmApplyPixel(nCount++, DstPixel, pApplyXform->GetNumDstSamples());
9771#endif
9772 }
9773
9774 }
9775 else if (n==1) {
9776 i = m_Xforms->begin();
9777
9778 pApply = i->ptr;
9779 pApplyXform = pApply->GetXform();
9780 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
9782 }
9783
9784 pApplyXform->Apply(pApply, DstPixel, pSrc);
9785#ifdef DEBUG_CMM_APPLY
9786 DumpCmmApplyPixel(nCount++, DstPixel, pApplyXform->GetNumDstSamples());
9787#endif
9788 }
9789
9790#ifdef DEBUG_CMM_APPLY
9791 DumpCmmApplyPixel(nCount++, DstPixel, icGetSpaceSamples(m_pCmm->GetDestSpace()));
9792 printf("End ApplyNamedCmm\n\n");
9793#endif
9794
9795 return icCmmStatOk;
9796}
9797
9798
9811icStatusCMM CIccApplyNamedColorCmm::Apply(icFloatNumber *DstPixel, const icFloatNumber *SrcPixel, icUInt32Number nPixels)
9812{
9813 icFloatNumber *pDst;
9814 const icFloatNumber *pSrc;
9815 CIccApplyXformList::iterator i;
9816 int j, n = (int)m_Xforms->size();
9817 CIccApplyXform *pApply;
9818 const CIccXform *pApplyXform;
9819 CIccXformNamedColor *pXform;
9820 icUInt32Number k;
9821
9822 if (!n)
9823 return icCmmStatBadXform;
9824
9825 if (!m_Pixel && !InitPixel()) {
9826 return icCmmStatAllocErr;
9827 }
9828
9829 icChar NamedColor[255];
9830 icStatusCMM rv;
9831
9832 for (k=0; k<nPixels; k++) {
9833
9834 pSrc = SrcPixel;
9835 pDst = m_Pixel;
9836
9837 if (n>1) {
9838 for (j=0, i=m_Xforms->begin(); j<n-1 && i!=m_Xforms->end(); i++, j++) {
9839
9840 pApply = i->ptr;
9841 pApplyXform = pApply->GetXform();
9842 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
9843 pXform = (CIccXformNamedColor*)pApplyXform;
9844
9845 switch(pXform->GetInterface()) {
9846 case icApplyPixel2Pixel:
9847 pXform->Apply(pApply, pDst, pSrc);
9848 break;
9849
9850 case icApplyPixel2Named:
9851 pXform->Apply(pApply, NamedColor, pSrc);
9852 break;
9853
9854 case icApplyNamed2Pixel:
9855 if (j==0) {
9857 }
9858
9859 rv = pXform->Apply(pApply, pDst, NamedColor);
9860
9861 if (rv) {
9862 return rv;
9863 }
9864 break;
9865
9866 default:
9867 break;
9868 }
9869 }
9870 else {
9871 pApplyXform->Apply(pApply, pDst, pSrc);
9872 }
9873 pSrc = pDst;
9874 }
9875
9876 pApply = i->ptr;
9877 pApplyXform = pApply->GetXform();
9878 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
9879 pXform = (CIccXformNamedColor*)pApplyXform;
9880
9881 switch(pXform->GetInterface()) {
9882 case icApplyPixel2Pixel:
9883 pXform->Apply(pApply, DstPixel, pSrc);
9884 break;
9885
9886 case icApplyPixel2Named:
9887 default:
9889 break;
9890
9891 case icApplyNamed2Pixel:
9892 rv = pXform->Apply(pApply, DstPixel, NamedColor);
9893 if (rv) {
9894 return rv;
9895 }
9896 break;
9897
9898 }
9899 }
9900 else {
9901 pApplyXform->Apply(pApply, DstPixel, pSrc);
9902 }
9903
9904 }
9905 else if (n==1) {
9906 i = m_Xforms->begin();
9907
9908 pApply = i->ptr;
9909 pApplyXform = pApply->GetXform();
9910 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
9912 }
9913
9914 pApplyXform->Apply(pApply, DstPixel, pSrc);
9915 }
9916
9917 SrcPixel += m_pCmm->GetSourceSamples();
9918 DstPixel += m_pCmm->GetDestSamples();
9919 }
9920
9921 return icCmmStatOk;
9922}
9923
9924
9937icStatusCMM CIccApplyNamedColorCmm::Apply(icChar* DstColorName, const icFloatNumber *SrcPixel)
9938{
9939 icFloatNumber *pDst, *pTmp;
9940 const icFloatNumber *pSrc;
9941 CIccApplyXformList::iterator i;
9942 int j, n = (int)m_Xforms->size();
9943 CIccApplyXform *pApply;
9944 const CIccXform *pApplyXform;
9945 CIccXformNamedColor *pXform;
9946
9947 if (!n)
9948 return icCmmStatBadXform;
9949
9950 if (!m_Pixel && !InitPixel()) {
9951 return icCmmStatAllocErr;
9952 }
9953
9954 icChar NamedColor[256];
9955 icStatusCMM rv;
9956
9957 pSrc = SrcPixel;
9958 pDst = m_Pixel;
9959
9960 if (n>1) {
9961 for (j=0, i=m_Xforms->begin(); j<n-1 && i!=m_Xforms->end(); i++, j++) {
9962
9963 pApply = i->ptr;
9964 pApplyXform = pApply->GetXform();
9965 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
9966 pXform = (CIccXformNamedColor*)pApplyXform;
9967 switch(pXform->GetInterface()) {
9968 case icApplyPixel2Pixel:
9969 pXform->Apply(pApply, pDst, pSrc);
9970 break;
9971
9972 case icApplyPixel2Named:
9973 pXform->Apply(pApply, NamedColor, pSrc);
9974 break;
9975
9976 case icApplyNamed2Pixel:
9977 if (j==0) {
9979 }
9980 rv = pXform->Apply(pApply, pDst, NamedColor);
9981 if (rv) {
9982 return rv;
9983 }
9984 break;
9985
9986 default:
9987 break;
9988 }
9989 }
9990 else {
9991 pApplyXform->Apply(pApply, pDst, pSrc);
9992 }
9993 pTmp = (icFloatNumber*)pSrc;
9994 pSrc = pDst;
9995 if (pTmp==SrcPixel)
9996 pDst = m_Pixel2;
9997 else
9998 pDst = pTmp;
9999 }
10000
10001 pApply = i->ptr;
10002 pApplyXform = pApply->GetXform();
10003 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
10004 pXform = (CIccXformNamedColor*)pApplyXform;
10005 switch(pXform->GetInterface()) {
10006
10007 case icApplyPixel2Named:
10008 pXform->Apply(pApply, DstColorName, pSrc);
10009 break;
10010
10011 case icApplyPixel2Pixel:
10012 case icApplyNamed2Pixel:
10013 default:
10015 break;
10016 }
10017 }
10018 else {
10020 }
10021
10022 }
10023 else if (n==1) {
10024 i = m_Xforms->begin();
10025 pApply = i->ptr;
10026 pApplyXform = pApply->GetXform();
10027 if (pApplyXform->GetXformType()!=icXformTypeNamedColor) {
10029 }
10030
10031 pXform = (CIccXformNamedColor*)pApplyXform;
10032 pXform->Apply(pApply, DstColorName, pSrc);
10033 }
10034
10035 return icCmmStatOk;
10036}
10037
10038
10051icStatusCMM CIccApplyNamedColorCmm::Apply(icFloatNumber *DstPixel, const icChar *SrcColorName, icFloatNumber tint/*=1.0*/)
10052{
10053 icFloatNumber *pDst, *pTmp;
10054 const icFloatNumber *pSrc;
10055 CIccApplyXformList::iterator i;
10056 int j, n = (int)m_Xforms->size();
10057 CIccApplyXform *pApply;
10058 const CIccXform *pApplyXform;
10059 CIccXformNamedColor *pXform;
10060
10061 if (!n)
10062 return icCmmStatBadXform;
10063
10064 if (!m_Pixel && !InitPixel()) {
10065 return icCmmStatAllocErr;
10066 }
10067
10068 icChar NamedColor[255];
10069 icStatusCMM rv;
10070
10071 i=m_Xforms->begin();
10072 pApply = i->ptr;
10073 pApplyXform = pApply->GetXform();
10074 if (pApplyXform->GetXformType()!=icXformTypeNamedColor)
10076
10077 pXform = (CIccXformNamedColor*)pApplyXform;
10078
10079 pDst = m_Pixel;
10080
10081 if (n>1) {
10082 rv = pXform->Apply(pApply, pDst, SrcColorName, tint);
10083 if (rv) {
10084 return rv;
10085 }
10086
10087 pSrc = pDst;
10088 pDst = m_Pixel2;
10089
10090 for (j=0, i++; j<n-2 && i!=m_Xforms->end(); i++, j++) {
10091
10092 pApply = i->ptr;
10093 pApplyXform = pApply->GetXform();
10094 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
10095 CIccXformNamedColor *pXform = (CIccXformNamedColor*)pApplyXform;
10096 switch(pXform->GetInterface()) {
10097 case icApplyPixel2Pixel:
10098 pXform->Apply(pApply, pDst, pSrc);
10099 break;
10100
10101 case icApplyPixel2Named:
10102 pXform->Apply(pApply, NamedColor, pSrc);
10103 break;
10104
10105 case icApplyNamed2Pixel:
10106 rv = pXform->Apply(pApply, pDst, NamedColor);
10107 if (rv) {
10108 return rv;
10109 }
10110 break;
10111
10112 default:
10113 break;
10114 }
10115 }
10116 else {
10117 pApplyXform->Apply(pApply, pDst, pSrc);
10118 }
10119 pTmp = (icFloatNumber*)pSrc;
10120 pSrc = pDst;
10121 pDst = pTmp;
10122 }
10123
10124 pApply = i->ptr;
10125 pApplyXform = pApply->GetXform();
10126 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
10127 pXform = (CIccXformNamedColor*)pApplyXform;
10128 switch(pXform->GetInterface()) {
10129 case icApplyPixel2Pixel:
10130 pXform->Apply(pApply, DstPixel, pSrc);
10131 break;
10132
10133 case icApplyPixel2Named:
10134 default:
10136 break;
10137
10138 case icApplyNamed2Pixel:
10139 rv = pXform->Apply(pApply, DstPixel, NamedColor);
10140 if (rv) {
10141 return rv;
10142 }
10143 break;
10144
10145 }
10146 }
10147 else {
10148 pApplyXform->Apply(pApply, DstPixel, pSrc);
10149 }
10150
10151 }
10152 else if (n==1) {
10153 rv = pXform->Apply(pApply, DstPixel, SrcColorName, tint);
10154 if (rv) {
10155 return rv;
10156 }
10157 }
10158
10159
10160 return icCmmStatOk;
10161}
10162
10175icStatusCMM CIccApplyNamedColorCmm::Apply(icChar *DstColorName, const icChar *SrcColorName, icFloatNumber tint/*=1.0*/)
10176{
10177 icFloatNumber *pDst, *pTmp;
10178 const icFloatNumber *pSrc;
10179 CIccApplyXformList::iterator i;
10180 int j, n = (int)m_Xforms->size();
10181 icChar NamedColor[256];
10182 icStatusCMM rv;
10183 CIccApplyXform *pApply;
10184 const CIccXform *pApplyXform;
10185 CIccXformNamedColor *pXform;
10186
10187 if (!n)
10188 return icCmmStatBadXform;
10189
10190 if (!m_Pixel && !InitPixel()) {
10191 return icCmmStatAllocErr;
10192 }
10193
10194 i=m_Xforms->begin();
10195
10196 pApply = i->ptr;
10197 pApplyXform = pApply->GetXform();
10198 if (pApplyXform->GetXformType()!=icXformTypeNamedColor)
10200
10201 pXform = (CIccXformNamedColor*)pApplyXform;
10202
10203 pDst = m_Pixel;
10204
10205 if (n>1) {
10206 rv = pXform->Apply(pApply, pDst, SrcColorName, tint);
10207
10208 if (rv) {
10209 return rv;
10210 }
10211
10212 pSrc = pDst;
10213 pDst = m_Pixel2;
10214
10215 for (j=0, i++; j<n-2 && i!=m_Xforms->end(); i++, j++) {
10216
10217 pApply = i->ptr;
10218 pApplyXform = pApply->GetXform();
10219 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
10220 pXform = (CIccXformNamedColor*)pApplyXform;
10221 switch(pXform->GetInterface()) {
10222 case icApplyPixel2Pixel:
10223 pXform->Apply(pApply, pDst, pSrc);
10224 break;
10225
10226
10227 case icApplyPixel2Named:
10228 pXform->Apply(pApply, NamedColor, pSrc);
10229 break;
10230
10231 case icApplyNamed2Pixel:
10232 rv = pXform->Apply(pApply, pDst, NamedColor);
10233 if (rv) {
10234 return rv;
10235 }
10236 break;
10237
10238 default:
10239 break;
10240 }
10241 }
10242 else {
10243 pApplyXform->Apply(pApply, pDst, pSrc);
10244 }
10245 pTmp = (icFloatNumber*)pSrc;
10246 pSrc = pDst;
10247 pDst = pTmp;
10248 }
10249
10250 pApply = i->ptr;
10251 pApplyXform = pApply->GetXform();
10252 if (pApplyXform->GetXformType()==icXformTypeNamedColor) {
10253 pXform = (CIccXformNamedColor*)pApplyXform;
10254 switch(pXform->GetInterface()) {
10255 case icApplyPixel2Named:
10256 pXform->Apply(pApply, DstColorName, pSrc);
10257 break;
10258
10259 case icApplyPixel2Pixel:
10260 case icApplyNamed2Pixel:
10261 default:
10263 break;
10264 }
10265 }
10266 else {
10268 }
10269
10270 }
10271 else if (n==1) {
10273 }
10274
10275 return icCmmStatOk;
10276}
10277
10291CIccNamedColorCmm::CIccNamedColorCmm(icColorSpaceSignature nSrcSpace, icColorSpaceSignature nDestSpace,
10292 bool bFirstInput) : CIccCmm(nSrcSpace, nDestSpace, bFirstInput)
10293{
10294 m_nApplyInterface = icApplyPixel2Pixel;
10295}
10296
10305CIccNamedColorCmm::~CIccNamedColorCmm()
10306{
10307}
10308
10309
10327icStatusCMM CIccNamedColorCmm::AddXform(const icChar *szProfilePath,
10328 icRenderingIntent nIntent /*=icUnknownIntent*/,
10329 icXformInterp nInterp /*icXformInterp*/,
10330 IIccProfileConnectionConditions *pPcc/*=NULL*/,
10331 icXformLutType nLutType /*=icXformLutColor*/,
10332 bool bUseD2BxB2DxTags /*=true*/,
10333 CIccCreateXformHintManager *pHintManager /*=NULL*/,
10334 bool bUseSubProfile /*=false*/)
10335{
10336 CIccProfile *pProfile = OpenIccProfile(szProfilePath, bUseSubProfile);
10337
10338 if (!pProfile)
10340
10341 icStatusCMM rv = AddXform(pProfile, nIntent, nInterp, pPcc, nLutType, bUseD2BxB2DxTags, pHintManager);
10342
10343 if (rv != icCmmStatOk)
10344 delete pProfile;
10345
10346 return rv;
10347}
10348
10367icStatusCMM CIccNamedColorCmm::AddXform(CIccProfile *pProfile,
10368 icRenderingIntent nIntent /*=icUnknownIntent*/,
10369 icXformInterp nInterp /*=icInterpLinear*/,
10370 IIccProfileConnectionConditions *pPcc/*=NULL*/,
10371 icXformLutType nLutType /*=icXformLutColor*/,
10372 bool bUseD2BxB2DxTags /*=true*/,
10373 CIccCreateXformHintManager *pHintManager /*=NULL*/)
10374{
10375 icColorSpaceSignature nSrcSpace, nDstSpace;
10376 CIccXformPtr Xform;
10377 bool bInput = !m_bLastInput;
10378 icStatusCMM rv;
10379 icXformLutType nUseLutType = nLutType;
10380
10381 switch(pProfile->m_Header.deviceClass) {
10384 nIntent = icPerceptual;
10385 nLutType = icXformLutMCS;
10386 break;
10387
10389 nLutType = icXformLutMCS;
10390 break;
10391
10392 default:
10393 break;
10394 }
10395
10396 Xform.ptr = NULL;
10397 switch (nUseLutType) {
10398 //Automatically choose which one
10399 case icXformLutColor:
10401 case icXformLutSpectral:
10403 {
10404 CIccTag *pTag = pProfile->FindTag(icSigNamedColor2Tag);
10405
10406 if (pTag && (pProfile->m_Header.deviceClass==icSigNamedColorClass || nLutType == icXformLutNamedColor)) {
10407 if (bInput) {
10408 nSrcSpace = icSigNamedData;
10409 }
10410 else if (nLutType == icXformLutSpectral || ((bUseD2BxB2DxTags || !pProfile->m_Header.pcs) && pProfile->m_Header.spectralPCS && nLutType != icXformLutColorimetric)) {
10411 nSrcSpace = (icColorSpaceSignature)pProfile->m_Header.spectralPCS;
10412 bUseD2BxB2DxTags = true;
10413 }
10414 else {
10415 nSrcSpace = pProfile->m_Header.pcs;
10416 }
10417
10418 if (!m_Xforms->size()) {
10419 if (m_nSrcSpace==icSigUnknownData) {
10420 m_nSrcSpace = nSrcSpace;
10421 }
10422 else {
10423 nSrcSpace = m_nSrcSpace;
10424 }
10425 }
10426 else {
10427 if (m_nLastSpace==icSigUnknownData) {
10428 m_nLastSpace = nSrcSpace;
10429 }
10430 else {
10431 nSrcSpace = m_nLastSpace;
10432 }
10433 }
10434
10435 if (nSrcSpace==icSigNamedData) {
10436 if (nLutType == icXformLutSpectral || (bUseD2BxB2DxTags && pProfile->m_Header.spectralPCS && nLutType != icXformLutColorimetric)) {
10437 nDstSpace = (icColorSpaceSignature)pProfile->m_Header.spectralPCS;
10438 bUseD2BxB2DxTags = true;
10439 }
10440 else {
10441 nDstSpace = pProfile->m_Header.pcs;
10442 }
10443 bInput = true;
10444 }
10445 else {
10446 nDstSpace = icSigNamedData;
10447 bInput = false;
10448 }
10449
10450 Xform.ptr = CIccXform::Create(pProfile, bInput, nIntent, nInterp, pPcc, icXformLutNamedColor, bUseD2BxB2DxTags, pHintManager);
10451 if (!Xform.ptr) {
10452 return icCmmStatBadXform;
10453 }
10454 CIccXformNamedColor *pXform = (CIccXformNamedColor *)Xform.ptr;
10455 rv = pXform->SetSrcSpace(nSrcSpace);
10456 if (rv)
10457 return rv;
10458
10459 rv = pXform->SetDestSpace(nDstSpace);
10460 if (rv)
10461 return rv;
10462 }
10463 else {
10464 //It isn't named color so make we will use color lut.
10465 if (nUseLutType==icXformLutNamedColor)
10466 nUseLutType = icXformLutColor;
10467
10468 //Check pProfile if nIntent and input can be found.
10469 if (bInput) {
10470 nSrcSpace = pProfile->m_Header.colorSpace;
10471
10472 if (nLutType == icXformLutSpectral || ((bUseD2BxB2DxTags || !pProfile->m_Header.pcs) && pProfile->m_Header.spectralPCS && nLutType != icXformLutColorimetric)) {
10473 nDstSpace = (icColorSpaceSignature)pProfile->m_Header.spectralPCS;
10474 bUseD2BxB2DxTags = true;
10475 }
10476 else
10477 nDstSpace = pProfile->m_Header.pcs;
10478 }
10479 else {
10480 if (pProfile->m_Header.deviceClass == icSigLinkClass) {
10481 return icCmmStatBadSpaceLink;
10482 }
10483 if (pProfile->m_Header.deviceClass == icSigAbstractClass) {
10484 bInput = true;
10485 nIntent = icPerceptual; // Note: icPerceptualIntent = 0
10486 }
10487
10488 if (nLutType == icXformLutSpectral || ((bUseD2BxB2DxTags || !pProfile->m_Header.pcs) && pProfile->m_Header.spectralPCS && nLutType != icXformLutColorimetric)) {
10489 nSrcSpace = (icColorSpaceSignature)pProfile->m_Header.spectralPCS;
10490 bUseD2BxB2DxTags = true;
10491 }
10492 else
10493 nSrcSpace = pProfile->m_Header.pcs;
10494
10495 nDstSpace = pProfile->m_Header.colorSpace;
10496 }
10497 }
10498 }
10499 break;
10500
10501 case icXformLutPreview:
10502 nSrcSpace = pProfile->m_Header.pcs;
10503 nDstSpace = pProfile->m_Header.pcs;
10504 bInput = false;
10505 break;
10506
10507 case icXformLutGamut:
10508 nSrcSpace = pProfile->m_Header.pcs;
10509 nDstSpace = icSigGamutData;
10510 bInput = true;
10511 break;
10512
10514 nSrcSpace = pProfile->m_Header.colorSpace;
10515 nDstSpace = icSigUnknownData;
10516 break;
10517
10519 nSrcSpace = pProfile->m_Header.colorSpace;
10520 nDstSpace = icSigUnknownData;
10521 break;
10522
10523 case icXformLutMCS:
10524 switch(pProfile->m_Header.deviceClass)
10525 {
10526 case icSigInputClass:
10528 nSrcSpace = pProfile->m_Header.colorSpace;
10529 nDstSpace = (icColorSpaceSignature)pProfile->m_Header.mcs;
10530 break;
10532 nSrcSpace = (icColorSpaceSignature)pProfile->m_Header.mcs;
10533 if (bUseD2BxB2DxTags && pProfile->m_Header.spectralPCS) {
10534 nDstSpace = (icColorSpaceSignature)pProfile->m_Header.spectralPCS;
10535 }
10536 else {
10537 nDstSpace = pProfile->m_Header.pcs;
10538 }
10539 bInput = true;
10540 break;
10541
10543 nSrcSpace = (icColorSpaceSignature)pProfile->m_Header.mcs;
10544 nDstSpace = pProfile->m_Header.colorSpace;
10545 break;
10546
10547 default:
10548 return icCmmStatBadLutType;
10549 }
10550 break;
10551
10552 default:
10553 return icCmmStatBadLutType;
10554 }
10555
10556 //Make sure color spaces match with previous xforms
10557 if (!m_Xforms->size()) {
10558 if (m_nSrcSpace == icSigUnknownData) {
10559 m_nLastSpace = nSrcSpace;
10560 m_nSrcSpace = nSrcSpace;
10561 }
10562 else if (!IsCompatSpace(m_nSrcSpace, nSrcSpace) && !IsNChannelCompat(m_nSrcSpace, nSrcSpace)) {
10563 return icCmmStatBadSpaceLink;
10564 }
10565 }
10566 else if (!IsCompatSpace(m_nLastSpace, nSrcSpace) && !IsNChannelCompat(m_nSrcSpace, nSrcSpace)) {
10567 return icCmmStatBadSpaceLink;
10568 }
10569
10570 if (!m_Xforms->size())
10571 m_nSrcSpace = nSrcSpace;
10572
10573 m_nDestSpace = nDstSpace;
10574
10575 //Automatic creation of intent from header/last profile
10576 if (nIntent==icUnknownIntent) {
10577 if (bInput) {
10578 nIntent = (icRenderingIntent)pProfile->m_Header.renderingIntent;
10579 }
10580 else {
10581 nIntent = m_nLastIntent;
10582 }
10583 if (nIntent == icUnknownIntent)
10584 nIntent = icPerceptual;
10585 }
10586
10587 if (!Xform.ptr)
10588 Xform.ptr = CIccXform::Create(pProfile, bInput, nIntent, nInterp, pPcc, nUseLutType, bUseD2BxB2DxTags, pHintManager);
10589
10590 if (!Xform.ptr) {
10591 return icCmmStatBadXform;
10592 }
10593
10594 m_nLastSpace = Xform.ptr->GetDstSpace();
10595 m_nLastIntent = nIntent;
10596
10597 if (pProfile->m_Header.deviceClass == icSigLinkClass)
10598 bInput = false;
10599 m_bLastInput = bInput;
10600
10601 m_Xforms->push_back(Xform);
10602
10603 return icCmmStatOk;
10604}
10605
10616 icStatusCMM CIccNamedColorCmm::Begin(bool bAllocNewApply/* =true */, bool bUsePcsConversion/*=false*/)
10617{
10618 if (m_nDestSpace==icSigUnknownData) {
10619 m_nDestSpace = m_nLastSpace;
10620 }
10621 else if (!IsCompatSpace(m_nDestSpace, m_nLastSpace) && !IsCompatSpacePCS(m_nDestSpace, m_nLastSpace)) {
10622 return icCmmStatBadSpaceLink;
10623 }
10624
10625 if (m_nSrcSpace != icSigNamedData) {
10626 if (m_nDestSpace != icSigNamedData) {
10627 m_nApplyInterface = icApplyPixel2Pixel;
10628 }
10629 else {
10630 m_nApplyInterface = icApplyPixel2Named;
10631 }
10632 }
10633 else {
10634 if (m_nDestSpace != icSigNamedData) {
10635 m_nApplyInterface = icApplyNamed2Pixel;
10636 }
10637 else {
10638 m_nApplyInterface = icApplyNamed2Named;
10639 }
10640 }
10641
10642 CheckPCSRangeConversions();
10643 SetLateBindingCC();
10644
10645 icStatusCMM rv;
10646 CIccXformList::iterator i;
10647
10648 for (i=m_Xforms->begin(); i!=m_Xforms->end(); i++) {
10649 rv = i->ptr->Begin();
10650
10651 if (rv!= icCmmStatOk) {
10652 return rv;
10653 }
10654 }
10655
10656 rv = CheckPCSConnections(bUsePcsConversion);
10657 if (rv != icCmmStatOk && rv!=icCmmStatIdentityXform)
10658 return rv;
10659
10660 if (bAllocNewApply) {
10661 rv = icCmmStatOk;
10662
10663 m_pApply = GetNewApplyCmm(rv);
10664 }
10665 else
10666 rv = icCmmStatOk;
10667
10668 return rv;
10669}
10670
10681 CIccApplyCmm *CIccNamedColorCmm::GetNewApplyCmm(icStatusCMM &status)
10682 {
10683 CIccApplyCmm *pApply = new CIccApplyNamedColorCmm(this);
10684
10685 CIccXformList::iterator i;
10686
10687 for (i=m_Xforms->begin(); i!=m_Xforms->end(); i++) {
10688 CIccApplyXform *pXform = i->ptr->GetNewApply(status);
10689 if (status != icCmmStatOk || !pXform) {
10690 delete pApply;
10691 return NULL;
10692 }
10693 pApply->AppendApplyXform(pXform);
10694 }
10695
10696 m_bValid = true;
10697
10698 status = icCmmStatOk;
10699 return pApply;
10700}
10701
10702
10715icStatusCMM CIccNamedColorCmm::Apply(icChar* DstColorName, const icFloatNumber *SrcPixel)
10716{
10717 return ((CIccApplyNamedColorCmm*)m_pApply)->Apply(DstColorName, SrcPixel);
10718}
10719
10720
10733icStatusCMM CIccNamedColorCmm::Apply(icFloatNumber *DstPixel, const icChar *SrcColorName, icFloatNumber tint/*=1.0*/)
10734{
10735 return ((CIccApplyNamedColorCmm*)m_pApply)->Apply(DstPixel, SrcColorName, tint);
10736}
10737
10738
10751icStatusCMM CIccNamedColorCmm::Apply(icChar* DstColorName, const icChar *SrcColorName, icFloatNumber tint/*=1.0*/)
10752{
10753 return ((CIccApplyNamedColorCmm*)m_pApply)->Apply(DstColorName, SrcColorName, tint);
10754}
10755
10756
10768icStatusCMM CIccNamedColorCmm::SetLastXformDest(icColorSpaceSignature nDestSpace)
10769{
10770 int n = (int)m_Xforms->size();
10771 CIccXformPtr *pLastXform;
10772
10773 if (!n)
10774 return icCmmStatBadXform;
10775
10776 pLastXform = &m_Xforms->back();
10777
10778 if (pLastXform->ptr->GetXformType()==icXformTypeNamedColor) {
10779 CIccXformNamedColor *pXform = (CIccXformNamedColor *)pLastXform->ptr;
10780 if (pXform->GetSrcSpace() == icSigNamedData &&
10781 nDestSpace == icSigNamedData) {
10782 return icCmmStatBadSpaceLink;
10783 }
10784
10785 if (nDestSpace != icSigNamedData &&
10786 pXform->GetDstSpace() == icSigNamedData) {
10787 return icCmmStatBadSpaceLink;
10788 }
10789
10790 return pXform->SetDestSpace(nDestSpace);
10791 }
10792
10793 return icCmmStatBadXform;
10794}
10795
10796
10804CIccMruCmm::CIccMruCmm()
10805{
10806 m_pCmm = NULL;
10807 m_bDeleteCmm = false;
10808 m_nCacheSize = 0;
10809}
10810
10811
10819CIccMruCmm::~CIccMruCmm()
10820{
10821 if (m_pCmm && m_bDeleteCmm)
10822 delete m_pCmm;
10823}
10824
10825
10846CIccMruCmm* CIccMruCmm::Attach(CIccCmm *pCmm, icUInt8Number nCacheSize/* =4 */, bool bDeleteCmm/*=true*/)
10847{
10848 if (!pCmm || !nCacheSize)
10849 return NULL;
10850
10851 if (!pCmm->Valid()) {
10852 if (bDeleteCmm)
10853 delete pCmm;
10854 return NULL;
10855 }
10856
10857 CIccMruCmm *rv = new CIccMruCmm();
10858
10859 rv->m_pCmm = pCmm;
10860 rv->m_nCacheSize = nCacheSize;
10861 rv->m_bDeleteCmm = bDeleteCmm;
10862
10863 rv->m_nSrcSpace = pCmm->GetSourceSpace();
10864 rv->m_nDestSpace = pCmm->GetDestSpace();
10865 rv->m_nLastSpace = pCmm->GetLastSpace();
10866 rv->m_nLastIntent = pCmm->GetLastIntent();
10867
10868 if (rv->Begin()!=icCmmStatOk) {
10869 delete rv;
10870 return NULL;
10871 }
10872
10873 return rv;
10874}
10875
10876CIccApplyCmm *CIccMruCmm::GetNewApplyCmm(icStatusCMM &status)
10877{
10878 CIccApplyMruCmm *rv = new CIccApplyMruCmm(this);
10879
10880 if (!rv) {
10881 status = icCmmStatAllocErr;
10882 return NULL;
10883 }
10884
10885 if (!rv->Init(m_pCmm, m_nCacheSize)) {
10886 delete rv;
10887 status = icCmmStatBad;
10888 return NULL;
10889 }
10890
10891 return rv;
10892}
10893
10901template<class T>
10902CIccMruCache<T>::CIccMruCache()
10903{
10904 m_cache = NULL;
10905 m_nNumPixel = 0;
10906 m_pixelData = NULL;
10907 m_nSrcSamples = 0;
10908 m_pFirst = NULL;
10909}
10910
10918template<class T>
10919CIccMruCache<T>::~CIccMruCache()
10920{
10921 if (m_cache)
10922 delete[] m_cache;
10923
10924 if (m_pixelData)
10925 free(m_pixelData);
10926}
10927
10942template<class T>
10943bool CIccMruCache<T>::Init(icUInt16Number nSrcSamples, icUInt16Number nDstSamples, icUInt16Number nCacheSize)
10944{
10945 m_nSrcSamples = nSrcSamples;
10946 m_nSrcSize = nSrcSamples * sizeof(T);
10947 m_nDstSize = nDstSamples * sizeof(T);
10948
10949 m_nTotalSamples = m_nSrcSamples + nDstSamples;
10950
10951 m_nNumPixel = 0;
10952 m_nCacheSize = nCacheSize;
10953
10954 m_pFirst = NULL;
10955 m_cache = new CIccMruPixel<T>[nCacheSize];
10956
10957 if (!m_cache)
10958 return false;
10959
10960 m_pixelData = (T*)malloc((int)nCacheSize * m_nTotalSamples * sizeof(T));
10961
10962 if (!m_pixelData)
10963 return false;
10964
10965 return true;
10966}
10967
10968template<class T>
10969CIccMruCache<T> *CIccMruCache<T>::NewMruCache(icUInt16Number nSrcSamples, icUInt16Number nDstSamples, icUInt16Number nCacheSize /* = 4 */)
10970{
10971 CIccMruCache<T> *rv = new CIccMruCache<T>;
10972
10973 if (!rv->Init(nSrcSamples, nDstSamples, nCacheSize)) {
10974 delete rv;
10975 return NULL;
10976 }
10977
10978 return rv;
10979}
10980
10996template<class T>
10997bool CIccMruCache<T>::Apply(T* DstPixel, const T* SrcPixel)
10998{
10999 CIccMruPixel<T>* ptr, * prev = NULL, * last = NULL;
11000 int i;
11001 T* pixel;
11002
11003 for (ptr = m_pFirst, i = 0; ptr; ptr = ptr->pNext, i++) {
11004 if (!memcmp(SrcPixel, ptr->pPixelData, m_nSrcSize)) {
11005 memcpy(DstPixel, &ptr->pPixelData[m_nSrcSamples], m_nDstSize);
11006 if (ptr != m_pFirst) {
11007 if (last)
11008 last->pNext = ptr->pNext;
11009
11010 ptr->pNext = m_pFirst;
11011 m_pFirst = ptr;
11012 }
11013 return true;
11014 }
11015 prev = last;
11016 last = ptr;
11017 }
11018
11019 // If we get here SrcPixel is not in the cache
11020 if (i < m_nCacheSize) {
11021 pixel = &m_pixelData[i * m_nTotalSamples];
11022
11023 ptr = &m_cache[i];
11024 ptr->pPixelData = pixel;
11025 ptr->pNext = m_pFirst;
11026 m_pFirst = ptr;
11027 }
11028 else {
11029 if (last) {
11030 if (prev)
11031 prev->pNext = NULL;
11032
11033 last->pNext = m_pFirst;
11034 m_pFirst = last;
11035 pixel = last->pPixelData;
11036 }
11037 else {
11038 // Cache is empty — initialize first entry
11039 pixel = &m_pixelData[0];
11040 ptr = &m_cache[0];
11041 ptr->pPixelData = pixel;
11042 ptr->pNext = nullptr;
11043 m_pFirst = ptr;
11044 }
11045 }
11046
11047 T* dest = &pixel[m_nSrcSamples];
11048 memcpy(pixel, SrcPixel, m_nSrcSize);
11049
11050 return false;
11051}
11052
11053
11054template<class T>
11055void CIccMruCache<T>::Update(T* DstPixel)
11056{
11057 memcpy(&m_pFirst->pPixelData[m_nSrcSamples], DstPixel, m_nDstSize);
11058}
11059
11060//Make sure typedef classes get built
11061template class CIccMruCache<icFloatNumber>;
11062template class CIccMruCache<icUInt8Number>;
11063template class CIccMruCache<icUInt16Number>;
11064
11065
11066CIccApplyMruCmm::CIccApplyMruCmm(CIccMruCmm *pCmm) : CIccApplyCmm(pCmm)
11067{
11068 m_pCachedCmm = NULL;
11069 m_pCache = NULL;
11070}
11071
11079CIccApplyMruCmm::~CIccApplyMruCmm()
11080{
11081 if (m_pCache)
11082 delete m_pCache;
11083
11084}
11085
11100bool CIccApplyMruCmm::Init(CIccCmm *pCachedCmm, icUInt16Number nCacheSize)
11101{
11102 m_pCachedCmm = pCachedCmm;
11103
11104 m_pCache = CIccMruCacheFloat::NewMruCache(m_pCmm->GetSourceSamples(), m_pCmm->GetDestSamples(), nCacheSize);
11105
11106 if (!m_pCache)
11107 return false;
11108
11109 return true;
11110}
11111
11126icStatusCMM CIccApplyMruCmm::Apply(icFloatNumber *DstPixel, const icFloatNumber *SrcPixel)
11127{
11128#if defined(_DEBUG)
11129 if (!m_pCache)
11130 return icCmmStatInvalidLut;
11131#endif
11132
11133 if (!m_pCache->Apply(DstPixel, SrcPixel)) {
11134
11135 m_pCachedCmm->Apply(DstPixel, SrcPixel);
11136
11137 m_pCache->Update(DstPixel);
11138 }
11139
11140 return icCmmStatOk;
11141}
11142
11158icStatusCMM CIccApplyMruCmm::Apply(icFloatNumber *DstPixel, const icFloatNumber *SrcPixel, icUInt32Number nPixels)
11159{
11161
11162#if defined(_DEBUG)
11163 if (!m_pCache)
11164 return icCmmStatInvalidLut;
11165#endif
11166
11167 for (k=0; k<nPixels;k++) {
11168 if (!m_pCache->Apply(DstPixel, SrcPixel)) {
11169 m_pCachedCmm->Apply(DstPixel, SrcPixel);
11170 m_pCache->Update(DstPixel);
11171 }
11172 SrcPixel += m_pCmm->GetSourceSamples();
11173 DstPixel += m_pCmm->GetDestSamples();
11174 }
11175
11176 return icCmmStatOk;
11177}
11178
11179
11180#ifdef USEREFICCMAXNAMESPACE
11181} //namespace refIccMAX
11182#endif
#define icSigLabPcsData
Definition icProfileHeader.h:939
unsigned char icUInt8Number
Definition icProfileHeader.h:250
#define icUnknownIntent
Definition icProfileHeader.h:1152
#define icSigBRDFDirect
Definition icProfileHeader.h:902
unsigned short icUInt16Number
Definition icProfileHeader.h:256
#define icSigRadiantSpectralPcsData
Definition icProfileHeader.h:943
long icInt32Number
Definition icProfileHeader.h:291
#define icSigSparseMatrixSpectralPcsData
Definition icProfileHeader.h:945
icProfileClassSignature
Definition icProfileHeader.h:951
@ icSigAbstractClass
Definition icProfileHeader.h:956
@ icSigColorEncodingClass
Definition icProfileHeader.h:959
@ icSigMaterialVisualizationClass
Definition icProfileHeader.h:962
@ icSigInputClass
Definition icProfileHeader.h:952
@ icSigMaterialLinkClass
Definition icProfileHeader.h:961
@ icSigNamedColorClass
Definition icProfileHeader.h:958
@ icSigMaterialIdentificationClass
Definition icProfileHeader.h:960
@ icSigLinkClass
Definition icProfileHeader.h:955
@ icIlluminantUnknown
Definition icProfileHeader.h:1191
#define icSigXYZPcsData
Definition icProfileHeader.h:940
icUInt16Number steps
Definition icProfileHeader.h:1469
icS15Fixed16Number Y
Definition icProfileHeader.h:1430
#define icGetColorSpaceType(sig)
Definition icProfileHeader.h:932
#define icSparseMatrixFloatNum
Definition icProfileHeader.h:1359
@ icSigMatrixElemType
Definition icProfileHeader.h:644
icColorSpaceSignature
Definition icProfileHeader.h:843
@ icSigLuvData
Definition icProfileHeader.h:848
@ icSigNamedData
Definition icProfileHeader.h:873
@ icSigCmykData
Definition icProfileHeader.h:855
@ icSigRgbData
Definition icProfileHeader.h:851
@ icSigHlsData
Definition icProfileHeader.h:854
@ icSig4colorData
Definition icProfileHeader.h:861
@ icSigYCbCrData
Definition icProfileHeader.h:849
@ icSigCmyData
Definition icProfileHeader.h:856
@ icSigGrayData
Definition icProfileHeader.h:852
@ icSig3colorData
Definition icProfileHeader.h:860
@ icSigHsvData
Definition icProfileHeader.h:853
@ icSigYxyData
Definition icProfileHeader.h:850
unsigned long icUInt32Number
Definition icProfileHeader.h:262
icFloat16Number start
Definition icProfileHeader.h:1467
icUInt32Number icSignature
Definition icProfileHeader.h:271
@ icSigUtf8TextType
Definition icProfileHeader.h:574
@ icSigTagArrayType
Definition icProfileHeader.h:563
@ icSigMultiProcessElementType
Definition icProfileHeader.h:550
@ icSigParametricCurveType
Definition icProfileHeader.h:552
@ icSigXYZType
Definition icProfileHeader.h:576
@ icSigCurveType
Definition icProfileHeader.h:533
@ icSigNamedColor2Type
Definition icProfileHeader.h:551
#define icSigUnknownData
Definition icProfileHeader.h:903
#define icVersionNumberV5
Definition icProfileHeader.h:193
icFloat16Number end
Definition icProfileHeader.h:1468
icSpectralColorSignature
Definition icProfileHeader.h:907
icS15Fixed16Number Z
Definition icProfileHeader.h:1431
icS15Fixed16Number X
Definition icProfileHeader.h:1429
@ icSigNamedColorArray
Definition icProfileHeader.h:618
@ icSigUtf8TextTypeArray
Definition icProfileHeader.h:620
#define icSigReflectanceSpectralPcsData
Definition icProfileHeader.h:941
#define icSigBRDFParameters
Definition icProfileHeader.h:901
@ icSigBToD0Tag
Definition icProfileHeader.h:408
@ icSigGrayTRCTag
Definition icProfileHeader.h:421
@ icSigBRDFMToB1Tag
Definition icProfileHeader.h:367
@ icSigBRDFMToB3Tag
Definition icProfileHeader.h:369
@ icSigBRDFDToB0Tag
Definition icProfileHeader.h:362
@ icSigAToB3Tag
Definition icProfileHeader.h:345
@ icSigBlueMatrixColumnTag
Definition icProfileHeader.h:348
@ icSigMaterialDefaultValuesTag
Definition icProfileHeader.h:426
@ icSigMToS3Tag
Definition icProfileHeader.h:436
@ icSigBrdfSpectralParameter0Tag
Definition icProfileHeader.h:354
@ icSigGreenTRCTag
Definition icProfileHeader.h:424
@ icSigAToM0Tag
Definition icProfileHeader.h:346
@ icSigMToB0Tag
Definition icProfileHeader.h:429
@ icSigAToB0Tag
Definition icProfileHeader.h:342
@ icSigMToB3Tag
Definition icProfileHeader.h:432
@ icSigBToA1Tag
Definition icProfileHeader.h:375
@ icSigDToB3Tag
Definition icProfileHeader.h:407
@ icSigBRDFAToB0Tag
Definition icProfileHeader.h:358
@ icSigDToB0Tag
Definition icProfileHeader.h:404
@ icSigBToD3Tag
Definition icProfileHeader.h:411
@ icSigBToA0Tag
Definition icProfileHeader.h:374
@ icSigMToS0Tag
Definition icProfileHeader.h:433
@ icSigRedTRCTag
Definition icProfileHeader.h:463
@ icSigHToS1Tag
Definition icProfileHeader.h:418
@ icSigBToD1Tag
Definition icProfileHeader.h:409
@ icSigBlueTRCTag
Definition icProfileHeader.h:349
@ icSigMToB1Tag
Definition icProfileHeader.h:430
@ icSigHToS0Tag
Definition icProfileHeader.h:417
@ icSigGreenMatrixColumnTag
Definition icProfileHeader.h:423
@ icSigMediaWhitePointTag
Definition icProfileHeader.h:439
@ icSigBRDFMToS3Tag
Definition icProfileHeader.h:373
@ icSigAToB1Tag
Definition icProfileHeader.h:343
@ icSigBToA3Tag
Definition icProfileHeader.h:377
@ icSigBRDFMToS1Tag
Definition icProfileHeader.h:371
@ icSigBRDFMToS0Tag
Definition icProfileHeader.h:370
@ icSigPreview0Tag
Definition icProfileHeader.h:448
@ icSigNamedColor2Tag
Definition icProfileHeader.h:445
@ icSigRedMatrixColumnTag
Definition icProfileHeader.h:462
@ icSigGamutTag
Definition icProfileHeader.h:412
@ icSigMToA0Tag
Definition icProfileHeader.h:428
@ icSigMToS1Tag
Definition icProfileHeader.h:434
@ icSigDToB1Tag
Definition icProfileHeader.h:405
@ icSigBrdfColorimetricParameter0Tag
Definition icProfileHeader.h:350
@ icSigMaterialTypeArrayTag
Definition icProfileHeader.h:427
@ icSigBRDFMToB0Tag
Definition icProfileHeader.h:366
icRenderingIntent
Definition icProfileHeader.h:1142
@ icPerceptual
Definition icProfileHeader.h:1143
@ icRelativeColorimetric
Definition icProfileHeader.h:1144
@ icAbsoluteColorimetric
Definition icProfileHeader.h:1147
#define icMCSNeedsSubsetTrue
Definition icProfileHeader.h:225
#define icSigBiDirReflectanceSpectralPcsData
Definition icProfileHeader.h:944
@ icSigBrdfTransformMbr
Definition icProfileHeader.h:680
#define icSigTransmissionSpectralPcsData
Definition icProfileHeader.h:942
#define icSigGamutData
Definition icProfileHeader.h:900
Definition icProfileHeader.h:1428
Definition icProfileHeader.h:1466
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
#define icPerceptualRefWhiteX
Definition IccCmm.h:143
icXformInterp
CMM Interpolation types.
Definition IccCmm.h:113
@ icInterpLinear
Definition IccCmm.h:114
#define icPerceptualRefBlackZ
Definition IccCmm.h:141
#define icPerceptualRefBlackY
Definition IccCmm.h:140
#define icPerceptualRefWhiteZ
Definition IccCmm.h:145
icStatusCMM
CMM return status values.
Definition IccCmm.h:90
@ icCmmStatBadLutType
Definition IccCmm.h:103
@ icCmmStatInvalidProfile
Definition IccCmm.h:95
@ icCmmStatTooManySamples
Definition IccCmm.h:108
@ icCmmStatProfileMissingTag
Definition IccCmm.h:98
@ icCmmStatBadSpaceLink
Definition IccCmm.h:94
@ icCmmStatBadMCSLink
Definition IccCmm.h:109
@ icCmmStatIncorrectApply
Definition IccCmm.h:100
@ icCmmStatUnsupportedPcsLink
Definition IccCmm.h:105
@ icCmmStatBadColorEncoding
Definition IccCmm.h:101
@ icCmmStatCantOpenProfile
Definition IccCmm.h:93
@ icCmmStatBadConnection
Definition IccCmm.h:106
@ icCmmStatBadXform
Definition IccCmm.h:96
@ icCmmStatBad
Definition IccCmm.h:91
@ icCmmStatBadTintXform
Definition IccCmm.h:107
@ icCmmStatColorNotFound
Definition IccCmm.h:99
@ icCmmStatOk
Definition IccCmm.h:92
@ icCmmStatIdentityXform
Definition IccCmm.h:104
@ icCmmStatInvalidLut
Definition IccCmm.h:97
@ icCmmStatAllocErr
Definition IccCmm.h:102
icMCSConnectionType
Definition IccCmm.h:118
@ icNoMCS
Definition IccCmm.h:119
@ icToMCS
Definition IccCmm.h:120
@ icFromMCS
Definition IccCmm.h:121
#define icPerceptualRefWhiteY
Definition IccCmm.h:144
@ icXformTypeMpe
Definition IccCmm.h:154
@ icXformTypeMatrixTRC
Definition IccCmm.h:149
@ icXformTypeNDLut
Definition IccCmm.h:152
@ icXformTypeMonochrome
Definition IccCmm.h:155
@ icXformType3DLut
Definition IccCmm.h:150
@ icXformType4DLut
Definition IccCmm.h:151
@ icXformTypeNamedColor
Definition IccCmm.h:153
#define icPerceptualRefBlackX
Definition IccCmm.h:139
#define stricmp
Definition IccProfLibConf.h:149
CIccCurve * LPIccCurve
Definition IccTagLut.h:112
icFloatNumber deviceCoords[icAny]
Definition IccTagBasic.h:567
icFloatNumber pcsCoords[3]
Definition IccTagBasic.h:566
class ICCPROFLIB_API CIccProfile
Definition IccPcc.h:80
CIccProfile * OpenIccProfile(const icChar *szFilename, bool bUseSubProfile)
Definition IccProfile.cpp:3387
unsigned char icUChar
Definition IccDefs.h:111
float icFloatNumber
Definition IccDefs.h:101
icUInt16Number icU1Fixed15Number
Definition IccDefs.h:82
char icChar
Definition IccDefs.h:110
#define icSigLab2Data
Definition IccDefs.h:94
#define icNearRange
Definition IccMatrixMath.h:82
ICCPROFLIB_API icUInt32Number icGetSpectralSpaceSamples(const icHeader *pHdr)
Definition IccUtil.cpp:1367
ICCPROFLIB_API icFloatNumber icU8toF(icUInt8Number num)
Definition IccUtil.cpp:738
ICCPROFLIB_API bool icIsSpaceCLR(icColorSpaceSignature sig)
Definition IccUtil.cpp:262
ICCPROFLIB_API icUInt8Number icFtoU8(icFloatNumber num)
Definition IccUtil.cpp:724
ICCPROFLIB_API icU1Fixed15Number icDtoUSF(icFloatNumber num)
Definition IccUtil.cpp:587
ICCPROFLIB_API icS15Fixed16Number icDtoF(icFloatNumber num)
Definition IccUtil.cpp:545
ICCPROFLIB_API void icXyzToPcs(icFloatNumber *XYZ)
Definition IccUtil.cpp:941
ICCPROFLIB_API void icXYZtoLab(icFloatNumber *Lab, const icFloatNumber *XYZ=NULL, const icFloatNumber *WhiteXYZ=NULL)
Definition IccUtil.cpp:846
ICCPROFLIB_API icFloatNumber icFtoD(icS15Fixed16Number num)
Definition IccUtil.cpp:559
ICCPROFLIB_API void icLabToPcs(icFloatNumber *Lab)
Definition IccUtil.cpp:927
ICCPROFLIB_API icUInt32Number icGetSpaceSamples(icColorSpaceSignature sig)
Definition IccUtil.cpp:1303
ICCPROFLIB_API icUInt16Number icFtoU16(icFloatNumber num)
Definition IccUtil.cpp:745
ICCPROFLIB_API void icXyzFromPcs(icFloatNumber *XYZ)
Here are some conversion routines to convert to regular XYZ encoding.
Definition IccUtil.cpp:934
ICCPROFLIB_API icFloat16Number icFtoF16(icFloat32Number num)
Definition IccUtil.cpp:673
ICCPROFLIB_API icUInt8Number icABtoU8(icFloatNumber num)
Definition IccUtil.cpp:766
ICCPROFLIB_API bool icMatrixInvert3x3(icFloatNumber *matrix)
Definition IccUtil.cpp:391
bool ICCPROFLIB_API icSameSpectralRange(const icSpectralRange &rng1, const icSpectralRange &rng2)
Definition IccUtil.cpp:1399
ICCPROFLIB_API icFloatNumber icU16toF(icUInt16Number num)
Definition IccUtil.cpp:759
ICCPROFLIB_API void icLabtoXYZ(icFloatNumber *XYZ, const icFloatNumber *Lab=NULL, const icFloatNumber *WhiteXYZ=NULL)
Definition IccUtil.cpp:830
ICCPROFLIB_API icFloatNumber icU8toAB(icUInt8Number num)
Definition IccUtil.cpp:777
ICCPROFLIB_API void icLabFromPcs(icFloatNumber *Lab)
Here are some conversion routines to convert to regular Lab encoding.
Definition IccUtil.cpp:919
ICCPROFLIB_API icFloatNumber icUSFtoD(icU1Fixed15Number num)
Definition IccUtil.cpp:601
#define icUtf8StrCmp(x, y)
Definition IccUtil.h:188
ICCPROFLIB_API icFloat32Number icF16toF(icFloat16Number num)
Definition IccUtil.cpp:629
#define icNotZero(v)
Definition IccUtil.h:89
static __inline bool IsSpaceSpectralPCS(icUInt32Number sig)
Definition IccCmm.cpp:104
#define ICCPCSSTEPDUMPFMT
Definition IccCmm.cpp:129
#define IsCompatSpace(x, y)
Definition IccCmm.cpp:124
static icFloatNumber RGBClip(icFloatNumber v, CIccCurve *pCurve)
Definition IccCmm.cpp:5300
#define IsCompatSpacePCS(x, y)
Definition IccCmm.cpp:126
icFloatNumber icD50XYZ[3]
Definition IccUtil.cpp:782
static icFloatNumber XYZScale(icFloatNumber v)
Definition IccCmm.cpp:5289
#define IsSpaceColorimetricPCS(x)
Definition IccCmm.cpp:116
#define IsNChannelCompat(x, y)
Definition IccCmm.cpp:122
#define ICCDUMPPIXEL(n, pix)
Definition IccCmm.cpp:3376
static icFloatNumber XYZDescale(icFloatNumber v)
Definition IccCmm.cpp:5295
#define IsSpacePCS(x)
Definition IccCmm.cpp:118
@ icElemInterpLinear
Definition IccTagMPE.h:94
icStatusEncConvert ICCPROFLIB_API icConvertEncodingProfile(CIccProfilePtr &newIcc, CIccProfile *pEncodeIcc)
Definition IccEncoding.cpp:538
@ icEncConvertOk
Definition IccEncoding.h:75
static icFloatNumber UnitClip(icFloatNumber v)
Definition iccApplyProfiles.cpp:83
Definition IccArrayBasic.h:144
CIccStructNamedColor * FindColor(const icChar *szColor) const
Definition IccArrayBasic.cpp:303
bool GetSpectralTint(icFloatNumber *dstColor, const CIccStructNamedColor *pColor, icFloatNumber tint=1.0f, icNamedColorlMemberSignature sig=icSigNmclSpectralDataMbr) const
Definition IccArrayBasic.cpp:461
CIccStructNamedColor * FindSpectralColor(const icFloatNumber *pSpec, icFloatNumber dMinRms=1000.0) const
Definition IccArrayBasic.cpp:387
void SetColorSpaces(icColorSpaceSignature csPcs, icColorSpaceSignature csDevice, icSpectralColorSignature csSpectralPCS=icSigNoSpectralData, const icSpectralRange *pSpectralRange=NULL, const icSpectralRange *pBiSPectralRange=NULL)
Definition IccArrayBasic.cpp:261
CIccStructNamedColor * FindDeviceColor(const icFloatNumber *pDevColor) const
Definition IccArrayBasic.cpp:315
CIccStructNamedColor * FindPcsColor(const icFloatNumber *pPCS, icFloatNumber dMinDE=1000.0) const
Definition IccArrayBasic.cpp:349
bool GetDeviceTint(icFloatNumber *dstColor, const CIccStructNamedColor *pColor, icFloatNumber tint=1.0f, icNamedColorlMemberSignature sig=icSigNmclDeviceDataMbr) const
Definition IccArrayBasic.cpp:424
bool GetPcsTint(icFloatNumber *dstColor, const CIccStructNamedColor *pColor, icFloatNumber tint=1.0f, icNamedColorlMemberSignature sig=icSigNmclPcsDataMbr) const
Definition IccArrayBasic.cpp:443
CIccTag * GetElem(icSignature sigElem) const
Definition IccStructBasic.cpp:172
Definition IccStructBasic.h:127
std::string getName() const
Definition IccStructBasic.cpp:457
Definition IccStructBasic.h:161
Definition IccUtil.h:375
Definition IccTagComposite.h:226
bool AreAllOfType(icTagTypeSignature sigTagType)
Definition IccTagComposite.cpp:1145
IIccArray * GetArrayHandler()
Definition IccTagComposite.cpp:1624
CIccTag * GetIndex(icUInt32Number index) const
Definition IccTagComposite.cpp:1544
icUInt32Number GetSize() const
Returns the size of the data array.
Definition IccTagComposite.h:260
virtual icArraySignature GetTagArrayType() const
Definition IccTagComposite.h:238
static CIccXform * CreateXform(icXformType xformType, CIccTag *pTag=NULL, CIccCreateXformHintManager *pHintManager=NULL)
Definition IccXformFactory.h:185
Definition IccMpeBasic.h:600
icFloatNumber * GetConstants() const
Definition IccMpeBasic.h:619
virtual bool Begin(icElemInterp nInterp, CIccTagMultiProcessElement *pMPE)
Definition IccMpeBasic.cpp:5204
icFloatNumber * GetMatrix() const
Definition IccMpeBasic.h:618
bool GetApplyConstants() const
Definition IccMpeBasic.h:620
Definition IccPcc.h:94
virtual CIccTagMultiProcessElement * getStandardToCustomPcc()=0
virtual const CIccTagSpectralViewingConditions * getPccViewingConditions()=0
virtual CIccTagMultiProcessElement * getCustomToStandardPcc()=0
virtual void getLumIlluminantXYZ(icFloatNumber *pXYZ)=0
virtual bool getMediaWhiteXYZ(icFloatNumber *pXYZ)=0
icFloatNumber getObserverWhiteScaleFactor(const icFloatNumber *pWhite, const icSpectralRange &whiteRange)
Definition IccPcc.cpp:198
bool isStandardPcc()
Definition IccPcc.cpp:139
virtual void getNormIlluminantXYZ(icFloatNumber *pXYZ)=0
bool isEquivalentPcc(IIccProfileConnectionConditions &IPCC)
Definition IccPcc.cpp:79
Definition IccPcc.h:135
Definition IccIO.h:217
bool Attach(icUInt8Number *pData, icUInt32Number nSize, bool bWrite=false)
Definition IccIO.cpp:686
Definition IccSparseMatrix.h:154
static icUInt32Number MemSize(icUInt32Number nMaxEntries, icUInt16Number nRows, icUInt8Number nTypeSize)
Definition IccSparseMatrix.cpp:505
Definition IccTagBasic.h:108
virtual icTagTypeSignature GetType() const
Definition IccTagBasic.h:131
virtual bool IsSupported()
Definition IccTagBasic.h:153
virtual bool IsMBBType()
Definition IccTagBasic.h:136
virtual bool IsNumArrayType() const
Definition IccTagBasic.h:137
virtual icArraySignature GetTagArrayType() const
Definition IccTagBasic.h:133
Definition IccTagBasic.h:322
Definition IccTagBasic.h:582
icInt32Number FindDeviceColor(icFloatNumber *pDevColor) const
Definition IccTagBasic.cpp:3299
bool GetColorName(std::string &sColorName, icInt32Number index) const
Definition IccTagBasic.cpp:3348
icInt32Number FindColor(const icChar *szColor) const
Definition IccTagBasic.cpp:3255
icColorSpaceSignature GetPCS() const
Definition IccTagBasic.h:633
icUInt32Number GetDeviceCoords() const
Definition IccTagBasic.h:629
icColorSpaceSignature GetDeviceSpace() const
Definition IccTagBasic.h:634
icInt32Number FindCachedPCSColor(icFloatNumber *pPCS, icFloatNumber dMinDE=1000.0) const
Definition IccTagBasic.cpp:3180
SIccNamedColorEntry * GetEntry(icUInt32Number index) const
Definition IccTagBasic.h:626
Definition IccTagBasic.h:668
Definition IccTagBasic.h:791
virtual bool GetValues(icFloatNumber *DstVector, icUInt32Number nStart=0, icUInt32Number nVectorSize=1) const =0
Definition IccTagBasic.h:1692
const icFloatNumber * getObserver(icSpectralRange &observerRange) const
Definition IccTagBasic.cpp:11569
icFloatNumber getIlluminantCCT() const
Definition IccTagBasic.h:1713
icIlluminant getStdIllumiant() const
Definition IccTagBasic.h:1712
const icFloatNumber * getIlluminant(icSpectralRange &illumRange) const
Definition IccTagBasic.cpp:11405
icFloatNumber * applyRangeToObserver(const icSpectralRange &newRange) const
Definition IccTagBasic.cpp:11301
Definition IccTagLut.h:91
virtual icFloatNumber Apply(icFloatNumber v) const
Definition IccTagLut.h:101
virtual void Begin()
Definition IccTagLut.h:100
icFloatNumber Find(icFloatNumber v)
Definition IccTagLut.h:103
Definition IccTagLut.h:128
Definition IccTagLut.h:302
Definition IccTagLut.h:326
CIccApplyCLUT * GetNewApply()
Definition IccTagLut.cpp:2403
Definition IccTagLut.h:428
Definition IccTagMPE.h:146
virtual icUInt16Number NumInputChannels() const
Definition IccTagMPE.h:159
virtual icUInt16Number NumOutputChannels() const
Definition IccTagMPE.h:160
virtual icElemTypeSignature GetType() const =0
Definition IccTagMPE.h:358
icUInt16Number NumInputChannels() const
Definition IccTagMPE.h:393
icUInt16Number NumOutputChannels() const
Definition IccTagMPE.h:394
virtual CIccTag * NewCopy() const
Definition IccTagMPE.h:363
virtual void Apply(CIccApplyTagMpe *pApply, icFloatNumber *pDestPixel, const icFloatNumber *pSrcPixel) const
Definition IccTagMPE.cpp:1440
icUInt32Number NumElements() const
Definition IccTagMPE.h:398
CIccMultiProcessElement * GetElement(int nIndex)
Definition IccTagMPE.cpp:1189

◆ IsNChannelCompat

#define IsNChannelCompat (   x,
 
)    ((IsSpaceNChannel(x) && icNumColorSpaceChannels(x)==icGetSpaceSamples(y)) || (IsSpaceNChannel(y) && icNumColorSpaceChannels(y)==icGetSpaceSamples(x)))

◆ IsSpaceCMYK

#define IsSpaceCMYK (   x)    ((x)==icSigCmykData || (x)==icSig4colorData)

◆ IsSpaceColorimetricPCS

#define IsSpaceColorimetricPCS (   x)    ((x)==icSigXYZPcsData || (x)==icSigLabPcsData)

◆ IsSpaceDevicePCS

#define IsSpaceDevicePCS (   x)    ((x)==icSigDevXYZData || (x)==icSigDevLabData)

◆ IsSpaceMCS

#define IsSpaceMCS (   x)    (icGetColorSpaceType(x)==icSigSrcMCSChannelData)

◆ IsSpaceNChannel

#define IsSpaceNChannel (   x)    (icGetColorSpaceType(x)==icSigNChannelData)

◆ IsSpacePCS

#define IsSpacePCS (   x)    (IsSpaceColorimetricPCS(x) || IsSpaceSpectralPCS(x))

Function Documentation

◆ IsSpaceSpectralPCS()

static __inline bool IsSpaceSpectralPCS ( icUInt32Number  sig)
static

◆ RGBClip()

static icFloatNumber RGBClip ( icFloatNumber  v,
CIccCurve pCurve 
)
static
5301{
5302 if (v<=0)
5303 return(pCurve->Apply(0));
5304 else if (v>=1.0)
5305 return (pCurve->Apply(1.0));
5306
5307 return pCurve->Apply(v);
5308}

References CIccCurve::Apply().

+ Here is the call graph for this function:

◆ XYZDescale()

static icFloatNumber XYZDescale ( icFloatNumber  v)
static
5296{
5297 return (icFloatNumber)(v * 65535.0 / 32768.0);
5298}

◆ XYZScale()

static icFloatNumber XYZScale ( icFloatNumber  v)
static
5290{
5291 v = (icFloatNumber)(v * 32768.0 / 65535.0);
5292 return v;
5293}

Variable Documentation

◆ icD50XYZ

icFloatNumber icD50XYZ[3]
extern
782{ 0.9642f, 1.0000f, 0.8249f };