summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarti Maria <info@littlecms.com>2011-04-12 15:48:03 +0200
committerMarti Maria <info@littlecms.com>2011-04-12 15:48:03 +0200
commit97f22bda885166a18e346db8dd24bd66bc4615cd (patch)
treedf399bb7e3db23ae02b8a0b01262fe5041f6c783
parentb735a01cd82f08ef46733c9f19eb08ba1a6623af (diff)
downloadlcms2-97f22bda885166a18e346db8dd24bd66bc4615cd.tar.gz
Added named color functionality
-rw-r--r--ChangeLog2
-rw-r--r--src/cmscnvrt.c4
-rw-r--r--src/cmserr.c2
-rw-r--r--src/cmsio1.c40
-rw-r--r--src/cmsnamed.c24
-rw-r--r--src/cmspack.c2
-rw-r--r--src/cmsxform.c13
-rw-r--r--src/lcms2_internal.h2
-rw-r--r--utils/transicc/transicc.c76
9 files changed, 127 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index d8dc63c..34262b1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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) {