diff options
author | Marti Maria <info@littlecms.com> | 2011-04-12 15:48:03 +0200 |
---|---|---|
committer | Marti Maria <info@littlecms.com> | 2011-04-12 15:48:03 +0200 |
commit | 97f22bda885166a18e346db8dd24bd66bc4615cd (patch) | |
tree | df399bb7e3db23ae02b8a0b01262fe5041f6c783 | |
parent | b735a01cd82f08ef46733c9f19eb08ba1a6623af (diff) | |
download | lcms2-97f22bda885166a18e346db8dd24bd66bc4615cd.tar.gz |
Added named color functionality
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | src/cmscnvrt.c | 4 | ||||
-rw-r--r-- | src/cmserr.c | 2 | ||||
-rw-r--r-- | src/cmsio1.c | 40 | ||||
-rw-r--r-- | src/cmsnamed.c | 24 | ||||
-rw-r--r-- | src/cmspack.c | 2 | ||||
-rw-r--r-- | src/cmsxform.c | 13 | ||||
-rw-r--r-- | src/lcms2_internal.h | 2 | ||||
-rw-r--r-- | utils/transicc/transicc.c | 76 |
9 files changed, 127 insertions, 38 deletions
@@ -36,4 +36,4 @@ changed memmove to memcpy in cache for xput improvement Profiles with weird curves are not prone to p`relinearization optimization. Added functions to retrieve formatters from transforms Fixed a bug that made crash black preservation on CMYK2CMYK devicelinks - +Added named color functionality diff --git a/src/cmscnvrt.c b/src/cmscnvrt.c index 7e47d6c..8b5cd72 100644 --- a/src/cmscnvrt.c +++ b/src/cmscnvrt.c @@ -476,7 +476,7 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID, hProfile = hProfiles[i]; ClassSig = cmsGetDeviceClass(hProfile); lIsDeviceLink = (ClassSig == cmsSigLinkClass || ClassSig == cmsSigAbstractClass ); - + // First profile is used as input unless devicelink or abstract if ((i == 0) && !lIsDeviceLink) { lIsInput = TRUE; @@ -508,7 +508,7 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID, // If devicelink is found, then no custom intent is allowed and we can // read the LUT to be applied. Settings don't apply here. - if (lIsDeviceLink) { + if (lIsDeviceLink || ((ClassSig == cmsSigNamedColorClass) && (nProfiles == 1))) { // Get the involved LUT from the profile Lut = _cmsReadDevicelinkLUT(hProfile, Intent); diff --git a/src/cmserr.c b/src/cmserr.c index caa17e5..83d1e4f 100644 --- a/src/cmserr.c +++ b/src/cmserr.c @@ -250,7 +250,7 @@ void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Numbe // Sub allocation takes care of many pointers of small size. The memory allocated in // this way have be freed at once. Next function allocates a single chunk for linked list // I prefer this method over realloc due to the big inpact on xput realloc may have if -// memory is being swapped to disk. This approach is safer (although thats not true on any platform) +// memory is being swapped to disk. This approach is safer (although that may not be true on all platforms) static _cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32Number Initial) { diff --git a/src/cmsio1.c b/src/cmsio1.c index b235333..f746d81 100644 --- a/src/cmsio1.c +++ b/src/cmsio1.c @@ -246,6 +246,25 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) cmsTagSignature tagFloat = Device2PCSFloat[Intent]; cmsContext ContextID = cmsGetProfileContextID(hProfile); + // On named color, take the appropiate tag + if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { + + cmsPipeline* Lut; + cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) cmsReadTag(hProfile, cmsSigNamedColor2Tag); + + if (nc == NULL) return NULL; + + Lut = cmsPipelineAlloc(ContextID, 0, 0); + if (Lut == NULL) { + cmsFreeNamedColorList(nc); + return NULL; + } + + cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, TRUE)); + cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)); + return Lut; + } + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence // Floating point LUT are always V4, so no adjustment is required @@ -490,6 +509,27 @@ cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent) cmsTagSignature tagFloat = Device2PCSFloat[Intent]; cmsContext ContextID = cmsGetProfileContextID(hProfile); + + // On named color, take the appropiate tag + if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { + + cmsPipeline* Lut; + cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) cmsReadTag(hProfile, cmsSigNamedColor2Tag); + + if (nc == NULL) return NULL; + + Lut = cmsPipelineAlloc(ContextID, 0, 0); + if (Lut == NULL) { + cmsFreeNamedColorList(nc); + return NULL; + } + + cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, FALSE)); + if (cmsGetColorSpace(hProfile) == cmsSigLabData) + cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)); + return Lut; + } + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence // Floating point LUT are always V4, no adjustment is required diff --git a/src/cmsnamed.c b/src/cmsnamed.c index d1a86b6..f4f423d 100644 --- a/src/cmsnamed.c +++ b/src/cmsnamed.c @@ -619,6 +619,24 @@ void* DupNamedColorList(cmsStage* mpe) } static +void EvalNamedColorPCS(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) +{ + cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) mpe ->Data; + cmsUInt16Number index = (cmsUInt16Number) _cmsQuickSaturateWord(In[0] * 65535.0); + + if (index >= NamedColorList-> nColors) { + cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index); + } + else { + + // Named color always uses Lab + Out[0] = (cmsFloat32Number) (NamedColorList->List[index].PCS[0] / 65535.0); + Out[1] = (cmsFloat32Number) (NamedColorList->List[index].PCS[1] / 65535.0); + Out[2] = (cmsFloat32Number) (NamedColorList->List[index].PCS[2] / 65535.0); + } +} + +static void EvalNamedColor(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) { cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) mpe ->Data; @@ -636,12 +654,12 @@ void EvalNamedColor(const cmsFloat32Number In[], cmsFloat32Number Out[], const c // Named color lookup element -cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList) +cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS) { return _cmsStageAllocPlaceholder(NamedColorList ->ContextID, cmsSigNamedColorElemType, - 1, 3, - EvalNamedColor, + 1, UsePCS ? 3 : NamedColorList ->ColorantCount, + UsePCS ? EvalNamedColorPCS : EvalNamedColor, DupNamedColorList, FreeNamedColorList, cmsDupNamedColorList(NamedColorList)); diff --git a/src/cmspack.c b/src/cmspack.c index ae8df4f..c49961f 100644 --- a/src/cmspack.c +++ b/src/cmspack.c @@ -1873,7 +1873,7 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* Info, cmsFloat64Number* Inks = (cmsFloat64Number*) output; int nChan = T_CHANNELS(Info -> OutputFormat); int i; - cmsFloat64Number maximum = IsInkSpace(Info ->InputFormat) ? 655.35 : 65535.0; + cmsFloat64Number maximum = IsInkSpace(Info ->OutputFormat) ? 655.35 : 65535.0; if (T_PLANAR(Info -> OutputFormat)) { diff --git a/src/cmsxform.c b/src/cmsxform.c index 4e13e1a..e7f30c5 100644 --- a/src/cmsxform.c +++ b/src/cmsxform.c @@ -433,6 +433,13 @@ cmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpac *Input = PostColorSpace = cmsGetColorSpace(hProfiles[0]); + // Special handling for named color profiles as devicelinks + if (nProfiles == 1 && cmsGetDeviceClass(hProfiles[0]) == cmsSigNamedColorClass) { + *Input = cmsSig1colorData; + *Output = PostColorSpace; + return TRUE; + } + for (i=0; i < nProfiles; i++) { cmsHPROFILE hProfile = hProfiles[i]; @@ -440,9 +447,13 @@ cmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpac int lIsInput = (PostColorSpace != cmsSigXYZData) && (PostColorSpace != cmsSigLabData); + int lIsDeviceLink; + if (hProfile == NULL) return FALSE; - if (lIsInput) { + lIsDeviceLink = (cmsGetDeviceClass(hProfile) == cmsSigLinkClass); + + if (lIsInput || lIsDeviceLink) { ColorSpaceIn = cmsGetColorSpace(hProfile); ColorSpaceOut = cmsGetPCS(hProfile); diff --git a/src/lcms2_internal.h b/src/lcms2_internal.h index cdcba71..872272a 100644 --- a/src/lcms2_internal.h +++ b/src/lcms2_internal.h @@ -424,7 +424,7 @@ cmsStage* _cmsStageAllocLabPrelin(cmsContext ContextID); cmsStage* _cmsStageAllocLabV2ToV4(cmsContext ContextID); cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID); cmsStage* _cmsStageAllocLabV4ToV2(cmsContext ContextID); -cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList); +cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS); cmsStage* _cmsStageAllocIdentityCurves(cmsContext ContextID, int nChannels); cmsStage* _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan); diff --git a/utils/transicc/transicc.c b/utils/transicc/transicc.c index 1840e33..8993004 100644 --- a/utils/transicc/transicc.c +++ b/utils/transicc/transicc.c @@ -261,10 +261,10 @@ void HandleSwitches(int argc, char *argv[]) } - // If output CGATS involved, switch to float - if ((argc - xoptind) > 2) { - lIsFloat = TRUE; - } + // If output CGATS involved, switch to float + if ((argc - xoptind) > 2) { + lIsFloat = TRUE; + } } @@ -272,10 +272,10 @@ void HandleSwitches(int argc, char *argv[]) static void SetRange(cmsFloat64Number range, cmsBool IsInput) { - if (IsInput) - InputRange = range; - else - OutputRange = range; + if (IsInput) + InputRange = range; + else + OutputRange = range; } // Populate a named color list with usual component names. @@ -407,14 +407,20 @@ cmsBool OpenTransforms(void) hOutput = NULL; hProof = NULL; - InputColorSpace = cmsGetColorSpace(hInput); - OutputColorSpace = cmsGetPCS(hInput); + if (cmsGetDeviceClass(hInput) == cmsSigNamedColorClass) { + OutputColorSpace = cmsGetColorSpace(hInput); + InputColorSpace = cmsGetPCS(hInput); + } + else { + InputColorSpace = cmsGetColorSpace(hInput); + OutputColorSpace = cmsGetPCS(hInput); + } // Read colorant tables if present if (cmsIsTag(hInput, cmsSigColorantTableTag)) { List = cmsReadTag(hInput, cmsSigColorantTableTag); InputColorant = cmsDupNamedColorList(List); - InputRange = 1; + InputRange = 1; } else InputColorant = ComponentNames(InputColorSpace, TRUE); @@ -422,7 +428,7 @@ cmsBool OpenTransforms(void) List = cmsReadTag(hInput, cmsSigColorantTableOutTag); OutputColorant = cmsDupNamedColorList(List); - OutputRange = 1; + OutputRange = 1; } else OutputColorant = ComponentNames(OutputColorSpace, FALSE); @@ -490,18 +496,19 @@ cmsBool OpenTransforms(void) // Input is always in floating point dwIn = cmsFormatterForColorspaceOfProfile(hInput, 0, TRUE); - if (lIsDeviceLink) { + if (lIsDeviceLink) { - dwOut = cmsFormatterForPCSOfProfile(hInput, lIsFloat ? 0 : 2, lIsFloat); - } - else { - - // 16 bits or floating point (only on output) + dwOut = cmsFormatterForPCSOfProfile(hInput, lIsFloat ? 0 : 2, lIsFloat); + } + else { + + // 16 bits or floating point (only on output) dwOut = cmsFormatterForColorspaceOfProfile(hOutput, lIsFloat ? 0 : 2, lIsFloat); - } + } // For named color, there is a specialized formatter if (cmsGetDeviceClass(hInput) == cmsSigNamedColorClass) { + dwOut = dwIn; dwIn = TYPE_NAMED_COLOR_INDEX; InputNamedColor = TRUE; } @@ -657,8 +664,12 @@ cmsUInt16Number GetIndex(void) { char Buffer[4096], Name[40], Prefix[40], Suffix[40]; int index, max; + const cmsNAMEDCOLORLIST* NamedColorList; + + NamedColorList = cmsGetNamedColorList(hTrans); + if (NamedColorList == NULL) return 0; - max = cmsNamedColorCount(hTrans)-1; + max = cmsNamedColorCount(NamedColorList)-1; GetLine(Buffer, "Color index (0..%d)? ", max); index = atoi(Buffer); @@ -666,9 +677,9 @@ cmsUInt16Number GetIndex(void) if (index > max) FatalError("Named color %d out of range!", index); - cmsNamedColorInfo(hTrans, index, Name, Prefix, Suffix, NULL, NULL); + cmsNamedColorInfo(NamedColorList, index, Name, Prefix, Suffix, NULL, NULL); - printf("\n%s %s %s: ", Prefix, Name, Suffix); + printf("\n%s %s %s\n", Prefix, Name, Suffix); return (cmsUInt16Number) index; } @@ -686,7 +697,9 @@ void TakeFloatValues(cmsFloat64Number Float[]) if (InputNamedColor) { - Float[0] = GetIndex(); + // This is named color index, which is always cmsUInt16Number + cmsUInt16Number index = GetIndex(); + memcpy(Float, &index, sizeof(cmsUInt16Number)); return; } @@ -697,7 +710,7 @@ void TakeFloatValues(cmsFloat64Number Float[]) cmsNamedColorInfo(InputColorant, i, ChannelName, NULL, NULL, NULL, NULL); } else { - InputRange = 1; + InputRange = 1; sprintf(ChannelName, "Channel #%d", i+1); } @@ -830,8 +843,15 @@ void TakeCGATSValues(int nPatch, cmsFloat64Number Float[]) if (InputNamedColor) { - int index = cmsNamedColorIndex(hTrans, CGATSPatch); - if (index < 0) + const cmsNAMEDCOLORLIST* NamedColorList; + int index; + + NamedColorList = cmsGetNamedColorList(hTrans); + if (NamedColorList == NULL) + FatalError("Malformed named color profile"); + + index = cmsNamedColorIndex(NamedColorList, CGATSPatch); + if (index < 0) FatalError("Named color '%s' not found in the profile", CGATSPatch); Float[0] = index; @@ -982,7 +1002,7 @@ void PutCGATSValues(cmsFloat64Number Float[]) static void SetOutputDataFormat(void) { - cmsIT8DefineDblFormat(hIT8out, "%.4g"); + cmsIT8DefineDblFormat(hIT8out, "%.4g"); cmsIT8SetPropertyStr(hIT8out, "ORIGINATOR", "icctrans"); if (IncludePart != NULL) @@ -1104,7 +1124,7 @@ int main(int argc, char *argv[]) InitUtils("transicc"); - Verbose = 1; + Verbose = 1; if (argc == 1) { |