“fed81c404311e77ed9527413851e7294373fc24c”上不存在“src/share/classes/java/lang/invoke/ToGeneric.java”
提交 1ce44c68 编写于 作者: P prr

8029750: Enhance LCMS color processing

Reviewed-by: bae, vadim, mschoene
上级 f91f21c6
...@@ -467,6 +467,7 @@ void CMSEXPORT cmsCIECAM02Forward(cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh ...@@ -467,6 +467,7 @@ void CMSEXPORT cmsCIECAM02Forward(cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh
CAM02COLOR clr; CAM02COLOR clr;
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel; cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
memset(&clr, 0, sizeof(clr));
_cmsAssert(lpMod != NULL); _cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL); _cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL); _cmsAssert(pOut != NULL);
...@@ -491,6 +492,7 @@ void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ ...@@ -491,6 +492,7 @@ void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ
CAM02COLOR clr; CAM02COLOR clr;
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel; cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
memset(&clr, 0, sizeof(clr));
_cmsAssert(lpMod != NULL); _cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL); _cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL); _cmsAssert(pOut != NULL);
......
...@@ -59,8 +59,8 @@ ...@@ -59,8 +59,8 @@
// IT8.7 / CGATS.17-200x handling ----------------------------------------------------------------------------- // IT8.7 / CGATS.17-200x handling -----------------------------------------------------------------------------
#define MAXID 128 // Max lenght of identifier #define MAXID 128 // Max length of identifier
#define MAXSTR 1024 // Max lenght of string #define MAXSTR 1024 // Max length of string
#define MAXTABLES 255 // Max Number of tables in a single stream #define MAXTABLES 255 // Max Number of tables in a single stream
#define MAXINCLUDE 20 // Max number of nested includes #define MAXINCLUDE 20 // Max number of nested includes
...@@ -383,28 +383,28 @@ static const char* PredefinedSampleID[] = { ...@@ -383,28 +383,28 @@ static const char* PredefinedSampleID[] = {
//Forward declaration of some internal functions //Forward declaration of some internal functions
static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size); static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size);
// Checks if c is a separator // Checks whatever c is a separator
static static
cmsBool isseparator(int c) cmsBool isseparator(int c)
{ {
return (c == ' ') || (c == '\t') || (c == '\r'); return (c == ' ') || (c == '\t') ;
} }
// Checks whatever if c is a valid identifier char // Checks whatever c is a valid identifier char
static static
cmsBool ismiddle(int c) cmsBool ismiddle(int c)
{ {
return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127)); return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127));
} }
// Checks whatsever if c is a valid identifier middle char. // Checks whatsever c is a valid identifier middle char.
static static
cmsBool isidchar(int c) cmsBool isidchar(int c)
{ {
return isalnum(c) || ismiddle(c); return isalnum(c) || ismiddle(c);
} }
// Checks whatsever if c is a valid identifier first char. // Checks whatsever c is a valid identifier first char.
static static
cmsBool isfirstidchar(int c) cmsBool isfirstidchar(int c)
{ {
...@@ -436,7 +436,6 @@ cmsBool isabsolutepath(const char *path) ...@@ -436,7 +436,6 @@ cmsBool isabsolutepath(const char *path)
} }
// Makes a file path based on a given reference path // Makes a file path based on a given reference path
// NOTE: this function doesn't check if the path exists or even if it's legal // NOTE: this function doesn't check if the path exists or even if it's legal
static static
...@@ -634,6 +633,7 @@ cmsFloat64Number ParseFloatNumber(const char *Buffer) ...@@ -634,6 +633,7 @@ cmsFloat64Number ParseFloatNumber(const char *Buffer)
cmsFloat64Number dnum = 0.0; cmsFloat64Number dnum = 0.0;
int sign = 1; int sign = 1;
// keep safe
if (Buffer == NULL) return 0.0; if (Buffer == NULL) return 0.0;
if (*Buffer == '-' || *Buffer == '+') { if (*Buffer == '-' || *Buffer == '+') {
...@@ -869,6 +869,14 @@ void InSymbol(cmsIT8* it8) ...@@ -869,6 +869,14 @@ void InSymbol(cmsIT8* it8)
// Next line // Next line
case '\r':
NextCh(it8);
if (it8 ->ch == '\n')
NextCh(it8);
it8->sy = SEOLN;
it8->lineno++;
break;
case '\n': case '\n':
NextCh(it8); NextCh(it8);
it8->sy = SEOLN; it8->sy = SEOLN;
...@@ -878,7 +886,7 @@ void InSymbol(cmsIT8* it8) ...@@ -878,7 +886,7 @@ void InSymbol(cmsIT8* it8)
// Comment // Comment
case '#': case '#':
NextCh(it8); NextCh(it8);
while (it8->ch && it8->ch != '\n') while (it8->ch && it8->ch != '\n' && it8->ch != '\r')
NextCh(it8); NextCh(it8);
it8->sy = SCOMMENT; it8->sy = SCOMMENT;
...@@ -996,6 +1004,9 @@ cmsBool GetVal(cmsIT8* it8, char* Buffer, cmsUInt32Number max, const char* Error ...@@ -996,6 +1004,9 @@ cmsBool GetVal(cmsIT8* it8, char* Buffer, cmsUInt32Number max, const char* Error
{ {
switch (it8->sy) { switch (it8->sy) {
case SEOLN: // Empty value
Buffer[0]=0;
break;
case SIDENT: strncpy(Buffer, it8->id, max); case SIDENT: strncpy(Buffer, it8->id, max);
Buffer[max-1]=0; Buffer[max-1]=0;
break; break;
...@@ -1157,6 +1168,8 @@ cmsBool IsAvailableOnList(KEYVALUE* p, const char* Key, const char* Subkey, KEYV ...@@ -1157,6 +1168,8 @@ cmsBool IsAvailableOnList(KEYVALUE* p, const char* Key, const char* Subkey, KEYV
for (; p != NULL; p = p->NextSubkey) { for (; p != NULL; p = p->NextSubkey) {
if (p ->Subkey == NULL) continue;
if (LastPtr) *LastPtr = p; if (LastPtr) *LastPtr = p;
if (cmsstrcasecmp(Subkey, p->Subkey) == 0) if (cmsstrcasecmp(Subkey, p->Subkey) == 0)
...@@ -1284,7 +1297,7 @@ cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE IT8, cmsUInt32Number nTable) ...@@ -1284,7 +1297,7 @@ cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE IT8, cmsUInt32Number nTable)
it8 ->nTable = nTable; it8 ->nTable = nTable;
return nTable; return (cmsInt32Number) nTable;
} }
...@@ -1389,7 +1402,7 @@ cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUIn ...@@ -1389,7 +1402,7 @@ cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUIn
cmsIT8* it8 = (cmsIT8*) hIT8; cmsIT8* it8 = (cmsIT8*) hIT8;
char Buffer[1024]; char Buffer[1024];
sprintf(Buffer, "%d", Val); sprintf(Buffer, "%u", Val);
return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL; return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL;
} }
...@@ -1426,6 +1439,8 @@ cmsFloat64Number CMSEXPORT cmsIT8GetPropertyDbl(cmsHANDLE hIT8, const char* cPro ...@@ -1426,6 +1439,8 @@ cmsFloat64Number CMSEXPORT cmsIT8GetPropertyDbl(cmsHANDLE hIT8, const char* cPro
{ {
const char *v = cmsIT8GetProperty(hIT8, cProp); const char *v = cmsIT8GetProperty(hIT8, cProp);
if (v == NULL) return 0.0;
return ParseFloatNumber(v); return ParseFloatNumber(v);
} }
...@@ -1458,7 +1473,7 @@ void AllocateDataFormat(cmsIT8* it8) ...@@ -1458,7 +1473,7 @@ void AllocateDataFormat(cmsIT8* it8)
t -> nSamples = 10; t -> nSamples = 10;
} }
t -> DataFormat = (char**) AllocChunk (it8, (t->nSamples + 1) * sizeof(char *)); t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *));
if (t->DataFormat == NULL) { if (t->DataFormat == NULL) {
SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array"); SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array");
...@@ -1514,7 +1529,7 @@ void AllocateDataSet(cmsIT8* it8) ...@@ -1514,7 +1529,7 @@ void AllocateDataSet(cmsIT8* it8)
t-> nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS")); t-> nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
t-> nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS")); t-> nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
t-> Data = (char**)AllocChunk (it8, (t->nSamples + 1) * (t->nPatches + 1) *sizeof (char*)); t-> Data = (char**)AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * ((cmsUInt32Number) t->nPatches + 1) *sizeof (char*));
if (t->Data == NULL) { if (t->Data == NULL) {
SynError(it8, "AllocateDataSet: Unable to allocate data array"); SynError(it8, "AllocateDataSet: Unable to allocate data array");
...@@ -1573,7 +1588,7 @@ void WriteStr(SAVESTREAM* f, const char *str) ...@@ -1573,7 +1588,7 @@ void WriteStr(SAVESTREAM* f, const char *str)
if (str == NULL) if (str == NULL)
str = " "; str = " ";
// Lenghth to write // Length to write
len = (cmsUInt32Number) strlen(str); len = (cmsUInt32Number) strlen(str);
f ->Used += len; f ->Used += len;
...@@ -2097,7 +2112,7 @@ cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet) ...@@ -2097,7 +2112,7 @@ cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
NextCh(it8); NextCh(it8);
// If a newline is found, then this is a type string // If a newline is found, then this is a type string
if (it8 ->ch == '\n') { if (it8 ->ch == '\n' || it8->ch == '\r') {
cmsIT8SetSheetType(it8, it8 ->id); cmsIT8SetSheetType(it8, it8 ->id);
InSymbol(it8); InSymbol(it8);
...@@ -2212,7 +2227,7 @@ void CookPointers(cmsIT8* it8) ...@@ -2212,7 +2227,7 @@ void CookPointers(cmsIT8* it8)
char Buffer[256]; char Buffer[256];
char *Type = p ->Value; char *Type = p ->Value;
int nTable = k; int nTable = (int) k;
snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type ); snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type );
...@@ -2566,6 +2581,8 @@ cmsFloat64Number CMSEXPORT cmsIT8GetDataRowColDbl(cmsHANDLE hIT8, int row, int c ...@@ -2566,6 +2581,8 @@ cmsFloat64Number CMSEXPORT cmsIT8GetDataRowColDbl(cmsHANDLE hIT8, int row, int c
Buffer = cmsIT8GetDataRowCol(hIT8, row, col); Buffer = cmsIT8GetDataRowCol(hIT8, row, col);
if (Buffer == NULL) return 0.0;
return ParseFloatNumber(Buffer); return ParseFloatNumber(Buffer);
} }
...@@ -2778,7 +2795,7 @@ void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter) ...@@ -2778,7 +2795,7 @@ void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter)
if (Formatter == NULL) if (Formatter == NULL)
strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT); strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
else else
strcpy(it8->DoubleFormatter, Formatter); strncpy(it8->DoubleFormatter, Formatter, sizeof(it8->DoubleFormatter));
it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0; it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0;
} }
......
...@@ -270,7 +270,7 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState, ...@@ -270,7 +270,7 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState,
// m2 holds CHAD from output white to D50 times abs. col. scaling // m2 holds CHAD from output white to D50 times abs. col. scaling
// Observer is not adapted, undo the chromatic adaptation // Observer is not adapted, undo the chromatic adaptation
_cmsMAT3per(m, &m3, ChromaticAdaptationMatrixOut); _cmsMAT3per(m, &m2, ChromaticAdaptationMatrixOut);
m3 = *ChromaticAdaptationMatrixIn; m3 = *ChromaticAdaptationMatrixIn;
if (!_cmsMAT3inverse(&m3, &m4)) return FALSE; if (!_cmsMAT3inverse(&m3, &m4)) return FALSE;
...@@ -416,14 +416,17 @@ cmsBool AddConversion(cmsPipeline* Result, cmsColorSpaceSignature InPCS, cmsColo ...@@ -416,14 +416,17 @@ cmsBool AddConversion(cmsPipeline* Result, cmsColorSpaceSignature InPCS, cmsColo
switch (OutPCS) { switch (OutPCS) {
case cmsSigXYZData: // XYZ -> XYZ case cmsSigXYZData: // XYZ -> XYZ
if (!IsEmptyLayer(m, off)) if (!IsEmptyLayer(m, off) &&
cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)); !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)))
return FALSE;
break; break;
case cmsSigLabData: // XYZ -> Lab case cmsSigLabData: // XYZ -> Lab
if (!IsEmptyLayer(m, off)) if (!IsEmptyLayer(m, off) &&
cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)); !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)))
cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID)); return FALSE;
if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID)))
return FALSE;
break; break;
default: default:
...@@ -431,24 +434,26 @@ cmsBool AddConversion(cmsPipeline* Result, cmsColorSpaceSignature InPCS, cmsColo ...@@ -431,24 +434,26 @@ cmsBool AddConversion(cmsPipeline* Result, cmsColorSpaceSignature InPCS, cmsColo
} }
break; break;
case cmsSigLabData: // Input profile operates in Lab case cmsSigLabData: // Input profile operates in Lab
switch (OutPCS) { switch (OutPCS) {
case cmsSigXYZData: // Lab -> XYZ case cmsSigXYZData: // Lab -> XYZ
cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID)); if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID)))
if (!IsEmptyLayer(m, off)) return FALSE;
cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)); if (!IsEmptyLayer(m, off) &&
!cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)))
return FALSE;
break; break;
case cmsSigLabData: // Lab -> Lab case cmsSigLabData: // Lab -> Lab
if (!IsEmptyLayer(m, off)) { if (!IsEmptyLayer(m, off)) {
cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID)); if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID)) ||
cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)); !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)) ||
cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID)); !cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID)))
return FALSE;
} }
break; break;
...@@ -457,7 +462,6 @@ cmsBool AddConversion(cmsPipeline* Result, cmsColorSpaceSignature InPCS, cmsColo ...@@ -457,7 +462,6 @@ cmsBool AddConversion(cmsPipeline* Result, cmsColorSpaceSignature InPCS, cmsColo
} }
break; break;
// On colorspaces other than PCS, check for same space // On colorspaces other than PCS, check for same space
default: default:
if (InPCS != OutPCS) return FALSE; if (InPCS != OutPCS) return FALSE;
...@@ -497,7 +501,8 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID, ...@@ -497,7 +501,8 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID,
cmsFloat64Number AdaptationStates[], cmsFloat64Number AdaptationStates[],
cmsUInt32Number dwFlags) cmsUInt32Number dwFlags)
{ {
cmsPipeline* Lut, *Result; cmsPipeline* Lut = NULL;
cmsPipeline* Result;
cmsHPROFILE hProfile; cmsHPROFILE hProfile;
cmsMAT3 m; cmsMAT3 m;
cmsVEC3 off; cmsVEC3 off;
...@@ -593,8 +598,11 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID, ...@@ -593,8 +598,11 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID,
} }
// Concatenate to the output LUT // Concatenate to the output LUT
cmsPipelineCat(Result, Lut); if (!cmsPipelineCat(Result, Lut))
goto Error;
cmsPipelineFree(Lut); cmsPipelineFree(Lut);
Lut = NULL;
// Update current space // Update current space
CurrentColorSpace = ColorSpaceOut; CurrentColorSpace = ColorSpaceOut;
...@@ -604,6 +612,7 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID, ...@@ -604,6 +612,7 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID,
Error: Error:
if (Lut != NULL) cmsPipelineFree(Lut);
if (Result != NULL) cmsPipelineFree(Result); if (Result != NULL) cmsPipelineFree(Result);
return NULL; return NULL;
...@@ -742,7 +751,8 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID, ...@@ -742,7 +751,8 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
if (CLUT == NULL) goto Error; if (CLUT == NULL) goto Error;
// This is the one and only MPE in this LUT // This is the one and only MPE in this LUT
cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT); if (!cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT))
goto Error;
// Sample it. We cannot afford pre/post linearization this time. // Sample it. We cannot afford pre/post linearization this time.
if (!cmsStageSampleCLut16bit(CLUT, BlackPreservingGrayOnlySampler, (void*) &bp, 0)) if (!cmsStageSampleCLut16bit(CLUT, BlackPreservingGrayOnlySampler, (void*) &bp, 0))
...@@ -959,7 +969,8 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID, ...@@ -959,7 +969,8 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
CLUT = cmsStageAllocCLut16bit(ContextID, nGridPoints, 4, 4, NULL); CLUT = cmsStageAllocCLut16bit(ContextID, nGridPoints, 4, 4, NULL);
if (CLUT == NULL) goto Cleanup; if (CLUT == NULL) goto Cleanup;
cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT); if (!cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT))
goto Cleanup;
cmsStageSampleCLut16bit(CLUT, BlackPreservingSampler, (void*) &bp, 0); cmsStageSampleCLut16bit(CLUT, BlackPreservingSampler, (void*) &bp, 0);
...@@ -1057,7 +1068,7 @@ cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32 ...@@ -1057,7 +1068,7 @@ cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32
} }
// The plug-in registration. User can add new intents or override default routines // The plug-in registration. User can add new intents or override default routines
cmsBool _cmsRegisterRenderingIntentPlugin(cmsPluginBase* Data) cmsBool _cmsRegisterRenderingIntentPlugin(cmsContext id, cmsPluginBase* Data)
{ {
cmsPluginRenderingIntent* Plugin = (cmsPluginRenderingIntent*) Data; cmsPluginRenderingIntent* Plugin = (cmsPluginRenderingIntent*) Data;
cmsIntentsList* fl; cmsIntentsList* fl;
...@@ -1072,7 +1083,7 @@ cmsBool _cmsRegisterRenderingIntentPlugin(cmsPluginBase* Data) ...@@ -1072,7 +1083,7 @@ cmsBool _cmsRegisterRenderingIntentPlugin(cmsPluginBase* Data)
fl = SearchIntent(Plugin ->Intent); fl = SearchIntent(Plugin ->Intent);
if (fl == NULL) { if (fl == NULL) {
fl = (cmsIntentsList*) _cmsPluginMalloc(sizeof(cmsIntentsList)); fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList));
if (fl == NULL) return FALSE; if (fl == NULL) return FALSE;
} }
......
...@@ -302,8 +302,6 @@ _cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32N ...@@ -302,8 +302,6 @@ _cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32N
return NULL; return NULL;
} }
chunk ->BlockSize = Initial; chunk ->BlockSize = Initial;
chunk ->Used = 0; chunk ->Used = 0;
chunk ->next = NULL; chunk ->next = NULL;
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// //
// Little Color Management System // Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer // Copyright (c) 1998-2013 Marti Maria Saguer
// //
// Permission is hereby granted, free of charge, to any person obtaining // Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"), // a copy of this software and associated documentation files (the "Software"),
...@@ -99,7 +99,7 @@ static _cmsParametricCurvesCollection DefaultCurves = { ...@@ -99,7 +99,7 @@ static _cmsParametricCurvesCollection DefaultCurves = {
static _cmsParametricCurvesCollection* ParametricCurves = &DefaultCurves; static _cmsParametricCurvesCollection* ParametricCurves = &DefaultCurves;
// As a way to install new parametric curves // As a way to install new parametric curves
cmsBool _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Data) cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext id, cmsPluginBase* Data)
{ {
cmsPluginParametricCurves* Plugin = (cmsPluginParametricCurves*) Data; cmsPluginParametricCurves* Plugin = (cmsPluginParametricCurves*) Data;
_cmsParametricCurvesCollection* fl; _cmsParametricCurvesCollection* fl;
...@@ -110,7 +110,7 @@ cmsBool _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Data) ...@@ -110,7 +110,7 @@ cmsBool _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Data)
return TRUE; return TRUE;
} }
fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(sizeof(_cmsParametricCurvesCollection)); fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(id, sizeof(_cmsParametricCurvesCollection));
if (fl == NULL) return FALSE; if (fl == NULL) return FALSE;
// Copy the parameters // Copy the parameters
...@@ -258,6 +258,7 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntr ...@@ -258,6 +258,7 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntr
} }
p ->InterpParams = _cmsComputeInterpParams(ContextID, p ->nEntries, 1, 1, p->Table16, CMS_LERP_FLAGS_16BITS); p ->InterpParams = _cmsComputeInterpParams(ContextID, p ->nEntries, 1, 1, p->Table16, CMS_LERP_FLAGS_16BITS);
if (p->InterpParams != NULL)
return p; return p;
Error: Error:
...@@ -423,7 +424,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu ...@@ -423,7 +424,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
if (e > 0) if (e > 0)
Val = pow(e, Params[0]) + Params[5]; Val = pow(e, Params[0]) + Params[5];
else else
Val = 0; Val = Params[5];
} }
else else
Val = R*Params[3] + Params[6]; Val = R*Params[3] + Params[6];
...@@ -458,7 +459,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu ...@@ -458,7 +459,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
e = Params[1]*R + Params[2]; e = Params[1]*R + Params[2];
if (e < 0) if (e < 0)
Val = 0; Val = Params[3];
else else
Val = pow(e, Params[0]) + Params[3]; Val = pow(e, Params[0]) + Params[3];
break; break;
...@@ -478,7 +479,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu ...@@ -478,7 +479,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
e = Params[2] * pow(R, Params[0]) + Params[3]; e = Params[2] * pow(R, Params[0]) + Params[3];
if (e <= 0) if (e <= 0)
Val = 0; Val = Params[4];
else else
Val = Params[1]*log10(e) + Params[4]; Val = Params[1]*log10(e) + Params[4];
break; break;
...@@ -544,7 +545,7 @@ cmsFloat64Number EvalSegmentedFn(const cmsToneCurve *g, cmsFloat64Number R) ...@@ -544,7 +545,7 @@ cmsFloat64Number EvalSegmentedFn(const cmsToneCurve *g, cmsFloat64Number R)
// Type == 0 means segment is sampled // Type == 0 means segment is sampled
if (g ->Segments[i].Type == 0) { if (g ->Segments[i].Type == 0) {
cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0); cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0) / (g ->Segments[i].x1 - g ->Segments[i].x0);
cmsFloat32Number Out; cmsFloat32Number Out;
// Setup the table (TODO: clean that) // Setup the table (TODO: clean that)
...@@ -629,20 +630,21 @@ cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID, ...@@ -629,20 +630,21 @@ cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID,
// Use a segmented curve to store the floating point table // Use a segmented curve to store the floating point table
cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cmsUInt32Number nEntries, const cmsFloat32Number values[]) cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cmsUInt32Number nEntries, const cmsFloat32Number values[])
{ {
cmsCurveSegment Seg[2]; cmsCurveSegment Seg[3];
// Initialize segmented curve part up to 0 // A segmented tone curve should have function segments in the first and last positions
Seg[0].x0 = -1; // Initialize segmented curve part up to 0 to constant value = samples[0]
Seg[0].x0 = MINUS_INF;
Seg[0].x1 = 0; Seg[0].x1 = 0;
Seg[0].Type = 6; Seg[0].Type = 6;
Seg[0].Params[0] = 1; Seg[0].Params[0] = 1;
Seg[0].Params[1] = 0; Seg[0].Params[1] = 0;
Seg[0].Params[2] = 0; Seg[0].Params[2] = 0;
Seg[0].Params[3] = 0; Seg[0].Params[3] = values[0];
Seg[0].Params[4] = 0; Seg[0].Params[4] = 0;
// From zero to any // From zero to 1
Seg[1].x0 = 0; Seg[1].x0 = 0;
Seg[1].x1 = 1.0; Seg[1].x1 = 1.0;
Seg[1].Type = 0; Seg[1].Type = 0;
...@@ -650,7 +652,19 @@ cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cm ...@@ -650,7 +652,19 @@ cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cm
Seg[1].nGridPoints = nEntries; Seg[1].nGridPoints = nEntries;
Seg[1].SampledPoints = (cmsFloat32Number*) values; Seg[1].SampledPoints = (cmsFloat32Number*) values;
return cmsBuildSegmentedToneCurve(ContextID, 2, Seg); // Final segment is constant = lastsample
Seg[2].x0 = 1.0;
Seg[2].x1 = PLUS_INF;
Seg[2].Type = 6;
Seg[2].Params[0] = 1;
Seg[2].Params[1] = 0;
Seg[2].Params[2] = 0;
Seg[2].Params[3] = values[nEntries-1];
Seg[2].Params[4] = 0;
return cmsBuildSegmentedToneCurve(ContextID, 3, Seg);
} }
// Parametric curves // Parametric curves
...@@ -993,7 +1007,7 @@ cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda ...@@ -993,7 +1007,7 @@ cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
if (Tab == NULL) return FALSE; if (Tab == NULL) return FALSE;
if (cmsIsToneCurveLinear(Tab)) return FALSE; // Nothing to do if (cmsIsToneCurveLinear(Tab)) return TRUE; // Nothing to do
nItems = Tab -> nEntries; nItems = Tab -> nEntries;
...@@ -1020,11 +1034,20 @@ cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda ...@@ -1020,11 +1034,20 @@ cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
if (z[i] == 0.) Zeros++; if (z[i] == 0.) Zeros++;
if (z[i] >= 65535.) Poles++; if (z[i] >= 65535.) Poles++;
if (z[i] < z[i-1]) return FALSE; // Non-Monotonic if (z[i] < z[i-1]) {
cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Non-Monotonic.");
return FALSE;
}
} }
if (Zeros > (nItems / 3)) return FALSE; // Degenerated, mostly zeros if (Zeros > (nItems / 3)) {
if (Poles > (nItems / 3)) return FALSE; // Degenerated, mostly poles cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly zeros.");
return FALSE;
}
if (Poles > (nItems / 3)) {
cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly poles.");
return FALSE;
}
// Seems ok // Seems ok
for (i=0; i < nItems; i++) { for (i=0; i < nItems; i++) {
......
...@@ -249,12 +249,9 @@ int GamutSampler(register const cmsUInt16Number In[], register cmsUInt16Number O ...@@ -249,12 +249,9 @@ int GamutSampler(register const cmsUInt16Number In[], register cmsUInt16Number O
cmsFloat64Number dE1, dE2, ErrorRatio; cmsFloat64Number dE1, dE2, ErrorRatio;
// Assume in-gamut by default. // Assume in-gamut by default.
dE1 = 0.;
dE2 = 0;
ErrorRatio = 1.0; ErrorRatio = 1.0;
// Convert input to Lab // Convert input to Lab
if (t -> hInput != NULL)
cmsDoTransform(t -> hInput, In, &LabIn1, 1); cmsDoTransform(t -> hInput, In, &LabIn1, 1);
// converts from PCS to colorant. This always // converts from PCS to colorant. This always
...@@ -374,7 +371,7 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID, ...@@ -374,7 +371,7 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
ProfileList[nGamutPCSposition] = hLab; ProfileList[nGamutPCSposition] = hLab;
BPCList[nGamutPCSposition] = 0; BPCList[nGamutPCSposition] = 0;
AdaptationList[nGamutPCSposition] = 1.0; AdaptationList[nGamutPCSposition] = 1.0;
Intents[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC; IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;
ColorSpace = cmsGetColorSpace(hGamut); ColorSpace = cmsGetColorSpace(hGamut);
...@@ -388,7 +385,7 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID, ...@@ -388,7 +385,7 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
nGamutPCSposition + 1, nGamutPCSposition + 1,
ProfileList, ProfileList,
BPCList, BPCList,
Intents, IntentList,
AdaptationList, AdaptationList,
NULL, 0, NULL, 0,
dwFormat, TYPE_Lab_DBL, dwFormat, TYPE_Lab_DBL,
...@@ -411,21 +408,24 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID, ...@@ -411,21 +408,24 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
// All ok? // All ok?
if (Chain.hForward && Chain.hReverse) { if (Chain.hInput && Chain.hForward && Chain.hReverse) {
// Go on, try to compute gamut LUT from PCS. This consist on a single channel containing // Go on, try to compute gamut LUT from PCS. This consist on a single channel containing
// dE when doing a transform back and forth on the colorimetric intent. // dE when doing a transform back and forth on the colorimetric intent.
Gamut = cmsPipelineAlloc(ContextID, 3, 1); Gamut = cmsPipelineAlloc(ContextID, 3, 1);
if (Gamut != NULL) { if (Gamut != NULL) {
CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL); CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL);
cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT); if (!cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT)) {
cmsPipelineFree(Gamut);
Gamut = NULL;
}
else {
cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0); cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0);
} }
} }
}
else else
Gamut = NULL; // Didn't work... Gamut = NULL; // Didn't work...
......
...@@ -83,7 +83,6 @@ cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Data) ...@@ -83,7 +83,6 @@ cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Data)
// Set the interpolation method // Set the interpolation method
cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p) cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
{ {
// Invoke factory, possibly in the Plug-in // Invoke factory, possibly in the Plug-in
...@@ -831,7 +830,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[], ...@@ -831,7 +830,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[],
register cmsUInt16Number Output[], register cmsUInt16Number Output[],
register const cmsInterpParams* p16) register const cmsInterpParams* p16)
{ {
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table; const cmsUInt16Number* LutTable;
cmsS15Fixed16Number fk; cmsS15Fixed16Number fk;
cmsS15Fixed16Number k0, rk; cmsS15Fixed16Number k0, rk;
int K0, K1; int K0, K1;
......
...@@ -154,7 +154,6 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID) ...@@ -154,7 +154,6 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID)
return iohandler; return iohandler;
Error: Error:
if (fm) _cmsFree(ContextID, fm);
if (iohandler) _cmsFree(ContextID, iohandler); if (iohandler) _cmsFree(ContextID, iohandler);
return NULL; return NULL;
...@@ -229,6 +228,11 @@ cmsBool MemoryWrite(struct _cms_io_handler* iohandler, cmsUInt32Number size, co ...@@ -229,6 +228,11 @@ cmsBool MemoryWrite(struct _cms_io_handler* iohandler, cmsUInt32Number size, co
if (ResData == NULL) return FALSE; // Housekeeping if (ResData == NULL) return FALSE; // Housekeeping
// Check for available space. Clip.
if (iohandler ->UsedSpace + size > ResData->Size) {
size = ResData ->Size - iohandler ->UsedSpace;
}
if (size == 0) return TRUE; // Write zero bytes is ok, but does nothing if (size == 0) return TRUE; // Write zero bytes is ok, but does nothing
memmove(ResData ->Block + ResData ->Pointer, Ptr, size); memmove(ResData ->Block + ResData ->Pointer, Ptr, size);
...@@ -350,7 +354,7 @@ cmsUInt32Number FileRead(cmsIOHANDLER* iohandler, void *Buffer, cmsUInt32Number ...@@ -350,7 +354,7 @@ cmsUInt32Number FileRead(cmsIOHANDLER* iohandler, void *Buffer, cmsUInt32Number
return nReaded; return nReaded;
} }
// Position file pointer in the file // Postion file pointer in the file
static static
cmsBool FileSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset) cmsBool FileSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset)
{ {
...@@ -389,13 +393,15 @@ cmsBool FileClose(cmsIOHANDLER* iohandler) ...@@ -389,13 +393,15 @@ cmsBool FileClose(cmsIOHANDLER* iohandler)
return TRUE; return TRUE;
} }
// Create a iohandler for disk based files. if FileName is NULL, then 'stream' member is also set // Create a iohandler for disk based files.
// to NULL and no real writting is performed. This only happens in writting access mode
cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const char* FileName, const char* AccessMode) cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const char* FileName, const char* AccessMode)
{ {
cmsIOHANDLER* iohandler = NULL; cmsIOHANDLER* iohandler = NULL;
FILE* fm = NULL; FILE* fm = NULL;
_cmsAssert(FileName != NULL);
_cmsAssert(AccessMode != NULL);
iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER)); iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER));
if (iohandler == NULL) return NULL; if (iohandler == NULL) return NULL;
...@@ -432,11 +438,8 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const cha ...@@ -432,11 +438,8 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const cha
iohandler ->UsedSpace = 0; iohandler ->UsedSpace = 0;
// Keep track of the original file // Keep track of the original file
if (FileName != NULL) {
strncpy(iohandler -> PhysicalFile, FileName, sizeof(iohandler -> PhysicalFile)-1); strncpy(iohandler -> PhysicalFile, FileName, sizeof(iohandler -> PhysicalFile)-1);
iohandler -> PhysicalFile[sizeof(iohandler -> PhysicalFile)-1] = 0; iohandler -> PhysicalFile[sizeof(iohandler -> PhysicalFile)-1] = 0;
}
iohandler ->Read = FileRead; iohandler ->Read = FileRead;
iohandler ->Seek = FileSeek; iohandler ->Seek = FileSeek;
...@@ -643,10 +646,13 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc) ...@@ -643,10 +646,13 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
Icc -> DeviceClass = (cmsProfileClassSignature) _cmsAdjustEndianess32(Header.deviceClass); Icc -> DeviceClass = (cmsProfileClassSignature) _cmsAdjustEndianess32(Header.deviceClass);
Icc -> ColorSpace = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.colorSpace); Icc -> ColorSpace = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.colorSpace);
Icc -> PCS = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.pcs); Icc -> PCS = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.pcs);
Icc -> RenderingIntent = _cmsAdjustEndianess32(Header.renderingIntent); Icc -> RenderingIntent = _cmsAdjustEndianess32(Header.renderingIntent);
Icc -> flags = _cmsAdjustEndianess32(Header.flags); Icc -> flags = _cmsAdjustEndianess32(Header.flags);
Icc -> manufacturer = _cmsAdjustEndianess32(Header.manufacturer); Icc -> manufacturer = _cmsAdjustEndianess32(Header.manufacturer);
Icc -> model = _cmsAdjustEndianess32(Header.model); Icc -> model = _cmsAdjustEndianess32(Header.model);
Icc -> creator = _cmsAdjustEndianess32(Header.creator);
_cmsAdjustEndianess64(&Icc -> attributes, &Header.attributes); _cmsAdjustEndianess64(&Icc -> attributes, &Header.attributes);
Icc -> Version = _cmsAdjustEndianess32(Header.version); Icc -> Version = _cmsAdjustEndianess32(Header.version);
...@@ -815,28 +821,33 @@ void CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags) ...@@ -815,28 +821,33 @@ void CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags)
cmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile) cmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile)
{ {
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
return (cmsUInt32Number) Icc ->manufacturer; return Icc ->manufacturer;
} }
void CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer) void CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer)
{ {
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
Icc -> manufacturer = (cmsUInt32Number) manufacturer; Icc -> manufacturer = manufacturer;
}
cmsUInt32Number CMSEXPORT cmsGetHeaderCreator(cmsHPROFILE hProfile)
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
return Icc ->creator;
} }
cmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile) cmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile)
{ {
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
return (cmsUInt32Number) Icc ->model; return Icc ->model;
} }
void CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model) void CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model)
{ {
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
Icc -> model = (cmsUInt32Number) model; Icc -> model = model;
} }
void CMSEXPORT cmsGetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number* Flags) void CMSEXPORT cmsGetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number* Flags)
{ {
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
...@@ -1073,7 +1084,6 @@ cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void* MemPtr, cmsUInt32Number ...@@ -1073,7 +1084,6 @@ cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void* MemPtr, cmsUInt32Number
return cmsOpenProfileFromMemTHR(NULL, MemPtr, dwSize); return cmsOpenProfileFromMemTHR(NULL, MemPtr, dwSize);
} }
static static
cmsBool SanityCheck(_cmsICCPROFILE* profile) cmsBool SanityCheck(_cmsICCPROFILE* profile)
{ {
...@@ -1112,11 +1122,13 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig) ...@@ -1112,11 +1122,13 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig)
cmsIOHANDLER* io = Icc ->IOhandler; cmsIOHANDLER* io = Icc ->IOhandler;
cmsTagDescriptor* TagDescriptor; cmsTagDescriptor* TagDescriptor;
cmsTagTypeSignature TypeBase; cmsTagTypeSignature TypeBase;
cmsTagTypeSignature Type;
cmsTagTypeHandler* TypeHandler; cmsTagTypeHandler* TypeHandler;
cmsFloat64Number Version = cmsGetProfileVersion((cmsHPROFILE) Icc);
cmsTagTypeHandler LocalTypeHandler;
for (i=0; i < Icc -> TagCount; i++) { for (i=0; i < Icc -> TagCount; i++) {
if (Icc ->TagNames[i] == 0) continue; if (Icc ->TagNames[i] == 0) continue;
// Linked tags are not written // Linked tags are not written
...@@ -1168,7 +1180,16 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig) ...@@ -1168,7 +1180,16 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig)
TagDescriptor = _cmsGetTagDescriptor(Icc -> TagNames[i]); TagDescriptor = _cmsGetTagDescriptor(Icc -> TagNames[i]);
if (TagDescriptor == NULL) continue; // Unsupported, ignore it if (TagDescriptor == NULL) continue; // Unsupported, ignore it
TypeHandler = Icc ->TagTypeHandlers[i]; if (TagDescriptor ->DecideType != NULL) {
Type = TagDescriptor ->DecideType(Version, Data);
}
else {
Type = TagDescriptor ->SupportedTypes[0];
}
TypeHandler = _cmsGetTagTypeHandler(Type);
if (TypeHandler == NULL) { if (TypeHandler == NULL) {
cmsSignalError(Icc ->ContextID, cmsERROR_INTERNAL, "(Internal) no handler for tag %x", Icc -> TagNames[i]); cmsSignalError(Icc ->ContextID, cmsERROR_INTERNAL, "(Internal) no handler for tag %x", Icc -> TagNames[i]);
...@@ -1179,9 +1200,10 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig) ...@@ -1179,9 +1200,10 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig)
if (!_cmsWriteTypeBase(io, TypeBase)) if (!_cmsWriteTypeBase(io, TypeBase))
return FALSE; return FALSE;
TypeHandler ->ContextID = Icc ->ContextID; LocalTypeHandler = *TypeHandler;
TypeHandler ->ICCVersion = Icc ->Version; LocalTypeHandler.ContextID = Icc ->ContextID;
if (!TypeHandler ->WritePtr(TypeHandler, io, Data, TagDescriptor ->ElemCount)) { LocalTypeHandler.ICCVersion = Icc ->Version;
if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, io, Data, TagDescriptor ->ElemCount)) {
char String[5]; char String[5];
...@@ -1357,10 +1379,11 @@ cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile) ...@@ -1357,10 +1379,11 @@ cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i]; cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i];
if (TypeHandler != NULL) { if (TypeHandler != NULL) {
cmsTagTypeHandler LocalTypeHandler = *TypeHandler;
TypeHandler ->ContextID = Icc ->ContextID; // As an additional parameters LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameters
TypeHandler ->ICCVersion = Icc ->Version; LocalTypeHandler.ICCVersion = Icc ->Version;
TypeHandler ->FreePtr(TypeHandler, Icc -> TagPtrs[i]); LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]);
} }
else else
_cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]); _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]);
...@@ -1404,6 +1427,7 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) ...@@ -1404,6 +1427,7 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
cmsIOHANDLER* io = Icc ->IOhandler; cmsIOHANDLER* io = Icc ->IOhandler;
cmsTagTypeHandler* TypeHandler; cmsTagTypeHandler* TypeHandler;
cmsTagTypeHandler LocalTypeHandler;
cmsTagDescriptor* TagDescriptor; cmsTagDescriptor* TagDescriptor;
cmsTagTypeSignature BaseType; cmsTagTypeSignature BaseType;
cmsUInt32Number Offset, TagSize; cmsUInt32Number Offset, TagSize;
...@@ -1444,14 +1468,15 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) ...@@ -1444,14 +1468,15 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
// Get type handler // Get type handler
TypeHandler = _cmsGetTagTypeHandler(BaseType); TypeHandler = _cmsGetTagTypeHandler(BaseType);
if (TypeHandler == NULL) return NULL; if (TypeHandler == NULL) return NULL;
LocalTypeHandler = *TypeHandler;
// Read the tag // Read the tag
Icc -> TagTypeHandlers[n] = TypeHandler; Icc -> TagTypeHandlers[n] = TypeHandler;
TypeHandler ->ContextID = Icc ->ContextID; LocalTypeHandler.ContextID = Icc ->ContextID;
TypeHandler ->ICCVersion = Icc ->Version; LocalTypeHandler.ICCVersion = Icc ->Version;
Icc -> TagPtrs[n] = TypeHandler ->ReadPtr(TypeHandler, io, &ElemCount, TagSize); Icc -> TagPtrs[n] = LocalTypeHandler.ReadPtr(&LocalTypeHandler, io, &ElemCount, TagSize);
// The tag type is supported, but something wrong happend and we cannot read the tag. // The tag type is supported, but something wrong happend and we cannot read the tag.
// let know the user about this (although it is just a warning) // let know the user about this (although it is just a warning)
...@@ -1504,6 +1529,7 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v ...@@ -1504,6 +1529,7 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v
{ {
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
cmsTagTypeHandler* TypeHandler = NULL; cmsTagTypeHandler* TypeHandler = NULL;
cmsTagTypeHandler LocalTypeHandler;
cmsTagDescriptor* TagDescriptor = NULL; cmsTagDescriptor* TagDescriptor = NULL;
cmsTagTypeSignature Type; cmsTagTypeSignature Type;
int i; int i;
...@@ -1534,9 +1560,10 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v ...@@ -1534,9 +1560,10 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v
if (TypeHandler != NULL) { if (TypeHandler != NULL) {
TypeHandler ->ContextID = Icc ->ContextID; // As an additional parameter LocalTypeHandler = *TypeHandler;
TypeHandler ->ICCVersion = Icc ->Version; LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter
TypeHandler->FreePtr(TypeHandler, Icc -> TagPtrs[i]); LocalTypeHandler.ICCVersion = Icc ->Version;
LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]);
} }
} }
} }
...@@ -1575,7 +1602,7 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v ...@@ -1575,7 +1602,7 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v
// Let the tag descriptor to decide the type base on depending on // Let the tag descriptor to decide the type base on depending on
// the data. This is useful for example on parametric curves, where // the data. This is useful for example on parametric curves, where
// curves specified by a table cannot be saved as parametric and needs // curves specified by a table cannot be saved as parametric and needs
// to be revented to single v2-curves, even on v4 profiles. // to be casted to single v2-curves, even on v4 profiles.
Type = TagDescriptor ->DecideType(Version, data); Type = TagDescriptor ->DecideType(Version, data);
} }
...@@ -1613,9 +1640,10 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v ...@@ -1613,9 +1640,10 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v
Icc ->TagSizes[i] = 0; Icc ->TagSizes[i] = 0;
Icc ->TagOffsets[i] = 0; Icc ->TagOffsets[i] = 0;
TypeHandler ->ContextID = Icc ->ContextID; LocalTypeHandler = *TypeHandler;
TypeHandler ->ICCVersion = Icc ->Version; LocalTypeHandler.ContextID = Icc ->ContextID;
Icc ->TagPtrs[i] = TypeHandler ->DupPtr(TypeHandler, data, TagDescriptor ->ElemCount); LocalTypeHandler.ICCVersion = Icc ->Version;
Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount);
if (Icc ->TagPtrs[i] == NULL) { if (Icc ->TagPtrs[i] == NULL) {
...@@ -1642,6 +1670,7 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig ...@@ -1642,6 +1670,7 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig
int i; int i;
cmsIOHANDLER* MemIO; cmsIOHANDLER* MemIO;
cmsTagTypeHandler* TypeHandler = NULL; cmsTagTypeHandler* TypeHandler = NULL;
cmsTagTypeHandler LocalTypeHandler;
cmsTagDescriptor* TagDescriptor = NULL; cmsTagDescriptor* TagDescriptor = NULL;
cmsUInt32Number rc; cmsUInt32Number rc;
cmsUInt32Number Offset, TagSize; cmsUInt32Number Offset, TagSize;
...@@ -1657,7 +1686,6 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig ...@@ -1657,7 +1686,6 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig
Offset = Icc ->TagOffsets[i]; Offset = Icc ->TagOffsets[i];
TagSize = Icc ->TagSizes[i]; TagSize = Icc ->TagSizes[i];
// read the data directly, don't keep copy // read the data directly, don't keep copy
if (data != NULL) { if (data != NULL) {
...@@ -1666,6 +1694,8 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig ...@@ -1666,6 +1694,8 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig
if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) return 0; if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) return 0;
if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) return 0; if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) return 0;
return TagSize;
} }
return Icc ->TagSizes[i]; return Icc ->TagSizes[i];
...@@ -1682,6 +1712,8 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig ...@@ -1682,6 +1712,8 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig
TagSize = BufferSize; TagSize = BufferSize;
memmove(data, Icc ->TagPtrs[i], TagSize); memmove(data, Icc ->TagPtrs[i], TagSize);
return TagSize;
} }
return Icc ->TagSizes[i]; return Icc ->TagSizes[i];
...@@ -1709,16 +1741,18 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig ...@@ -1709,16 +1741,18 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig
return 0; return 0;
} }
// FIXME: No handling for TypeHandler == NULL here?
// Serialize // Serialize
TypeHandler ->ContextID = Icc ->ContextID; LocalTypeHandler = *TypeHandler;
TypeHandler ->ICCVersion = Icc ->Version; LocalTypeHandler.ContextID = Icc ->ContextID;
LocalTypeHandler.ICCVersion = Icc ->Version;
if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) { if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) {
cmsCloseIOhandler(MemIO); cmsCloseIOhandler(MemIO);
return 0; return 0;
} }
if (!TypeHandler ->WritePtr(TypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) { if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) {
cmsCloseIOhandler(MemIO); cmsCloseIOhandler(MemIO);
return 0; return 0;
} }
......
...@@ -129,7 +129,6 @@ cmsBool _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile) ...@@ -129,7 +129,6 @@ cmsBool _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile)
Tag = (cmsMAT3*) cmsReadTag(hProfile, cmsSigChromaticAdaptationTag); Tag = (cmsMAT3*) cmsReadTag(hProfile, cmsSigChromaticAdaptationTag);
if (Tag != NULL) { if (Tag != NULL) {
*Dest = *Tag; *Dest = *Tag;
return TRUE; return TRUE;
} }
...@@ -193,7 +192,8 @@ cmsPipeline* BuildGrayInputMatrixPipeline(cmsHPROFILE hProfile) ...@@ -193,7 +192,8 @@ cmsPipeline* BuildGrayInputMatrixPipeline(cmsHPROFILE hProfile)
if (GrayTRC == NULL) return NULL; if (GrayTRC == NULL) return NULL;
Lut = cmsPipelineAlloc(ContextID, 1, 3); Lut = cmsPipelineAlloc(ContextID, 1, 3);
if (Lut == NULL) return NULL; if (Lut == NULL)
goto Error;
if (cmsGetPCS(hProfile) == cmsSigLabData) { if (cmsGetPCS(hProfile) == cmsSigLabData) {
...@@ -204,28 +204,35 @@ cmsPipeline* BuildGrayInputMatrixPipeline(cmsHPROFILE hProfile) ...@@ -204,28 +204,35 @@ cmsPipeline* BuildGrayInputMatrixPipeline(cmsHPROFILE hProfile)
EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero); EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
if (EmptyTab == NULL) { if (EmptyTab == NULL)
goto Error;
cmsPipelineFree(Lut);
return NULL;
}
LabCurves[0] = GrayTRC; LabCurves[0] = GrayTRC;
LabCurves[1] = EmptyTab; LabCurves[1] = EmptyTab;
LabCurves[2] = EmptyTab; LabCurves[2] = EmptyTab;
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, OneToThreeInputMatrix, NULL)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, OneToThreeInputMatrix, NULL)) ||
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, LabCurves)); !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, LabCurves))) {
cmsFreeToneCurve(EmptyTab);
goto Error;
}
cmsFreeToneCurve(EmptyTab); cmsFreeToneCurve(EmptyTab);
} }
else { else {
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &GrayTRC));
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, GrayInputMatrix, NULL)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &GrayTRC)) ||
!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, GrayInputMatrix, NULL)))
goto Error;
} }
return Lut; return Lut;
Error:
cmsFreeToneCurve(GrayTRC);
cmsPipelineFree(Lut);
return NULL;
} }
// RGB Matrix shaper // RGB Matrix shaper
...@@ -259,49 +266,31 @@ cmsPipeline* BuildRGBInputMatrixShaper(cmsHPROFILE hProfile) ...@@ -259,49 +266,31 @@ cmsPipeline* BuildRGBInputMatrixShaper(cmsHPROFILE hProfile)
Lut = cmsPipelineAlloc(ContextID, 3, 3); Lut = cmsPipelineAlloc(ContextID, 3, 3);
if (Lut != NULL) { if (Lut != NULL) {
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, Shapes)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, Shapes)) ||
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Mat, NULL)); !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Mat, NULL)))
goto Error;
// Note that it is certainly possible a single profile would have a LUT based // Note that it is certainly possible a single profile would have a LUT based
// tag for output working in lab and a matrix-shaper for the fallback cases. // tag for output working in lab and a matrix-shaper for the fallback cases.
// This is not allowed by the spec, but this code is tolerant to those cases // This is not allowed by the spec, but this code is tolerant to those cases
if (cmsGetPCS(hProfile) == cmsSigLabData) { if (cmsGetPCS(hProfile) == cmsSigLabData) {
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocXYZ2Lab(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocXYZ2Lab(ContextID)))
goto Error;
} }
} }
return Lut; return Lut;
Error:
cmsPipelineFree(Lut);
return NULL;
} }
// Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded // Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded
/*static
cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{
cmsContext ContextID = cmsGetProfileContextID(hProfile);
cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
cmsColorSpaceSignature spc = cmsGetColorSpace(hProfile);
if (Lut == NULL) return NULL;
// If PCS is Lab or XYZ, the floating point tag is accepting data in the space encoding,
// and since the formatter has already accomodated to 0..1.0, we should undo this change
if ( spc == cmsSigLabData)
{
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID));
}
else
if (spc == cmsSigXYZData)
{
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID));
}
return Lut;
}
*/
static static
cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat) cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{ {
...@@ -316,23 +305,31 @@ cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloa ...@@ -316,23 +305,31 @@ cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloa
// these need to be normalized into the appropriate ranges (Lab = 100,0,0, XYZ=1.0,1.0,1.0) // these need to be normalized into the appropriate ranges (Lab = 100,0,0, XYZ=1.0,1.0,1.0)
if ( spc == cmsSigLabData) if ( spc == cmsSigLabData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
goto Error;
} }
else if (spc == cmsSigXYZData) else if (spc == cmsSigXYZData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
goto Error;
} }
if ( PCS == cmsSigLabData) if ( PCS == cmsSigLabData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
goto Error;
} }
else if( PCS == cmsSigXYZData) else if( PCS == cmsSigXYZData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
goto Error;
} }
return Lut; return Lut;
Error:
cmsPipelineFree(Lut);
return NULL;
} }
...@@ -359,8 +356,11 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) ...@@ -359,8 +356,11 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
return NULL; return NULL;
} }
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, TRUE)); if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, TRUE)) ||
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)); !cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) {
cmsPipelineFree(Lut);
return NULL;
}
return Lut; return Lut;
} }
...@@ -395,12 +395,18 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) ...@@ -395,12 +395,18 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
return Lut; return Lut;
// If the input is Lab, add also a conversion at the begin // If the input is Lab, add also a conversion at the begin
if (cmsGetColorSpace(hProfile) == cmsSigLabData) if (cmsGetColorSpace(hProfile) == cmsSigLabData &&
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)); !cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
goto Error;
// Add a matrix for conversion V2 to V4 Lab PCS // Add a matrix for conversion V2 to V4 Lab PCS
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
goto Error;
return Lut; return Lut;
Error:
cmsPipelineFree(Lut);
return NULL;
} }
// Lut was not found, try to create a matrix-shaper // Lut was not found, try to create a matrix-shaper
...@@ -445,19 +451,25 @@ cmsPipeline* BuildGrayOutputPipeline(cmsHPROFILE hProfile) ...@@ -445,19 +451,25 @@ cmsPipeline* BuildGrayOutputPipeline(cmsHPROFILE hProfile)
if (cmsGetPCS(hProfile) == cmsSigLabData) { if (cmsGetPCS(hProfile) == cmsSigLabData) {
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickLstarMatrix, NULL)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickLstarMatrix, NULL)))
goto Error;
} }
else { else {
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickYMatrix, NULL)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickYMatrix, NULL)))
goto Error;
} }
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &RevGrayTRC)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &RevGrayTRC)))
cmsFreeToneCurve(RevGrayTRC); goto Error;
cmsFreeToneCurve(RevGrayTRC);
return Lut; return Lut;
}
Error:
cmsFreeToneCurve(RevGrayTRC);
cmsPipelineFree(Lut);
return NULL;
}
static static
...@@ -506,15 +518,21 @@ cmsPipeline* BuildRGBOutputMatrixShaper(cmsHPROFILE hProfile) ...@@ -506,15 +518,21 @@ cmsPipeline* BuildRGBOutputMatrixShaper(cmsHPROFILE hProfile)
// This is not allowed by the spec, but this code is tolerant to those cases // This is not allowed by the spec, but this code is tolerant to those cases
if (cmsGetPCS(hProfile) == cmsSigLabData) { if (cmsGetPCS(hProfile) == cmsSigLabData) {
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLab2XYZ(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLab2XYZ(ContextID)))
goto Error;
} }
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Inv, NULL)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Inv, NULL)) ||
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, InvShapes)); !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, InvShapes)))
goto Error;
} }
cmsFreeToneCurveTriple(InvShapes); cmsFreeToneCurveTriple(InvShapes);
return Lut; return Lut;
Error:
cmsFreeToneCurveTriple(InvShapes);
cmsPipelineFree(Lut);
return NULL;
} }
...@@ -540,30 +558,6 @@ void ChangeInterpolationToTrilinear(cmsPipeline* Lut) ...@@ -540,30 +558,6 @@ void ChangeInterpolationToTrilinear(cmsPipeline* Lut)
// Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded // Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded
/*static
cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{
cmsContext ContextID = cmsGetProfileContextID(hProfile);
cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
cmsColorSpaceSignature PCS = cmsGetPCS(hProfile);
if (Lut == NULL) return NULL;
// If PCS is Lab or XYZ, the floating point tag is accepting data in the space encoding,
// and since the formatter has already accomodated to 0..1.0, we should undo this change
if ( PCS == cmsSigLabData)
{
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID));
}
else
if (PCS == cmsSigXYZData)
{
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID));
}
return Lut;
}*/
static static
cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat) cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{ {
...@@ -578,25 +572,33 @@ cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFlo ...@@ -578,25 +572,33 @@ cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFlo
// and since the formatter has already accomodated to 0..1.0, we should undo this change // and since the formatter has already accomodated to 0..1.0, we should undo this change
if ( PCS == cmsSigLabData) if ( PCS == cmsSigLabData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
goto Error;
} }
else else
if (PCS == cmsSigXYZData) if (PCS == cmsSigXYZData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
goto Error;
} }
// the output can be Lab or XYZ, in which case normalisation is needed on the end of the pipeline // the output can be Lab or XYZ, in which case normalisation is needed on the end of the pipeline
if ( dataSpace == cmsSigLabData) if ( dataSpace == cmsSigLabData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
goto Error;
} }
else if ( dataSpace == cmsSigXYZData) else if (dataSpace == cmsSigXYZData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
goto Error;
} }
return Lut; return Lut;
Error:
cmsPipelineFree(Lut);
return NULL;
} }
// Create an output MPE LUT from agiven profile. Version mismatches are handled here // Create an output MPE LUT from agiven profile. Version mismatches are handled here
...@@ -643,13 +645,18 @@ cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent) ...@@ -643,13 +645,18 @@ cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent)
return Lut; return Lut;
// Add a matrix for conversion V4 to V2 Lab PCS // Add a matrix for conversion V4 to V2 Lab PCS
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
goto Error;
// If the output is Lab, add also a conversion at the end // If the output is Lab, add also a conversion at the end
if (cmsGetColorSpace(hProfile) == cmsSigLabData) if (cmsGetColorSpace(hProfile) == cmsSigLabData)
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
goto Error;
return Lut; return Lut;
Error:
cmsPipelineFree(Lut);
return NULL;
} }
// Lut not found, try to create a matrix-shaper // Lut not found, try to create a matrix-shaper
...@@ -681,25 +688,32 @@ cmsPipeline* _cmsReadFloatDevicelinkTag(cmsHPROFILE hProfile, cmsTagSignature ta ...@@ -681,25 +688,32 @@ cmsPipeline* _cmsReadFloatDevicelinkTag(cmsHPROFILE hProfile, cmsTagSignature ta
if (spc == cmsSigLabData) if (spc == cmsSigLabData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
goto Error;
} }
else else
if (spc == cmsSigXYZData) if (spc == cmsSigXYZData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
goto Error;
} }
if (PCS == cmsSigLabData) if (PCS == cmsSigLabData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
goto Error;
} }
else else
if (PCS == cmsSigXYZData) if (PCS == cmsSigXYZData)
{ {
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
goto Error;
} }
return Lut; return Lut;
Error:
cmsPipelineFree(Lut);
return NULL;
} }
// This one includes abstract profiles as well. Matrix-shaper cannot be obtained on that device class. The // This one includes abstract profiles as well. Matrix-shaper cannot be obtained on that device class. The
...@@ -721,15 +735,21 @@ cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent) ...@@ -721,15 +735,21 @@ cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent)
if (nc == NULL) return NULL; if (nc == NULL) return NULL;
Lut = cmsPipelineAlloc(ContextID, 0, 0); Lut = cmsPipelineAlloc(ContextID, 0, 0);
if (Lut == NULL) { if (Lut == NULL)
cmsFreeNamedColorList(nc); goto Error;
return NULL;
} if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, FALSE)))
goto Error;
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, FALSE));
if (cmsGetColorSpace(hProfile) == cmsSigLabData) if (cmsGetColorSpace(hProfile) == cmsSigLabData)
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)); if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
goto Error;
return Lut; return Lut;
Error:
cmsPipelineFree(Lut);
cmsFreeNamedColorList(nc);
return NULL;
} }
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
...@@ -774,16 +794,20 @@ cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent) ...@@ -774,16 +794,20 @@ cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent)
// Here it is possible to get Lab on both sides // Here it is possible to get Lab on both sides
if (cmsGetPCS(hProfile) == cmsSigLabData) { if (cmsGetPCS(hProfile) == cmsSigLabData) {
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)); if(!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
goto Error2;
} }
if (cmsGetColorSpace(hProfile) == cmsSigLabData) { if (cmsGetColorSpace(hProfile) == cmsSigLabData) {
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)); if(!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
goto Error2;
} }
return Lut; return Lut;
Error2:
cmsPipelineFree(Lut);
return NULL;
} }
// --------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------
......
...@@ -264,10 +264,10 @@ Error: ...@@ -264,10 +264,10 @@ Error:
if (NewElem ->TheCurves != NULL) { if (NewElem ->TheCurves != NULL) {
for (i=0; i < NewElem ->nCurves; i++) { for (i=0; i < NewElem ->nCurves; i++) {
if (NewElem ->TheCurves[i]) if (NewElem ->TheCurves[i])
cmsFreeToneCurve(Data ->TheCurves[i]); cmsFreeToneCurve(NewElem ->TheCurves[i]);
} }
} }
_cmsFree(mpe ->ContextID, Data ->TheCurves); _cmsFree(mpe ->ContextID, NewElem ->TheCurves);
_cmsFree(mpe ->ContextID, NewElem); _cmsFree(mpe ->ContextID, NewElem);
return NULL; return NULL;
} }
...@@ -392,6 +392,8 @@ static ...@@ -392,6 +392,8 @@ static
void MatrixElemTypeFree(cmsStage* mpe) void MatrixElemTypeFree(cmsStage* mpe)
{ {
_cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data; _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data;
if (Data == NULL)
return;
if (Data ->Double) if (Data ->Double)
_cmsFree(mpe ->ContextID, Data ->Double); _cmsFree(mpe ->ContextID, Data ->Double);
...@@ -526,10 +528,15 @@ void* CLUTElemDup(cmsStage* mpe) ...@@ -526,10 +528,15 @@ void* CLUTElemDup(cmsStage* mpe)
if (Data ->Tab.T) { if (Data ->Tab.T) {
if (Data ->HasFloatValues) if (Data ->HasFloatValues) {
NewElem ->Tab.TFloat = (cmsFloat32Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.TFloat, Data ->nEntries * sizeof (cmsFloat32Number)); NewElem ->Tab.TFloat = (cmsFloat32Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.TFloat, Data ->nEntries * sizeof (cmsFloat32Number));
else if (NewElem ->Tab.TFloat == NULL)
goto Error;
} else {
NewElem ->Tab.T = (cmsUInt16Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.T, Data ->nEntries * sizeof (cmsUInt16Number)); NewElem ->Tab.T = (cmsUInt16Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.T, Data ->nEntries * sizeof (cmsUInt16Number));
if (NewElem ->Tab.TFloat == NULL)
goto Error;
}
} }
NewElem ->Params = _cmsComputeInterpParamsEx(mpe ->ContextID, NewElem ->Params = _cmsComputeInterpParamsEx(mpe ->ContextID,
...@@ -538,8 +545,14 @@ void* CLUTElemDup(cmsStage* mpe) ...@@ -538,8 +545,14 @@ void* CLUTElemDup(cmsStage* mpe)
Data ->Params ->nOutputs, Data ->Params ->nOutputs,
NewElem ->Tab.T, NewElem ->Tab.T,
Data ->Params ->dwFlags); Data ->Params ->dwFlags);
if (NewElem->Params != NULL)
return (void*) NewElem; return (void*) NewElem;
Error:
if (NewElem->Tab.T)
// This works for both types
_cmsFree(mpe ->ContextID, NewElem -> Tab.T);
_cmsFree(mpe ->ContextID, NewElem);
return NULL;
} }
...@@ -636,7 +649,6 @@ cmsStage* CMSEXPORT cmsStageAllocCLut16bit(cmsContext ContextID, ...@@ -636,7 +649,6 @@ cmsStage* CMSEXPORT cmsStageAllocCLut16bit(cmsContext ContextID,
for (i=0; i < MAX_INPUT_DIMENSIONS; i++) for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
Dimensions[i] = nGridPoints; Dimensions[i] = nGridPoints;
return cmsStageAllocCLut16bitGranular(ContextID, Dimensions, inputChan, outputChan, Table); return cmsStageAllocCLut16bitGranular(ContextID, Dimensions, inputChan, outputChan, Table);
} }
...@@ -706,15 +718,12 @@ cmsStage* CMSEXPORT cmsStageAllocCLutFloatGranular(cmsContext ContextID, const c ...@@ -706,15 +718,12 @@ cmsStage* CMSEXPORT cmsStageAllocCLutFloatGranular(cmsContext ContextID, const c
} }
} }
NewElem ->Params = _cmsComputeInterpParamsEx(ContextID, clutPoints, inputChan, outputChan, NewElem ->Tab.TFloat, CMS_LERP_FLAGS_FLOAT); NewElem ->Params = _cmsComputeInterpParamsEx(ContextID, clutPoints, inputChan, outputChan, NewElem ->Tab.TFloat, CMS_LERP_FLAGS_FLOAT);
if (NewElem ->Params == NULL) { if (NewElem ->Params == NULL) {
cmsStageFree(NewMPE); cmsStageFree(NewMPE);
return NULL; return NULL;
} }
return NewMPE; return NewMPE;
} }
...@@ -772,7 +781,7 @@ cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, v ...@@ -772,7 +781,7 @@ cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, v
int i, t, nTotalPoints, index, rest; int i, t, nTotalPoints, index, rest;
int nInputs, nOutputs; int nInputs, nOutputs;
cmsUInt32Number* nSamples; cmsUInt32Number* nSamples;
cmsUInt16Number In[cmsMAXCHANNELS], Out[MAX_STAGE_CHANNELS]; cmsUInt16Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS];
_cmsStageCLutData* clut; _cmsStageCLutData* clut;
if (mpe == NULL) return FALSE; if (mpe == NULL) return FALSE;
...@@ -785,7 +794,9 @@ cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, v ...@@ -785,7 +794,9 @@ cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, v
nInputs = clut->Params ->nInputs; nInputs = clut->Params ->nInputs;
nOutputs = clut->Params ->nOutputs; nOutputs = clut->Params ->nOutputs;
if (nInputs >= cmsMAXCHANNELS) return FALSE; if (nInputs <= 0) return FALSE;
if (nOutputs <= 0) return FALSE;
if (nInputs > MAX_INPUT_DIMENSIONS) return FALSE;
if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE; if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE;
nTotalPoints = CubeSize(nSamples, nInputs); nTotalPoints = CubeSize(nSamples, nInputs);
...@@ -832,14 +843,16 @@ cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler ...@@ -832,14 +843,16 @@ cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler
int i, t, nTotalPoints, index, rest; int i, t, nTotalPoints, index, rest;
int nInputs, nOutputs; int nInputs, nOutputs;
cmsUInt32Number* nSamples; cmsUInt32Number* nSamples;
cmsFloat32Number In[cmsMAXCHANNELS], Out[MAX_STAGE_CHANNELS]; cmsFloat32Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS];
_cmsStageCLutData* clut = (_cmsStageCLutData*) mpe->Data; _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe->Data;
nSamples = clut->Params ->nSamples; nSamples = clut->Params ->nSamples;
nInputs = clut->Params ->nInputs; nInputs = clut->Params ->nInputs;
nOutputs = clut->Params ->nOutputs; nOutputs = clut->Params ->nOutputs;
if (nInputs >= cmsMAXCHANNELS) return FALSE; if (nInputs <= 0) return FALSE;
if (nOutputs <= 0) return FALSE;
if (nInputs > MAX_INPUT_DIMENSIONS) return FALSE;
if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE; if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE;
nTotalPoints = CubeSize(nSamples, nInputs); nTotalPoints = CubeSize(nSamples, nInputs);
...@@ -1021,8 +1034,7 @@ cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID) ...@@ -1021,8 +1034,7 @@ cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID)
mpe = cmsStageAllocToneCurves(ContextID, 3, LabTable); mpe = cmsStageAllocToneCurves(ContextID, 3, LabTable);
cmsFreeToneCurveTriple(LabTable); cmsFreeToneCurveTriple(LabTable);
if (mpe == NULL) return mpe; if (mpe == NULL) return NULL;
mpe ->Implements = cmsSigLabV2toV4; mpe ->Implements = cmsSigLabV2toV4;
return mpe; return mpe;
} }
...@@ -1250,10 +1262,20 @@ cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe) ...@@ -1250,10 +1262,20 @@ cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe)
NewMPE ->Implements = mpe ->Implements; NewMPE ->Implements = mpe ->Implements;
if (mpe ->DupElemPtr) if (mpe ->DupElemPtr) {
NewMPE ->Data = mpe ->DupElemPtr(mpe); NewMPE ->Data = mpe ->DupElemPtr(mpe);
else
if (NewMPE->Data == NULL) {
cmsStageFree(NewMPE);
return NULL;
}
} else {
NewMPE ->Data = NULL; NewMPE ->Data = NULL;
}
return NewMPE; return NewMPE;
} }
...@@ -1266,7 +1288,7 @@ cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe) ...@@ -1266,7 +1288,7 @@ cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe)
static static
void BlessLUT(cmsPipeline* lut) void BlessLUT(cmsPipeline* lut)
{ {
// We can set the input/output channels only if we have elements. // We can set the input/ouput channels only if we have elements.
if (lut ->Elements != NULL) { if (lut ->Elements != NULL) {
cmsStage *First, *Last; cmsStage *First, *Last;
...@@ -1466,12 +1488,12 @@ cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut) ...@@ -1466,12 +1488,12 @@ cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut)
} }
void CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe) int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe)
{ {
cmsStage* Anterior = NULL, *pt; cmsStage* Anterior = NULL, *pt;
_cmsAssert(lut != NULL); if (lut == NULL || mpe == NULL)
_cmsAssert(mpe != NULL); return FALSE;
switch (loc) { switch (loc) {
...@@ -1495,9 +1517,11 @@ void CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStag ...@@ -1495,9 +1517,11 @@ void CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStag
} }
break; break;
default:; default:;
return FALSE;
} }
BlessLUT(lut); BlessLUT(lut);
return TRUE;
} }
// Unlink an element and return the pointer to it // Unlink an element and return the pointer to it
...@@ -1559,7 +1583,7 @@ void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStag ...@@ -1559,7 +1583,7 @@ void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStag
// Concatenate two LUT into a new single one // Concatenate two LUT into a new single one
cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2) cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2)
{ {
cmsStage* mpe, *NewMPE; cmsStage* mpe;
// If both LUTS does not have elements, we need to inherit // If both LUTS does not have elements, we need to inherit
// the number of channels // the number of channels
...@@ -1574,15 +1598,10 @@ cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2) ...@@ -1574,15 +1598,10 @@ cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2)
mpe = mpe ->Next) { mpe = mpe ->Next) {
// We have to dup each element // We have to dup each element
NewMPE = cmsStageDup(mpe); if (!cmsPipelineInsertStage(l1, cmsAT_END, cmsStageDup(mpe)))
if (NewMPE == NULL) {
return FALSE; return FALSE;
} }
cmsPipelineInsertStage(l1, cmsAT_END, NewMPE);
}
BlessLUT(l1); BlessLUT(l1);
return TRUE; return TRUE;
} }
...@@ -1714,16 +1733,11 @@ cmsBool CMSEXPORT cmsPipelineEvalReverseFloat(cmsFloat32Number Target[], ...@@ -1714,16 +1733,11 @@ cmsBool CMSEXPORT cmsPipelineEvalReverseFloat(cmsFloat32Number Target[],
cmsFloat32Number fx[4], x[4], xd[4], fxd[4]; cmsFloat32Number fx[4], x[4], xd[4], fxd[4];
cmsVEC3 tmp, tmp2; cmsVEC3 tmp, tmp2;
cmsMAT3 Jacobian; cmsMAT3 Jacobian;
cmsFloat64Number LastResult[4];
// Only 3->3 and 4->3 are supported // Only 3->3 and 4->3 are supported
if (lut ->InputChannels != 3 && lut ->InputChannels != 4) return FALSE; if (lut ->InputChannels != 3 && lut ->InputChannels != 4) return FALSE;
if (lut ->OutputChannels != 3) return FALSE; if (lut ->OutputChannels != 3) return FALSE;
// Mark result of -1
LastResult[0] = LastResult[1] = LastResult[2] = -1.0f;
// Take the hint as starting point if specified // Take the hint as starting point if specified
if (Hint == NULL) { if (Hint == NULL) {
......
...@@ -338,7 +338,7 @@ cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile) ...@@ -338,7 +338,7 @@ cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
Error: Error:
// Free resources as something went wrong // Free resources as something went wrong
if (MD5 != NULL) _cmsFree(ContextID, MD5); // "MD5" cannot be other than NULL here, so no need to free it
if (Mem != NULL) _cmsFree(ContextID, Mem); if (Mem != NULL) _cmsFree(ContextID, Mem);
memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
return FALSE; return FALSE;
......
...@@ -475,6 +475,35 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu, ...@@ -475,6 +475,35 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
} }
// Get the number of translations in the MLU object
cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu)
{
if (mlu == NULL) return 0;
return mlu->UsedEntries;
}
// Get the language and country codes for a specific MLU index
cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu,
cmsUInt32Number idx,
char LanguageCode[3],
char CountryCode[3])
{
_cmsMLUentry *entry;
if (mlu == NULL) return FALSE;
if (idx >= (cmsUInt32Number) mlu->UsedEntries) return FALSE;
entry = &mlu->Entries[idx];
*(cmsUInt16Number *)LanguageCode = _cmsAdjustEndianess16(entry->Language);
*(cmsUInt16Number *)CountryCode = _cmsAdjustEndianess16(entry->Country);
return TRUE;
}
// Named color lists -------------------------------------------------------------------------------------------- // Named color lists --------------------------------------------------------------------------------------------
// Grow the list to keep at least NumElements // Grow the list to keep at least NumElements
...@@ -517,9 +546,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn ...@@ -517,9 +546,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn
while (v -> Allocated < n) while (v -> Allocated < n)
GrowNamedColorList(v); GrowNamedColorList(v);
strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix) - 1); strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1);
strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix) - 1); strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix)-1);
v->Prefix[sizeof(v ->Prefix) - 1] = v->Suffix[sizeof(v ->Suffix) - 1] = 0; v->Prefix[32] = v->Suffix[32] = 0;
v -> ColorantCount = ColorantCount; v -> ColorantCount = ColorantCount;
...@@ -529,8 +558,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn ...@@ -529,8 +558,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn
// Free a list // Free a list
void CMSEXPORT cmsFreeNamedColorList(cmsNAMEDCOLORLIST* v) void CMSEXPORT cmsFreeNamedColorList(cmsNAMEDCOLORLIST* v)
{ {
if (v == NULL) return;
if (v ->List) _cmsFree(v ->ContextID, v ->List); if (v ->List) _cmsFree(v ->ContextID, v ->List);
if (v) _cmsFree(v ->ContextID, v); _cmsFree(v ->ContextID, v);
} }
cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v) cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v)
...@@ -576,11 +606,8 @@ cmsBool CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* NamedColorList, ...@@ -576,11 +606,8 @@ cmsBool CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* NamedColorList,
if (Name != NULL) { if (Name != NULL) {
strncpy(NamedColorList ->List[NamedColorList ->nColors].Name, Name, strncpy(NamedColorList ->List[NamedColorList ->nColors].Name, Name, cmsMAX_PATH-1);
sizeof(NamedColorList ->List[NamedColorList ->nColors].Name) - 1); NamedColorList ->List[NamedColorList ->nColors].Name[cmsMAX_PATH-1] = 0;
NamedColorList ->List[NamedColorList ->nColors].
Name[sizeof(NamedColorList ->List[NamedColorList ->nColors].Name) - 1] = 0;
} }
else else
...@@ -891,7 +918,6 @@ cmsHANDLE CMSEXPORT cmsDictDup(cmsHANDLE hDict) ...@@ -891,7 +918,6 @@ cmsHANDLE CMSEXPORT cmsDictDup(cmsHANDLE hDict)
{ {
_cmsDICT* old_dict = (_cmsDICT*) hDict; _cmsDICT* old_dict = (_cmsDICT*) hDict;
cmsHANDLE hNew; cmsHANDLE hNew;
_cmsDICT* new_dict;
cmsDICTentry *entry; cmsDICTentry *entry;
_cmsAssert(old_dict != NULL); _cmsAssert(old_dict != NULL);
...@@ -899,8 +925,6 @@ cmsHANDLE CMSEXPORT cmsDictDup(cmsHANDLE hDict) ...@@ -899,8 +925,6 @@ cmsHANDLE CMSEXPORT cmsDictDup(cmsHANDLE hDict)
hNew = cmsDictAlloc(old_dict ->ContextID); hNew = cmsDictAlloc(old_dict ->ContextID);
if (hNew == NULL) return NULL; if (hNew == NULL) return NULL;
new_dict = (_cmsDICT*) hNew;
// Walk the list freeing all nodes // Walk the list freeing all nodes
entry = old_dict ->head; entry = old_dict ->head;
while (entry != NULL) { while (entry != NULL) {
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
// However, the following notice accompanied the original version of this // However, the following notice accompanied the original version of this
// file: // file:
// //
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// //
// Little Color Management System // Little Color Management System
...@@ -81,10 +82,6 @@ typedef struct { ...@@ -81,10 +82,6 @@ typedef struct {
int nInputs; int nInputs;
int nOutputs; int nOutputs;
// Since there is no limitation of the output number of channels, this buffer holding the connexion CLUT-shaper
// has to be dynamically allocated. This is not the case of first step shaper-CLUT, which is limited to max inputs
cmsUInt16Number* StageDEF;
_cmsInterpFn16 EvalCurveIn16[MAX_INPUT_DIMENSIONS]; // The maximum number of input channels is known in advance _cmsInterpFn16 EvalCurveIn16[MAX_INPUT_DIMENSIONS]; // The maximum number of input channels is known in advance
cmsInterpParams* ParamsCurveIn16[MAX_INPUT_DIMENSIONS]; cmsInterpParams* ParamsCurveIn16[MAX_INPUT_DIMENSIONS];
...@@ -202,8 +199,6 @@ cmsBool PreOptimize(cmsPipeline* Lut) ...@@ -202,8 +199,6 @@ cmsBool PreOptimize(cmsPipeline* Lut)
{ {
cmsBool AnyOpt = FALSE, Opt; cmsBool AnyOpt = FALSE, Opt;
AnyOpt = FALSE;
do { do {
Opt = FALSE; Opt = FALSE;
...@@ -253,6 +248,7 @@ void PrelinEval16(register const cmsUInt16Number Input[], ...@@ -253,6 +248,7 @@ void PrelinEval16(register const cmsUInt16Number Input[],
{ {
Prelin16Data* p16 = (Prelin16Data*) D; Prelin16Data* p16 = (Prelin16Data*) D;
cmsUInt16Number StageABC[MAX_INPUT_DIMENSIONS]; cmsUInt16Number StageABC[MAX_INPUT_DIMENSIONS];
cmsUInt16Number StageDEF[cmsMAXCHANNELS];
int i; int i;
for (i=0; i < p16 ->nInputs; i++) { for (i=0; i < p16 ->nInputs; i++) {
...@@ -260,11 +256,11 @@ void PrelinEval16(register const cmsUInt16Number Input[], ...@@ -260,11 +256,11 @@ void PrelinEval16(register const cmsUInt16Number Input[],
p16 ->EvalCurveIn16[i](&Input[i], &StageABC[i], p16 ->ParamsCurveIn16[i]); p16 ->EvalCurveIn16[i](&Input[i], &StageABC[i], p16 ->ParamsCurveIn16[i]);
} }
p16 ->EvalCLUT(StageABC, p16 ->StageDEF, p16 ->CLUTparams); p16 ->EvalCLUT(StageABC, StageDEF, p16 ->CLUTparams);
for (i=0; i < p16 ->nOutputs; i++) { for (i=0; i < p16 ->nOutputs; i++) {
p16 ->EvalCurveOut16[i](&p16->StageDEF[i], &Output[i], p16 ->ParamsCurveOut16[i]); p16 ->EvalCurveOut16[i](&StageDEF[i], &Output[i], p16 ->ParamsCurveOut16[i]);
} }
} }
...@@ -274,7 +270,6 @@ void PrelinOpt16free(cmsContext ContextID, void* ptr) ...@@ -274,7 +270,6 @@ void PrelinOpt16free(cmsContext ContextID, void* ptr)
{ {
Prelin16Data* p16 = (Prelin16Data*) ptr; Prelin16Data* p16 = (Prelin16Data*) ptr;
_cmsFree(ContextID, p16 ->StageDEF);
_cmsFree(ContextID, p16 ->EvalCurveOut16); _cmsFree(ContextID, p16 ->EvalCurveOut16);
_cmsFree(ContextID, p16 ->ParamsCurveOut16); _cmsFree(ContextID, p16 ->ParamsCurveOut16);
...@@ -289,7 +284,6 @@ void* Prelin16dup(cmsContext ContextID, const void* ptr) ...@@ -289,7 +284,6 @@ void* Prelin16dup(cmsContext ContextID, const void* ptr)
if (Duped == NULL) return NULL; if (Duped == NULL) return NULL;
Duped ->StageDEF = _cmsCalloc(ContextID, p16 ->nOutputs, sizeof(cmsUInt16Number));
Duped ->EvalCurveOut16 = _cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16)); Duped ->EvalCurveOut16 = _cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16));
Duped ->ParamsCurveOut16 = _cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* )); Duped ->ParamsCurveOut16 = _cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* ));
...@@ -328,7 +322,6 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID, ...@@ -328,7 +322,6 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID,
p16 ->EvalCLUT = ColorMap ->Interpolation.Lerp16; p16 ->EvalCLUT = ColorMap ->Interpolation.Lerp16;
p16 -> StageDEF = _cmsCalloc(ContextID, p16 ->nOutputs, sizeof(cmsUInt16Number));
p16 -> EvalCurveOut16 = (_cmsInterpFn16*) _cmsCalloc(ContextID, nOutputs, sizeof(_cmsInterpFn16)); p16 -> EvalCurveOut16 = (_cmsInterpFn16*) _cmsCalloc(ContextID, nOutputs, sizeof(_cmsInterpFn16));
p16 -> ParamsCurveOut16 = (cmsInterpParams**) _cmsCalloc(ContextID, nOutputs, sizeof(cmsInterpParams* )); p16 -> ParamsCurveOut16 = (cmsInterpParams**) _cmsCalloc(ContextID, nOutputs, sizeof(cmsInterpParams* ));
...@@ -413,7 +406,7 @@ cmsBool PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[], ...@@ -413,7 +406,7 @@ cmsBool PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[],
int i, index; int i, index;
if (CLUT -> Type != cmsSigCLutElemType) { if (CLUT -> Type != cmsSigCLutElemType) {
cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) Attempt to PatchLUT on non-lut MPE"); cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) Attempt to PatchLUT on non-lut stage");
return FALSE; return FALSE;
} }
...@@ -579,8 +572,8 @@ cmsBool FixWhiteMisalignment(cmsPipeline* Lut, cmsColorSpaceSignature EntryColor ...@@ -579,8 +572,8 @@ cmsBool FixWhiteMisalignment(cmsPipeline* Lut, cmsColorSpaceSignature EntryColor
static static
cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{ {
cmsPipeline* Src; cmsPipeline* Src = NULL;
cmsPipeline* Dest; cmsPipeline* Dest = NULL;
cmsStage* mpe; cmsStage* mpe;
cmsStage* CLUT; cmsStage* CLUT;
cmsStage *KeepPreLin = NULL, *KeepPostLin = NULL; cmsStage *KeepPreLin = NULL, *KeepPostLin = NULL;
...@@ -593,7 +586,6 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 ...@@ -593,7 +586,6 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
cmsToneCurve** DataSetOut; cmsToneCurve** DataSetOut;
Prelin16Data* p16; Prelin16Data* p16;
// This is a loosy optimization! does not apply in floating-point cases // This is a loosy optimization! does not apply in floating-point cases
if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE; if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE;
...@@ -632,7 +624,8 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 ...@@ -632,7 +624,8 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
// All seems ok, proceed. // All seems ok, proceed.
NewPreLin = cmsStageDup(PreLin); NewPreLin = cmsStageDup(PreLin);
cmsPipelineInsertStage(Dest, cmsAT_BEGIN, NewPreLin); if(!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, NewPreLin))
goto Error;
// Remove prelinearization. Since we have duplicated the curve // Remove prelinearization. Since we have duplicated the curve
// in destination LUT, the sampling shoud be applied after this stage. // in destination LUT, the sampling shoud be applied after this stage.
...@@ -646,7 +639,9 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 ...@@ -646,7 +639,9 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
if (CLUT == NULL) return FALSE; if (CLUT == NULL) return FALSE;
// Add the CLUT to the destination LUT // Add the CLUT to the destination LUT
cmsPipelineInsertStage(Dest, cmsAT_END, CLUT); if (!cmsPipelineInsertStage(Dest, cmsAT_END, CLUT)) {
goto Error;
}
// Postlinearization tables are kept unless indicated by flags // Postlinearization tables are kept unless indicated by flags
if (*dwFlags & cmsFLAGS_CLUT_POST_LINEARIZATION) { if (*dwFlags & cmsFLAGS_CLUT_POST_LINEARIZATION) {
...@@ -662,7 +657,8 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 ...@@ -662,7 +657,8 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
// All seems ok, proceed. // All seems ok, proceed.
NewPostLin = cmsStageDup(PostLin); NewPostLin = cmsStageDup(PostLin);
cmsPipelineInsertStage(Dest, cmsAT_END, NewPostLin); if (!cmsPipelineInsertStage(Dest, cmsAT_END, NewPostLin))
goto Error;
// In destination LUT, the sampling shoud be applied after this stage. // In destination LUT, the sampling shoud be applied after this stage.
cmsPipelineUnlinkStage(Src, cmsAT_END, &KeepPostLin); cmsPipelineUnlinkStage(Src, cmsAT_END, &KeepPostLin);
...@@ -673,10 +669,18 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 ...@@ -673,10 +669,18 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
// Now its time to do the sampling. We have to ignore pre/post linearization // Now its time to do the sampling. We have to ignore pre/post linearization
// The source LUT whithout pre/post curves is passed as parameter. // The source LUT whithout pre/post curves is passed as parameter.
if (!cmsStageSampleCLut16bit(CLUT, XFormSampler16, (void*) Src, 0)) { if (!cmsStageSampleCLut16bit(CLUT, XFormSampler16, (void*) Src, 0)) {
Error:
// Ops, something went wrong, Restore stages // Ops, something went wrong, Restore stages
if (KeepPreLin != NULL) cmsPipelineInsertStage(Src, cmsAT_BEGIN, KeepPreLin); if (KeepPreLin != NULL) {
if (KeepPostLin != NULL) cmsPipelineInsertStage(Src, cmsAT_END, KeepPostLin); if (!cmsPipelineInsertStage(Src, cmsAT_BEGIN, KeepPreLin)) {
_cmsAssert(0); // This never happens
}
}
if (KeepPostLin != NULL) {
if (!cmsPipelineInsertStage(Src, cmsAT_END, KeepPostLin)) {
_cmsAssert(0); // This never happens
}
}
cmsPipelineFree(Dest); cmsPipelineFree(Dest);
return FALSE; return FALSE;
} }
...@@ -709,7 +713,6 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 ...@@ -709,7 +713,6 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
Dest ->OutputChannels, Dest ->OutputChannels,
DataSetOut); DataSetOut);
_cmsPipelineSetOptimizationParameters(Dest, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup); _cmsPipelineSetOptimizationParameters(Dest, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup);
} }
...@@ -1062,7 +1065,8 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte ...@@ -1062,7 +1065,8 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte
LutPlusCurves = cmsPipelineDup(OriginalLut); LutPlusCurves = cmsPipelineDup(OriginalLut);
if (LutPlusCurves == NULL) goto Error; if (LutPlusCurves == NULL) goto Error;
cmsPipelineInsertStage(LutPlusCurves, cmsAT_BEGIN, cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, TransReverse)); if (!cmsPipelineInsertStage(LutPlusCurves, cmsAT_BEGIN, cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, TransReverse)))
goto Error;
// Create the result LUT // Create the result LUT
OptimizedLUT = cmsPipelineAlloc(OriginalLut ->ContextID, OriginalLut ->InputChannels, OriginalLut ->OutputChannels); OptimizedLUT = cmsPipelineAlloc(OriginalLut ->ContextID, OriginalLut ->InputChannels, OriginalLut ->OutputChannels);
...@@ -1071,13 +1075,15 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte ...@@ -1071,13 +1075,15 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte
OptimizedPrelinMpe = cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, Trans); OptimizedPrelinMpe = cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, Trans);
// Create and insert the curves at the beginning // Create and insert the curves at the beginning
cmsPipelineInsertStage(OptimizedLUT, cmsAT_BEGIN, OptimizedPrelinMpe); if (!cmsPipelineInsertStage(OptimizedLUT, cmsAT_BEGIN, OptimizedPrelinMpe))
goto Error;
// Allocate the CLUT for result // Allocate the CLUT for result
OptimizedCLUTmpe = cmsStageAllocCLut16bit(OriginalLut ->ContextID, nGridPoints, OriginalLut ->InputChannels, OriginalLut ->OutputChannels, NULL); OptimizedCLUTmpe = cmsStageAllocCLut16bit(OriginalLut ->ContextID, nGridPoints, OriginalLut ->InputChannels, OriginalLut ->OutputChannels, NULL);
// Add the CLUT to the destination LUT // Add the CLUT to the destination LUT
cmsPipelineInsertStage(OptimizedLUT, cmsAT_END, OptimizedCLUTmpe); if (!cmsPipelineInsertStage(OptimizedLUT, cmsAT_END, OptimizedCLUTmpe))
goto Error;
// Resample the LUT // Resample the LUT
if (!cmsStageSampleCLut16bit(OptimizedCLUTmpe, XFormSampler16, (void*) LutPlusCurves, 0)) goto Error; if (!cmsStageSampleCLut16bit(OptimizedCLUTmpe, XFormSampler16, (void*) LutPlusCurves, 0)) goto Error;
...@@ -1205,13 +1211,14 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsT ...@@ -1205,13 +1211,14 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsT
for (i=0; i < nCurves; i++) { for (i=0; i < nCurves; i++) {
c16->Curves[i] = _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number)); c16->Curves[i] = _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number));
if (c16->Curves[i] == NULL) { if (c16->Curves[i] == NULL) {
for (j=0; j < i; j++) { for (j=0; j < i; j++) {
_cmsFree(ContextID, c16->Curves[j]); _cmsFree(ContextID, c16->Curves[j]);
} }
_cmsFree(ContextID, c16->Curves); _cmsFree(ContextID, c16->Curves);
_cmsFree(ContextID, c16); _cmsFree(ContextID, c16);
return NULL; return NULL;
} }
...@@ -1340,7 +1347,8 @@ cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUI ...@@ -1340,7 +1347,8 @@ cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUI
// Maybe the curves are linear at the end // Maybe the curves are linear at the end
if (!AllCurvesAreLinear(ObtainedCurves)) { if (!AllCurvesAreLinear(ObtainedCurves)) {
cmsPipelineInsertStage(Dest, cmsAT_BEGIN, ObtainedCurves); if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, ObtainedCurves))
goto Error;
// If the curves are to be applied in 8 bits, we can save memory // If the curves are to be applied in 8 bits, we can save memory
if (_cmsFormatterIs8bit(*InputFormat)) { if (_cmsFormatterIs8bit(*InputFormat)) {
...@@ -1348,6 +1356,7 @@ cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUI ...@@ -1348,6 +1356,7 @@ cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUI
_cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) ObtainedCurves ->Data; _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) ObtainedCurves ->Data;
Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 256, Data ->TheCurves); Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 256, Data ->TheCurves);
if (c16 == NULL) goto Error;
*dwFlags |= cmsFLAGS_NOCACHE; *dwFlags |= cmsFLAGS_NOCACHE;
_cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves8, c16, CurvesFree, CurvesDup); _cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves8, c16, CurvesFree, CurvesDup);
...@@ -1357,6 +1366,7 @@ cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUI ...@@ -1357,6 +1366,7 @@ cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUI
_cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) cmsStageData(ObtainedCurves); _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) cmsStageData(ObtainedCurves);
Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 65536, Data ->TheCurves); Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 65536, Data ->TheCurves);
if (c16 == NULL) goto Error;
*dwFlags |= cmsFLAGS_NOCACHE; *dwFlags |= cmsFLAGS_NOCACHE;
_cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves16, c16, CurvesFree, CurvesDup); _cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves16, c16, CurvesFree, CurvesDup);
} }
...@@ -1366,7 +1376,8 @@ cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUI ...@@ -1366,7 +1376,8 @@ cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUI
// LUT optimizes to nothing. Set the identity LUT // LUT optimizes to nothing. Set the identity LUT
cmsStageFree(ObtainedCurves); cmsStageFree(ObtainedCurves);
cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels)); if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels)))
goto Error;
*dwFlags |= cmsFLAGS_NOCACHE; *dwFlags |= cmsFLAGS_NOCACHE;
_cmsPipelineSetOptimizationParameters(Dest, FastIdentity16, (void*) Dest, NULL, NULL); _cmsPipelineSetOptimizationParameters(Dest, FastIdentity16, (void*) Dest, NULL, NULL);
...@@ -1596,10 +1607,14 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 ...@@ -1596,10 +1607,14 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
if (!Dest) return FALSE; if (!Dest) return FALSE;
// Assamble the new LUT // Assamble the new LUT
cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1)); if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1)))
goto Error;
if (!IdentityMat) if (!IdentityMat)
cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset)); if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset)))
cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2)); goto Error;
if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2)))
goto Error;
// If identity on matrix, we can further optimize the curves, so call the join curves routine // If identity on matrix, we can further optimize the curves, so call the join curves routine
if (IdentityMat) { if (IdentityMat) {
...@@ -1621,6 +1636,10 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 ...@@ -1621,6 +1636,10 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
cmsPipelineFree(Src); cmsPipelineFree(Src);
*Lut = Dest; *Lut = Dest;
return TRUE; return TRUE;
Error:
// Leave Src unchanged
cmsPipelineFree(Dest);
return FALSE;
} }
...@@ -1650,7 +1669,7 @@ static _cmsOptimizationCollection DefaultOptimization[] = { ...@@ -1650,7 +1669,7 @@ static _cmsOptimizationCollection DefaultOptimization[] = {
static _cmsOptimizationCollection* OptimizationCollection = DefaultOptimization; static _cmsOptimizationCollection* OptimizationCollection = DefaultOptimization;
// Register new ways to optimize // Register new ways to optimize
cmsBool _cmsRegisterOptimizationPlugin(cmsPluginBase* Data) cmsBool _cmsRegisterOptimizationPlugin(cmsContext id, cmsPluginBase* Data)
{ {
cmsPluginOptimization* Plugin = (cmsPluginOptimization*) Data; cmsPluginOptimization* Plugin = (cmsPluginOptimization*) Data;
_cmsOptimizationCollection* fl; _cmsOptimizationCollection* fl;
...@@ -1664,7 +1683,7 @@ cmsBool _cmsRegisterOptimizationPlugin(cmsPluginBase* Data) ...@@ -1664,7 +1683,7 @@ cmsBool _cmsRegisterOptimizationPlugin(cmsPluginBase* Data)
// Optimizer callback is required // Optimizer callback is required
if (Plugin ->OptimizePtr == NULL) return FALSE; if (Plugin ->OptimizePtr == NULL) return FALSE;
fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(sizeof(_cmsOptimizationCollection)); fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(id, sizeof(_cmsOptimizationCollection));
if (fl == NULL) return FALSE; if (fl == NULL) return FALSE;
// Copy the parameters // Copy the parameters
......
...@@ -316,6 +316,23 @@ cmsUInt8Number* Unroll3BytesSkip1Swap(register _cmsTRANSFORM* info, ...@@ -316,6 +316,23 @@ cmsUInt8Number* Unroll3BytesSkip1Swap(register _cmsTRANSFORM* info,
cmsUNUSED_PARAMETER(Stride); cmsUNUSED_PARAMETER(Stride);
} }
static
cmsUInt8Number* Unroll3BytesSkip1SwapSwapFirst(register _cmsTRANSFORM* info,
register cmsUInt16Number wIn[],
register cmsUInt8Number* accum,
register cmsUInt32Number Stride)
{
wIn[2] = FROM_8_TO_16(*accum); accum++; // B
wIn[1] = FROM_8_TO_16(*accum); accum++; // G
wIn[0] = FROM_8_TO_16(*accum); accum++; // R
accum++; // A
return accum;
cmsUNUSED_PARAMETER(info);
cmsUNUSED_PARAMETER(Stride);
}
static static
cmsUInt8Number* Unroll3BytesSkip1SwapFirst(register _cmsTRANSFORM* info, cmsUInt8Number* Unroll3BytesSkip1SwapFirst(register _cmsTRANSFORM* info,
register cmsUInt16Number wIn[], register cmsUInt16Number wIn[],
...@@ -2901,6 +2918,9 @@ static cmsFormatters16 InputFormatters16[] = { ...@@ -2901,6 +2918,9 @@ static cmsFormatters16 InputFormatters16[] = {
{ CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSkip1Swap}, { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSkip1Swap},
{ CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3BytesSkip1SwapFirst}, { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3BytesSkip1SwapFirst},
{ CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
ANYSPACE, Unroll3BytesSkip1SwapSwapFirst},
{ CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Unroll4Bytes}, { CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Unroll4Bytes},
{ CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll4BytesReverse}, { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll4BytesReverse},
{ CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapFirst}, { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapFirst},
...@@ -3166,7 +3186,7 @@ static cmsFormattersFactoryList* FactoryList = NULL; ...@@ -3166,7 +3186,7 @@ static cmsFormattersFactoryList* FactoryList = NULL;
// Formatters management // Formatters management
cmsBool _cmsRegisterFormattersPlugin(cmsPluginBase* Data) cmsBool _cmsRegisterFormattersPlugin(cmsContext id, cmsPluginBase* Data)
{ {
cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data; cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data;
cmsFormattersFactoryList* fl ; cmsFormattersFactoryList* fl ;
...@@ -3178,7 +3198,7 @@ cmsBool _cmsRegisterFormattersPlugin(cmsPluginBase* Data) ...@@ -3178,7 +3198,7 @@ cmsBool _cmsRegisterFormattersPlugin(cmsPluginBase* Data)
return TRUE; return TRUE;
} }
fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(sizeof(cmsFormattersFactoryList)); fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(id, sizeof(cmsFormattersFactoryList));
if (fl == NULL) return FALSE; if (fl == NULL) return FALSE;
fl ->Factory = Plugin ->FormattersFactory; fl ->Factory = Plugin ->FormattersFactory;
......
...@@ -898,9 +898,11 @@ cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace) ...@@ -898,9 +898,11 @@ cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace)
{ {
switch (ColorSpace) { switch (ColorSpace) {
case cmsSigMCH1Data:
case cmsSig1colorData: case cmsSig1colorData:
case cmsSigGrayData: return 1; case cmsSigGrayData: return 1;
case cmsSigMCH2Data:
case cmsSig2colorData: return 2; case cmsSig2colorData: return 2;
case cmsSigXYZData: case cmsSigXYZData:
...@@ -912,10 +914,12 @@ cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace) ...@@ -912,10 +914,12 @@ cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace)
case cmsSigHsvData: case cmsSigHsvData:
case cmsSigHlsData: case cmsSigHlsData:
case cmsSigCmyData: case cmsSigCmyData:
case cmsSigMCH3Data:
case cmsSig3colorData: return 3; case cmsSig3colorData: return 3;
case cmsSigLuvKData: case cmsSigLuvKData:
case cmsSigCmykData: case cmsSigCmykData:
case cmsSigMCH4Data:
case cmsSig4colorData: return 4; case cmsSig4colorData: return 4;
case cmsSigMCH5Data: case cmsSigMCH5Data:
......
...@@ -125,10 +125,14 @@ void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number* ...@@ -125,10 +125,14 @@ void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number*
pOut[0] = pIn[7]; pOut[0] = pIn[7];
#else #else
_cmsAssert(Result != NULL); _cmsAssert(Result != NULL);
# ifdef CMS_DONT_USE_INT64
(*Result)[0] = QWord[0];
(*Result)[1] = QWord[1];
# else
*Result = *QWord; *Result = *QWord;
# endif
#endif #endif
} }
...@@ -543,10 +547,10 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...) ...@@ -543,10 +547,10 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)
static _cmsSubAllocator* PluginPool = NULL; static _cmsSubAllocator* PluginPool = NULL;
// Specialized malloc for plug-ins, that is freed upon exit. // Specialized malloc for plug-ins, that is freed upon exit.
void* _cmsPluginMalloc(cmsUInt32Number size) void* _cmsPluginMalloc(cmsContext id, cmsUInt32Number size)
{ {
if (PluginPool == NULL) if (PluginPool == NULL)
PluginPool = _cmsCreateSubAlloc(0, 4*1024); PluginPool = _cmsCreateSubAlloc(id, 4*1024);
return _cmsSubAlloc(PluginPool, size); return _cmsSubAlloc(PluginPool, size);
} }
...@@ -554,6 +558,11 @@ void* _cmsPluginMalloc(cmsUInt32Number size) ...@@ -554,6 +558,11 @@ void* _cmsPluginMalloc(cmsUInt32Number size)
// Main plug-in dispatcher // Main plug-in dispatcher
cmsBool CMSEXPORT cmsPlugin(void* Plug_in) cmsBool CMSEXPORT cmsPlugin(void* Plug_in)
{
return cmsPluginTHR(NULL, Plug_in);
}
cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)
{ {
cmsPluginBase* Plugin; cmsPluginBase* Plugin;
...@@ -583,35 +592,35 @@ cmsBool CMSEXPORT cmsPlugin(void* Plug_in) ...@@ -583,35 +592,35 @@ cmsBool CMSEXPORT cmsPlugin(void* Plug_in)
break; break;
case cmsPluginTagTypeSig: case cmsPluginTagTypeSig:
if (!_cmsRegisterTagTypePlugin(Plugin)) return FALSE; if (!_cmsRegisterTagTypePlugin(id, Plugin)) return FALSE;
break; break;
case cmsPluginTagSig: case cmsPluginTagSig:
if (!_cmsRegisterTagPlugin(Plugin)) return FALSE; if (!_cmsRegisterTagPlugin(id, Plugin)) return FALSE;
break; break;
case cmsPluginFormattersSig: case cmsPluginFormattersSig:
if (!_cmsRegisterFormattersPlugin(Plugin)) return FALSE; if (!_cmsRegisterFormattersPlugin(id, Plugin)) return FALSE;
break; break;
case cmsPluginRenderingIntentSig: case cmsPluginRenderingIntentSig:
if (!_cmsRegisterRenderingIntentPlugin(Plugin)) return FALSE; if (!_cmsRegisterRenderingIntentPlugin(id, Plugin)) return FALSE;
break; break;
case cmsPluginParametricCurveSig: case cmsPluginParametricCurveSig:
if (!_cmsRegisterParametricCurvesPlugin(Plugin)) return FALSE; if (!_cmsRegisterParametricCurvesPlugin(id, Plugin)) return FALSE;
break; break;
case cmsPluginMultiProcessElementSig: case cmsPluginMultiProcessElementSig:
if (!_cmsRegisterMultiProcessElementPlugin(Plugin)) return FALSE; if (!_cmsRegisterMultiProcessElementPlugin(id, Plugin)) return FALSE;
break; break;
case cmsPluginOptimizationSig: case cmsPluginOptimizationSig:
if (!_cmsRegisterOptimizationPlugin(Plugin)) return FALSE; if (!_cmsRegisterOptimizationPlugin(id, Plugin)) return FALSE;
break; break;
case cmsPluginTransformSig: case cmsPluginTransformSig:
if (!_cmsRegisterTransformPlugin(Plugin)) return FALSE; if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE;
break; break;
default: default:
...@@ -630,14 +639,14 @@ void CMSEXPORT cmsUnregisterPlugins(void) ...@@ -630,14 +639,14 @@ void CMSEXPORT cmsUnregisterPlugins(void)
{ {
_cmsRegisterMemHandlerPlugin(NULL); _cmsRegisterMemHandlerPlugin(NULL);
_cmsRegisterInterpPlugin(NULL); _cmsRegisterInterpPlugin(NULL);
_cmsRegisterTagTypePlugin(NULL); _cmsRegisterTagTypePlugin(NULL, NULL);
_cmsRegisterTagPlugin(NULL); _cmsRegisterTagPlugin(NULL, NULL);
_cmsRegisterFormattersPlugin(NULL); _cmsRegisterFormattersPlugin(NULL, NULL);
_cmsRegisterRenderingIntentPlugin(NULL); _cmsRegisterRenderingIntentPlugin(NULL, NULL);
_cmsRegisterParametricCurvesPlugin(NULL); _cmsRegisterParametricCurvesPlugin(NULL, NULL);
_cmsRegisterMultiProcessElementPlugin(NULL); _cmsRegisterMultiProcessElementPlugin(NULL, NULL);
_cmsRegisterOptimizationPlugin(NULL); _cmsRegisterOptimizationPlugin(NULL, NULL);
_cmsRegisterTransformPlugin(NULL); _cmsRegisterTransformPlugin(NULL, NULL);
if (PluginPool != NULL) if (PluginPool != NULL)
_cmsSubAllocDestroy(PluginPool); _cmsSubAllocDestroy(PluginPool);
......
...@@ -806,7 +806,6 @@ int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXY ...@@ -806,7 +806,6 @@ int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXY
mpe = Pipeline ->Elements; mpe = Pipeline ->Elements;
switch (cmsStageInputChannels(mpe)) { switch (cmsStageInputChannels(mpe)) {
case 3: case 3:
...@@ -838,8 +837,6 @@ int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXY ...@@ -838,8 +837,6 @@ int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXY
mpe = mpe ->Next; mpe = mpe ->Next;
} }
if (cmsStageType(mpe) == cmsSigCLutElemType) { if (cmsStageType(mpe) == cmsSigCLutElemType) {
_cmsIOPrintf(m, "/Table "); _cmsIOPrintf(m, "/Table ");
...@@ -854,7 +851,6 @@ int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXY ...@@ -854,7 +851,6 @@ int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXY
_cmsIOPrintf(m, " >>\n"); _cmsIOPrintf(m, " >>\n");
_cmsIOPrintf(m, "]\n"); _cmsIOPrintf(m, "]\n");
return 1; return 1;
} }
...@@ -950,6 +946,7 @@ int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Nu ...@@ -950,6 +946,7 @@ int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Nu
rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50); rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50);
cmsPipelineFree(DeviceLink); cmsPipelineFree(DeviceLink);
if (rc == 0) return 0;
} }
break; break;
......
...@@ -56,6 +56,8 @@ ...@@ -56,6 +56,8 @@
#include "lcms2_internal.h" #include "lcms2_internal.h"
#define cmsmin(a, b) (((a) < (b)) ? (a) : (b))
#define cmsmax(a, b) (((a) > (b)) ? (a) : (b))
// This file contains routines for resampling and LUT optimization, black point detection // This file contains routines for resampling and LUT optimization, black point detection
// and black preservation. // and black preservation.
...@@ -67,13 +69,13 @@ ...@@ -67,13 +69,13 @@
static static
cmsHTRANSFORM CreateRoundtripXForm(cmsHPROFILE hProfile, cmsUInt32Number nIntent) cmsHTRANSFORM CreateRoundtripXForm(cmsHPROFILE hProfile, cmsUInt32Number nIntent)
{ {
cmsHPROFILE hLab = cmsCreateLab4Profile(NULL); cmsContext ContextID = cmsGetProfileContextID(hProfile);
cmsHPROFILE hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
cmsHTRANSFORM xform; cmsHTRANSFORM xform;
cmsBool BPC[4] = { FALSE, FALSE, FALSE, FALSE }; cmsBool BPC[4] = { FALSE, FALSE, FALSE, FALSE };
cmsFloat64Number States[4] = { 1.0, 1.0, 1.0, 1.0 }; cmsFloat64Number States[4] = { 1.0, 1.0, 1.0, 1.0 };
cmsHPROFILE hProfiles[4]; cmsHPROFILE hProfiles[4];
cmsUInt32Number Intents[4]; cmsUInt32Number Intents[4];
cmsContext ContextID = cmsGetProfileContextID(hProfile);
hProfiles[0] = hLab; hProfiles[1] = hProfile; hProfiles[2] = hProfile; hProfiles[3] = hLab; hProfiles[0] = hLab; hProfiles[1] = hProfile; hProfiles[2] = hProfile; hProfiles[3] = hLab;
Intents[0] = INTENT_RELATIVE_COLORIMETRIC; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = INTENT_RELATIVE_COLORIMETRIC; Intents[0] = INTENT_RELATIVE_COLORIMETRIC; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = INTENT_RELATIVE_COLORIMETRIC;
...@@ -141,8 +143,8 @@ cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput, ...@@ -141,8 +143,8 @@ cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput,
cmsCloseProfile(hLab); cmsCloseProfile(hLab);
if (xform == NULL) { if (xform == NULL) {
// Something went wrong. Get rid of open resources and return zero as black
// Something went wrong. Get rid of open resources and return zero as black
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE; return FALSE;
} }
...@@ -173,7 +175,6 @@ cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput, ...@@ -173,7 +175,6 @@ cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput,
// Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Lab // Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Lab
static static
cmsBool BlackPointUsingPerceptualBlack(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile) cmsBool BlackPointUsingPerceptualBlack(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile)
{ {
cmsHTRANSFORM hRoundTrip; cmsHTRANSFORM hRoundTrip;
cmsCIELab LabIn, LabOut; cmsCIELab LabIn, LabOut;
...@@ -218,17 +219,27 @@ cmsBool BlackPointUsingPerceptualBlack(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfi ...@@ -218,17 +219,27 @@ cmsBool BlackPointUsingPerceptualBlack(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfi
// involves to turn BP to neutral and to use only L component. // involves to turn BP to neutral and to use only L component.
cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags) cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
{ {
cmsProfileClassSignature devClass;
// Zero for black point // Make sure the device class is adequate
if (cmsGetDeviceClass(hProfile) == cmsSigLinkClass) { devClass = cmsGetDeviceClass(hProfile);
if (devClass == cmsSigLinkClass ||
devClass == cmsSigAbstractClass ||
devClass == cmsSigNamedColorClass) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
// Make sure intent is adequate
if (Intent != INTENT_PERCEPTUAL &&
Intent != INTENT_RELATIVE_COLORIMETRIC &&
Intent != INTENT_SATURATION) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE; return FALSE;
} }
// v4 + perceptual & saturation intents does have its own black point, and it is // v4 + perceptual & saturation intents does have its own black point, and it is
// well specified enough to use it. Black point tag is deprecated in V4. // well specified enough to use it. Black point tag is deprecated in V4.
if ((cmsGetEncodedICCversion(hProfile) >= 0x4000000) && if ((cmsGetEncodedICCversion(hProfile) >= 0x4000000) &&
(Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) { (Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) {
...@@ -303,7 +314,7 @@ cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[] ...@@ -303,7 +314,7 @@ cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[]
{ {
double sum_x = 0, sum_x2 = 0, sum_x3 = 0, sum_x4 = 0; double sum_x = 0, sum_x2 = 0, sum_x3 = 0, sum_x4 = 0;
double sum_y = 0, sum_yx = 0, sum_yx2 = 0; double sum_y = 0, sum_yx = 0, sum_yx2 = 0;
double disc; double d, a, b, c;
int i; int i;
cmsMAT3 m; cmsMAT3 m;
cmsVEC3 v, res; cmsVEC3 v, res;
...@@ -333,14 +344,32 @@ cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[] ...@@ -333,14 +344,32 @@ cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[]
if (!_cmsMAT3solve(&res, &m, &v)) return 0; if (!_cmsMAT3solve(&res, &m, &v)) return 0;
// y = t x2 + u x + c
// x = ( - u + Sqrt( u^2 - 4 t c ) ) / ( 2 t )
disc = res.n[1]*res.n[1] - 4.0 * res.n[0] * res.n[2];
if (disc < 0) return -1;
return ( -1.0 * res.n[1] + sqrt( disc )) / (2.0 * res.n[0]); a = res.n[2];
b = res.n[1];
c = res.n[0];
if (fabs(a) < 1.0E-10) {
return cmsmin(0, cmsmax(50, -c/b ));
}
else {
d = b*b - 4.0 * a * c;
if (d <= 0) {
return 0;
}
else {
double rt = (-b + sqrt(d)) / (2.0 * a);
return cmsmax(0, cmsmin(50, rt));
}
}
} }
/*
static static
cmsBool IsMonotonic(int n, const cmsFloat64Number Table[]) cmsBool IsMonotonic(int n, const cmsFloat64Number Table[])
{ {
...@@ -361,6 +390,7 @@ cmsBool IsMonotonic(int n, const cmsFloat64Number Table[]) ...@@ -361,6 +390,7 @@ cmsBool IsMonotonic(int n, const cmsFloat64Number Table[])
return TRUE; return TRUE;
} }
*/
// Calculates the black point of a destination profile. // Calculates the black point of a destination profile.
// This algorithm comes from the Adobe paper disclosing its black point compensation method. // This algorithm comes from the Adobe paper disclosing its black point compensation method.
...@@ -369,14 +399,23 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF ...@@ -369,14 +399,23 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
cmsColorSpaceSignature ColorSpace; cmsColorSpaceSignature ColorSpace;
cmsHTRANSFORM hRoundTrip = NULL; cmsHTRANSFORM hRoundTrip = NULL;
cmsCIELab InitialLab, destLab, Lab; cmsCIELab InitialLab, destLab, Lab;
cmsFloat64Number inRamp[256], outRamp[256];
cmsFloat64Number MinL, MaxL; cmsFloat64Number MinL, MaxL;
cmsBool NearlyStraightMidRange = FALSE; cmsBool NearlyStraightMidrange = TRUE;
cmsFloat64Number L; cmsFloat64Number yRamp[256];
cmsFloat64Number x[101], y[101]; cmsFloat64Number x[256], y[256];
cmsFloat64Number lo, hi, NonMonoMin; cmsFloat64Number lo, hi;
int n, l, i, NonMonoIndx; int n, l;
cmsProfileClassSignature devClass;
// Make sure the device class is adequate
devClass = cmsGetDeviceClass(hProfile);
if (devClass == cmsSigLinkClass ||
devClass == cmsSigAbstractClass ||
devClass == cmsSigNamedColorClass) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
// Make sure intent is adequate // Make sure intent is adequate
if (Intent != INTENT_PERCEPTUAL && if (Intent != INTENT_PERCEPTUAL &&
...@@ -415,10 +454,8 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF ...@@ -415,10 +454,8 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
return cmsDetectBlackPoint(BlackPoint, hProfile, Intent, dwFlags); return cmsDetectBlackPoint(BlackPoint, hProfile, Intent, dwFlags);
} }
// It is one of the valid cases!, presto chargo hocus pocus, go for the Adobe magic // It is one of the valid cases!, use Adobe algorithm
// Step 1
// ======
// Set a first guess, that should work on good profiles. // Set a first guess, that should work on good profiles.
if (Intent == INTENT_RELATIVE_COLORIMETRIC) { if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
...@@ -449,71 +486,68 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF ...@@ -449,71 +486,68 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
hRoundTrip = CreateRoundtripXForm(hProfile, Intent); hRoundTrip = CreateRoundtripXForm(hProfile, Intent);
if (hRoundTrip == NULL) return FALSE; if (hRoundTrip == NULL) return FALSE;
// Calculate Min L* // Compute ramps
Lab = InitialLab;
Lab.L = 0;
cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
MinL = destLab.L;
// Calculate Max L* for (l=0; l < 256; l++) {
Lab = InitialLab;
Lab.L = 100;
cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
MaxL = destLab.L;
// Step 3 Lab.L = (cmsFloat64Number) (l * 100.0) / 255.0;
// ====== Lab.a = cmsmin(50, cmsmax(-50, InitialLab.a));
Lab.b = cmsmin(50, cmsmax(-50, InitialLab.b));
// check if quadratic estimation needs to be done. cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
// Conceptually, this code tests how close the source l and converted L are to one another in the mid-range inRamp[l] = Lab.L;
// of the values. If the converted ramp of L values is close enough to a straight line y=x, then InitialLab outRamp[l] = destLab.L;
// is good enough to be the DestinationBlackPoint, }
NearlyStraightMidRange = TRUE;
for (l=0; l <= 100; l++) { // Make monotonic
for (l = 254; l > 0; --l) {
outRamp[l] = cmsmin(outRamp[l], outRamp[l+1]);
}
Lab.L = l; // Check
Lab.a = InitialLab.a; if (! (outRamp[0] < outRamp[255])) {
Lab.b = InitialLab.b;
cmsDoTransform(hRoundTrip, &Lab, &destLab, 1); cmsDeleteTransform(hRoundTrip);
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
L = destLab.L;
// Check the mid range in 20% after MinL // Test for mid range straight (only on relative colorimetric)
if (L > (MinL + 0.2 * (MaxL - MinL))) {
// Is close enough? NearlyStraightMidrange = TRUE;
if (fabs(L - l) > 4.0) { MinL = outRamp[0]; MaxL = outRamp[255];
if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
// Too far away, profile is buggy! for (l=0; l < 256; l++) {
NearlyStraightMidRange = FALSE;
break; if (! ((inRamp[l] <= MinL + 0.2 * (MaxL - MinL) ) ||
} (fabs(inRamp[l] - outRamp[l]) < 4.0 )))
} NearlyStraightMidrange = FALSE;
}
}
else {
// Check is always performed for perceptual and saturation intents
NearlyStraightMidRange = FALSE;
} }
// If the mid range is straight (as determined above) then the
// DestinationBlackPoint shall be the same as initialLab.
// Otherwise, the DestinationBlackPoint shall be determined
// using curve fitting.
// If no furter checking is needed, we are done if (NearlyStraightMidrange) {
if (NearlyStraightMidRange) {
cmsLab2XYZ(NULL, BlackPoint, &InitialLab); cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
cmsDeleteTransform(hRoundTrip); cmsDeleteTransform(hRoundTrip);
return TRUE; return TRUE;
} }
}
// The round-trip curve normally looks like a nearly constant section at the black point, // curve fitting: The round-trip curve normally looks like a nearly constant section at the black point,
// with a corner and a nearly straight line to the white point. // with a corner and a nearly straight line to the white point.
// STEP 4 for (l=0; l < 256; l++) {
// =======
yRamp[l] = (outRamp[l] - MinL) / (MaxL - MinL);
}
// find the black point using the least squares error quadratic curve fitting // find the black point using the least squares error quadratic curve fitting
...@@ -528,62 +562,32 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF ...@@ -528,62 +562,32 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
hi = 0.25; hi = 0.25;
} }
// Capture points for the fitting. // Capture shadow points for the fitting.
n = 0; n = 0;
for (l=0; l <= 100; l++) { for (l=0; l < 256; l++) {
cmsFloat64Number ff;
Lab.L = (cmsFloat64Number) l;
Lab.a = InitialLab.a;
Lab.b = InitialLab.b;
cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
ff = (destLab.L - MinL)/(MaxL - MinL); cmsFloat64Number ff = yRamp[l];
if (ff >= lo && ff < hi) { if (ff >= lo && ff < hi) {
x[n] = inRamp[l];
x[n] = Lab.L; y[n] = yRamp[l];
y[n] = ff;
n++; n++;
} }
} }
// This part is not on the Adobe paper, but I found is necessary for getting any result.
if (IsMonotonic(n, y)) {
// Monotonic means lower point is stil valid
cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
cmsDeleteTransform(hRoundTrip);
return TRUE;
}
// No suitable points, regret and use safer algorithm // No suitable points
if (n == 0) { if (n < 3 ) {
cmsDeleteTransform(hRoundTrip); cmsDeleteTransform(hRoundTrip);
return cmsDetectBlackPoint(BlackPoint, hProfile, Intent, dwFlags); BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
} return FALSE;
NonMonoMin = 100;
NonMonoIndx = 0;
for (i=0; i < n; i++) {
if (y[i] < NonMonoMin) {
NonMonoIndx = i;
NonMonoMin = y[i];
}
} }
Lab.L = x[NonMonoIndx];
// fit and get the vertex of quadratic curve // fit and get the vertex of quadratic curve
Lab.L = RootOfLeastSquaresFitQuadraticCurve(n, x, y); Lab.L = RootOfLeastSquaresFitQuadraticCurve(n, x, y);
if (Lab.L < 0.0 || Lab.L > 50.0) { // clip to zero L* if the vertex is negative if (Lab.L < 0.0) { // clip to zero L* if the vertex is negative
Lab.L = 0; Lab.L = 0;
} }
......
...@@ -91,7 +91,7 @@ typedef struct _cmsTagTypeLinkedList_st { ...@@ -91,7 +91,7 @@ typedef struct _cmsTagTypeLinkedList_st {
// Register a new type handler. This routine is shared between normal types and MPE // Register a new type handler. This routine is shared between normal types and MPE
static static
cmsBool RegisterTypesPlugin(cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount) cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount)
{ {
cmsPluginTagType* Plugin = (cmsPluginTagType*) Data; cmsPluginTagType* Plugin = (cmsPluginTagType*) Data;
_cmsTagTypeLinkedList *pt, *Anterior = NULL; _cmsTagTypeLinkedList *pt, *Anterior = NULL;
...@@ -118,7 +118,7 @@ cmsBool RegisterTypesPlugin(cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedLi ...@@ -118,7 +118,7 @@ cmsBool RegisterTypesPlugin(cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedLi
} }
// Registering happens in plug-in memory pool // Registering happens in plug-in memory pool
pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(sizeof(_cmsTagTypeLinkedList)); pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList));
if (pt == NULL) return FALSE; if (pt == NULL) return FALSE;
pt ->Handler = Plugin ->Handler; pt ->Handler = Plugin ->Handler;
...@@ -208,10 +208,10 @@ cmsBool ReadPositionTable(struct _cms_typehandler_struct* self, ...@@ -208,10 +208,10 @@ cmsBool ReadPositionTable(struct _cms_typehandler_struct* self,
cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL; cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
// Let's take the offsets to each element // Let's take the offsets to each element
ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *)); ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
if (ElementOffsets == NULL) goto Error; if (ElementOffsets == NULL) goto Error;
ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *)); ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
if (ElementSizes == NULL) goto Error; if (ElementSizes == NULL) goto Error;
for (i=0; i < Count; i++) { for (i=0; i < Count; i++) {
...@@ -257,10 +257,10 @@ cmsBool WritePositionTable(struct _cms_typehandler_struct* self, ...@@ -257,10 +257,10 @@ cmsBool WritePositionTable(struct _cms_typehandler_struct* self,
cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL; cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
// Create table // Create table
ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *)); ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
if (ElementOffsets == NULL) goto Error; if (ElementOffsets == NULL) goto Error;
ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *)); ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
if (ElementSizes == NULL) goto Error; if (ElementSizes == NULL) goto Error;
// Keep starting position of curve offsets // Keep starting position of curve offsets
...@@ -456,6 +456,7 @@ static ...@@ -456,6 +456,7 @@ static
void* Type_Chromaticity_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) void* Type_Chromaticity_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
{ {
return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIExyYTRIPLE)); return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIExyYTRIPLE));
cmsUNUSED_PARAMETER(n); cmsUNUSED_PARAMETER(n);
} }
...@@ -1106,8 +1107,6 @@ void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm ...@@ -1106,8 +1107,6 @@ void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
{ {
cmsUInt32Number Count; cmsUInt32Number Count;
cmsToneCurve* NewGamma; cmsToneCurve* NewGamma;
cmsUInt16Number Linear[2] = { 0, 0xffff };
*nItems = 0; *nItems = 0;
if (!_cmsReadUInt32Number(io, &Count)) return NULL; if (!_cmsReadUInt32Number(io, &Count)) return NULL;
...@@ -1115,11 +1114,14 @@ void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm ...@@ -1115,11 +1114,14 @@ void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
switch (Count) { switch (Count) {
case 0: // Linear. case 0: // Linear.
{
cmsFloat64Number SingleGamma = 1.0;
NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, 2, Linear); NewGamma = cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
if (!NewGamma) return NULL; if (!NewGamma) return NULL;
*nItems = 1; *nItems = 1;
return NewGamma; return NewGamma;
}
case 1: // Specified as the exponent of gamma function case 1: // Specified as the exponent of gamma function
{ {
...@@ -1210,6 +1212,7 @@ cmsTagTypeSignature DecideCurveType(cmsFloat64Number ICCVersion, const void *Dat ...@@ -1210,6 +1212,7 @@ cmsTagTypeSignature DecideCurveType(cmsFloat64Number ICCVersion, const void *Dat
if (ICCVersion < 4.0) return cmsSigCurveType; if (ICCVersion < 4.0) return cmsSigCurveType;
if (Curve ->nSegments != 1) return cmsSigCurveType; // Only 1-segment curves can be saved as parametric if (Curve ->nSegments != 1) return cmsSigCurveType; // Only 1-segment curves can be saved as parametric
if (Curve ->Segments[0].Type < 0) return cmsSigCurveType; // Only non-inverted curves if (Curve ->Segments[0].Type < 0) return cmsSigCurveType; // Only non-inverted curves
if (Curve ->Segments[0].Type > 5) return cmsSigCurveType; // Only ICC parametric curves
return cmsSigParametricCurveType; return cmsSigParametricCurveType;
} }
...@@ -1386,6 +1389,9 @@ void *Type_Measurement_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* ...@@ -1386,6 +1389,9 @@ void *Type_Measurement_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER*
{ {
cmsICCMeasurementConditions mc; cmsICCMeasurementConditions mc;
memset(&mc, 0, sizeof(mc));
if (!_cmsReadUInt32Number(io, &mc.Observer)) return NULL; if (!_cmsReadUInt32Number(io, &mc.Observer)) return NULL;
if (!_cmsReadXYZNumber(io, &mc.Backing)) return NULL; if (!_cmsReadXYZNumber(io, &mc.Backing)) return NULL;
if (!_cmsReadUInt32Number(io, &mc.Geometry)) return NULL; if (!_cmsReadUInt32Number(io, &mc.Geometry)) return NULL;
...@@ -1640,7 +1646,6 @@ Byte Position Field Length (bytes) Content Encoded as... ...@@ -1640,7 +1646,6 @@ Byte Position Field Length (bytes) Content Encoded as...
static static
cmsBool Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels) cmsBool Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels)
{ {
cmsStage* mpe;
cmsUInt8Number* Temp = NULL; cmsUInt8Number* Temp = NULL;
int i, j; int i, j;
cmsToneCurve* Tables[cmsMAXCHANNELS]; cmsToneCurve* Tables[cmsMAXCHANNELS];
...@@ -1669,11 +1674,8 @@ cmsBool Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut ...@@ -1669,11 +1674,8 @@ cmsBool Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut
_cmsFree(ContextID, Temp); _cmsFree(ContextID, Temp);
Temp = NULL; Temp = NULL;
if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables)))
mpe = cmsStageAllocToneCurves(ContextID, nChannels, Tables); goto Error;
if (mpe == NULL) goto Error;
cmsPipelineInsertStage(lut, cmsAT_END, mpe);
for (i=0; i < nChannels; i++) for (i=0; i < nChannels; i++)
cmsFreeToneCurve(Tables[i]); cmsFreeToneCurve(Tables[i]);
...@@ -1701,13 +1703,21 @@ cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number ...@@ -1701,13 +1703,21 @@ cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number
if (Tables) { if (Tables) {
// Usual case of identity curves
if ((Tables ->TheCurves[i]->nEntries == 2) &&
(Tables->TheCurves[i]->Table16[0] == 0) &&
(Tables->TheCurves[i]->Table16[1] == 65535)) {
for (j=0; j < 256; j++) {
if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) j)) return FALSE;
}
}
else
if (Tables ->TheCurves[i]->nEntries != 256) { if (Tables ->TheCurves[i]->nEntries != 256) {
cmsSignalError(ContextID, cmsERROR_RANGE, "LUT8 needs 256 entries on prelinearization"); cmsSignalError(ContextID, cmsERROR_RANGE, "LUT8 needs 256 entries on prelinearization");
return FALSE; return FALSE;
} }
else
}
for (j=0; j < 256; j++) { for (j=0; j < 256; j++) {
if (Tables != NULL) if (Tables != NULL)
...@@ -1718,13 +1728,14 @@ cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number ...@@ -1718,13 +1728,14 @@ cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number
if (!_cmsWriteUInt8Number(io, val)) return FALSE; if (!_cmsWriteUInt8Number(io, val)) return FALSE;
} }
} }
}
return TRUE; return TRUE;
} }
// Check overflow // Check overflow
static static
size_t uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b) cmsUInt32Number uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b)
{ {
cmsUInt32Number rv = 1, rc; cmsUInt32Number rv = 1, rc;
...@@ -1736,13 +1747,13 @@ size_t uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b) ...@@ -1736,13 +1747,13 @@ size_t uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b)
rv *= a; rv *= a;
// Check for overflow // Check for overflow
if (rv > UINT_MAX / a) return (size_t) -1; if (rv > UINT_MAX / a) return (cmsUInt32Number) -1;
} }
rc = rv * n; rc = rv * n;
if (rv != rc / n) return (size_t) -1; if (rv != rc / n) return (cmsUInt32Number) -1;
return rc; return rc;
} }
...@@ -1757,7 +1768,6 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms ...@@ -1757,7 +1768,6 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms
cmsUInt8Number InputChannels, OutputChannels, CLUTpoints; cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
cmsUInt8Number* Temp = NULL; cmsUInt8Number* Temp = NULL;
cmsPipeline* NewLUT = NULL; cmsPipeline* NewLUT = NULL;
cmsStage *mpemat, *mpeclut;
cmsUInt32Number nTabSize, i; cmsUInt32Number nTabSize, i;
cmsFloat64Number Matrix[3*3]; cmsFloat64Number Matrix[3*3];
...@@ -1796,9 +1806,8 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms ...@@ -1796,9 +1806,8 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms
// Only operates if not identity... // Only operates if not identity...
if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) { if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {
mpemat = cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL); if (!cmsPipelineInsertStage(NewLUT, cmsAT_BEGIN, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL)))
if (mpemat == NULL) goto Error; goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_BEGIN, mpemat);
} }
// Get input tables // Get input tables
...@@ -1806,13 +1815,10 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms ...@@ -1806,13 +1815,10 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms
// Get 3D CLUT. Check the overflow.... // Get 3D CLUT. Check the overflow....
nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels); nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels);
if (nTabSize == (size_t) -1) goto Error; if (nTabSize == (cmsUInt32Number) -1) goto Error;
if (nTabSize > 0) { if (nTabSize > 0) {
cmsUInt16Number *PtrW, *T; cmsUInt16Number *PtrW, *T;
cmsUInt32Number Tsize;
Tsize = (cmsUInt32Number) nTabSize * sizeof(cmsUInt16Number);
PtrW = T = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number)); PtrW = T = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number));
if (T == NULL) goto Error; if (T == NULL) goto Error;
...@@ -1829,10 +1835,8 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms ...@@ -1829,10 +1835,8 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms
_cmsFree(self ->ContextID, Temp); _cmsFree(self ->ContextID, Temp);
Temp = NULL; Temp = NULL;
if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T)))
mpeclut = cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T); goto Error;
if (mpeclut == NULL) goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpeclut);
_cmsFree(self ->ContextID, T); _cmsFree(self ->ContextID, T);
} }
...@@ -1934,7 +1938,7 @@ cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, ...@@ -1934,7 +1938,7 @@ cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE; if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE;
nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels); nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels);
if (nTabSize == (size_t) -1) return FALSE; if (nTabSize == (cmsUInt32Number) -1) return FALSE;
if (nTabSize > 0) { if (nTabSize > 0) {
// The 3D CLUT. // The 3D CLUT.
...@@ -1983,7 +1987,6 @@ void Type_LUT8_Free(struct _cms_typehandler_struct* self, void* Ptr) ...@@ -1983,7 +1987,6 @@ void Type_LUT8_Free(struct _cms_typehandler_struct* self, void* Ptr)
static static
cmsBool Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries) cmsBool Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries)
{ {
cmsStage* mpe;
int i; int i;
cmsToneCurve* Tables[cmsMAXCHANNELS]; cmsToneCurve* Tables[cmsMAXCHANNELS];
...@@ -2007,10 +2010,8 @@ cmsBool Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lu ...@@ -2007,10 +2010,8 @@ cmsBool Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lu
// Add the table (which may certainly be an identity, but this is up to the optimizer, not the reading code) // Add the table (which may certainly be an identity, but this is up to the optimizer, not the reading code)
mpe = cmsStageAllocToneCurves(ContextID, nChannels, Tables); if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables)))
if (mpe == NULL) goto Error; goto Error;
cmsPipelineInsertStage(lut, cmsAT_END, mpe);
for (i=0; i < nChannels; i++) for (i=0; i < nChannels; i++)
cmsFreeToneCurve(Tables[i]); cmsFreeToneCurve(Tables[i]);
...@@ -2031,7 +2032,9 @@ cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCu ...@@ -2031,7 +2032,9 @@ cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCu
int j; int j;
cmsUInt32Number i; cmsUInt32Number i;
cmsUInt16Number val; cmsUInt16Number val;
int nEntries = 256; int nEntries;
_cmsAssert(Tables != NULL);
nEntries = Tables->TheCurves[0]->nEntries; nEntries = Tables->TheCurves[0]->nEntries;
...@@ -2039,11 +2042,7 @@ cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCu ...@@ -2039,11 +2042,7 @@ cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCu
for (j=0; j < nEntries; j++) { for (j=0; j < nEntries; j++) {
if (Tables != NULL)
val = Tables->TheCurves[i]->Table16[j]; val = Tables->TheCurves[i]->Table16[j];
else
val = _cmsQuantizeVal(j, nEntries);
if (!_cmsWriteUInt16Number(io, val)) return FALSE; if (!_cmsWriteUInt16Number(io, val)) return FALSE;
} }
} }
...@@ -2057,7 +2056,6 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm ...@@ -2057,7 +2056,6 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
{ {
cmsUInt8Number InputChannels, OutputChannels, CLUTpoints; cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
cmsPipeline* NewLUT = NULL; cmsPipeline* NewLUT = NULL;
cmsStage *mpemat, *mpeclut;
cmsUInt32Number nTabSize; cmsUInt32Number nTabSize;
cmsFloat64Number Matrix[3*3]; cmsFloat64Number Matrix[3*3];
cmsUInt16Number InputEntries, OutputEntries; cmsUInt16Number InputEntries, OutputEntries;
...@@ -2094,9 +2092,8 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm ...@@ -2094,9 +2092,8 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
// Only operates on 3 channels // Only operates on 3 channels
if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) { if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {
mpemat = cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL)))
if (mpemat == NULL) goto Error; goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpemat);
} }
if (!_cmsReadUInt16Number(io, &InputEntries)) goto Error; if (!_cmsReadUInt16Number(io, &InputEntries)) goto Error;
...@@ -2110,7 +2107,7 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm ...@@ -2110,7 +2107,7 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
// Get 3D CLUT // Get 3D CLUT
nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels); nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels);
if (nTabSize == (size_t) -1) goto Error; if (nTabSize == (cmsUInt32Number) -1) goto Error;
if (nTabSize > 0) { if (nTabSize > 0) {
cmsUInt16Number *T; cmsUInt16Number *T;
...@@ -2123,13 +2120,10 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm ...@@ -2123,13 +2120,10 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
goto Error; goto Error;
} }
mpeclut = cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) {
if (mpeclut == NULL) {
_cmsFree(self ->ContextID, T); _cmsFree(self ->ContextID, T);
goto Error; goto Error;
} }
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpeclut);
_cmsFree(self ->ContextID, T); _cmsFree(self ->ContextID, T);
} }
...@@ -2159,7 +2153,7 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io ...@@ -2159,7 +2153,7 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io
_cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL; _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
_cmsStageMatrixData* MatMPE = NULL; _cmsStageMatrixData* MatMPE = NULL;
_cmsStageCLutData* clut = NULL; _cmsStageCLutData* clut = NULL;
int InputChannels, OutputChannels, clutPoints; int i, InputChannels, OutputChannels, clutPoints;
// Disassemble the LUT into components. // Disassemble the LUT into components.
mpe = NewLUT -> Elements; mpe = NewLUT -> Elements;
...@@ -2234,13 +2228,13 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io ...@@ -2234,13 +2228,13 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io
if (PreMPE != NULL) { if (PreMPE != NULL) {
if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PreMPE ->TheCurves[0]->nEntries)) return FALSE; if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PreMPE ->TheCurves[0]->nEntries)) return FALSE;
} else { } else {
if (!_cmsWriteUInt16Number(io, 0)) return FALSE; if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
} }
if (PostMPE != NULL) { if (PostMPE != NULL) {
if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PostMPE ->TheCurves[0]->nEntries)) return FALSE; if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PostMPE ->TheCurves[0]->nEntries)) return FALSE;
} else { } else {
if (!_cmsWriteUInt16Number(io, 0)) return FALSE; if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
} }
...@@ -2249,9 +2243,16 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io ...@@ -2249,9 +2243,16 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io
if (PreMPE != NULL) { if (PreMPE != NULL) {
if (!Write16bitTables(self ->ContextID, io, PreMPE)) return FALSE; if (!Write16bitTables(self ->ContextID, io, PreMPE)) return FALSE;
} }
else {
for (i=0; i < InputChannels; i++) {
if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
}
}
nTabSize = uipow(OutputChannels, clutPoints, InputChannels); nTabSize = uipow(OutputChannels, clutPoints, InputChannels);
if (nTabSize == (size_t) -1) return FALSE; if (nTabSize == (cmsUInt32Number) -1) return FALSE;
if (nTabSize > 0) { if (nTabSize > 0) {
// The 3D CLUT. // The 3D CLUT.
if (clut != NULL) { if (clut != NULL) {
...@@ -2263,7 +2264,13 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io ...@@ -2263,7 +2264,13 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io
if (PostMPE != NULL) { if (PostMPE != NULL) {
if (!Write16bitTables(self ->ContextID, io, PostMPE)) return FALSE; if (!Write16bitTables(self ->ContextID, io, PostMPE)) return FALSE;
} }
else {
for (i=0; i < OutputChannels; i++) {
if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
}
}
return TRUE; return TRUE;
...@@ -2479,7 +2486,6 @@ void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c ...@@ -2479,7 +2486,6 @@ void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c
cmsUInt32Number offsetM; // Offset to first "M" curve cmsUInt32Number offsetM; // Offset to first "M" curve
cmsUInt32Number offsetC; // Offset to CLUT cmsUInt32Number offsetC; // Offset to CLUT
cmsUInt32Number offsetA; // Offset to first "A" curve cmsUInt32Number offsetA; // Offset to first "A" curve
cmsStage* mpe;
cmsPipeline* NewLUT = NULL; cmsPipeline* NewLUT = NULL;
...@@ -2501,37 +2507,35 @@ void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c ...@@ -2501,37 +2507,35 @@ void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c
if (NewLUT == NULL) return NULL; if (NewLUT == NULL) return NULL;
if (offsetA!= 0) { if (offsetA!= 0) {
mpe = ReadSetOfCurves(self, io, BaseOffset + offsetA, inputChan); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, inputChan)))
if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; } goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
} }
if (offsetC != 0) { if (offsetC != 0) {
mpe = ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; } goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
} }
if (offsetM != 0) { if (offsetM != 0) {
mpe = ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan)))
if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; } goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
} }
if (offsetMat != 0) { if (offsetMat != 0) {
mpe = ReadMatrix(self, io, BaseOffset + offsetMat); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; } goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
} }
if (offsetB != 0) { if (offsetB != 0) {
mpe = ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan)))
if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; } goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
} }
*nItems = 1; *nItems = 1;
return NewLUT; return NewLUT;
Error:
cmsPipelineFree(NewLUT);
return NULL;
cmsUNUSED_PARAMETER(SizeOfTag); cmsUNUSED_PARAMETER(SizeOfTag);
} }
...@@ -2798,7 +2802,6 @@ void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c ...@@ -2798,7 +2802,6 @@ void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c
cmsUInt32Number offsetM; // Offset to first "M" curve cmsUInt32Number offsetM; // Offset to first "M" curve
cmsUInt32Number offsetC; // Offset to CLUT cmsUInt32Number offsetC; // Offset to CLUT
cmsUInt32Number offsetA; // Offset to first "A" curve cmsUInt32Number offsetA; // Offset to first "A" curve
cmsStage* mpe;
cmsPipeline* NewLUT = NULL; cmsPipeline* NewLUT = NULL;
...@@ -2821,37 +2824,35 @@ void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c ...@@ -2821,37 +2824,35 @@ void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c
if (NewLUT == NULL) return NULL; if (NewLUT == NULL) return NULL;
if (offsetB != 0) { if (offsetB != 0) {
mpe = ReadSetOfCurves(self, io, BaseOffset + offsetB, inputChan); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, inputChan)))
if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; } goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
} }
if (offsetMat != 0) { if (offsetMat != 0) {
mpe = ReadMatrix(self, io, BaseOffset + offsetMat); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; } goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
} }
if (offsetM != 0) { if (offsetM != 0) {
mpe = ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan)))
if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; } goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
} }
if (offsetC != 0) { if (offsetC != 0) {
mpe = ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; } goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
} }
if (offsetA!= 0) { if (offsetA!= 0) {
mpe = ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan)))
if (mpe == NULL) { cmsPipelineFree(NewLUT); return NULL; } goto Error;
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
} }
*nItems = 1; *nItems = 1;
return NewLUT; return NewLUT;
Error:
cmsPipelineFree(NewLUT);
return NULL;
cmsUNUSED_PARAMETER(SizeOfTag); cmsUNUSED_PARAMETER(SizeOfTag);
} }
...@@ -3287,7 +3288,7 @@ void *Type_ProfileSequenceDesc_Read(struct _cms_typehandler_struct* self, cmsIOH ...@@ -3287,7 +3288,7 @@ void *Type_ProfileSequenceDesc_Read(struct _cms_typehandler_struct* self, cmsIOH
SizeOfTag -= sizeof(cmsUInt32Number); SizeOfTag -= sizeof(cmsUInt32Number);
if (!_cmsReadUInt64Number(io, &sec ->attributes)) goto Error; if (!_cmsReadUInt64Number(io, &sec ->attributes)) goto Error;
if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error; if (SizeOfTag < sizeof(cmsUInt64Number)) goto Error;
SizeOfTag -= sizeof(cmsUInt64Number); SizeOfTag -= sizeof(cmsUInt64Number);
if (!_cmsReadUInt32Number(io, (cmsUInt32Number *)&sec ->technology)) goto Error; if (!_cmsReadUInt32Number(io, (cmsUInt32Number *)&sec ->technology)) goto Error;
...@@ -4292,6 +4293,9 @@ void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, ...@@ -4292,6 +4293,9 @@ void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
if (!_cmsReadUInt16Number(io, &InputChans)) return NULL; if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
if (InputChans == 0) goto Error;
if (OutputChans == 0) goto Error;
if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16) if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16)
goto Error; goto Error;
...@@ -4381,7 +4385,6 @@ cmsBool ReadMPEElem(struct _cms_typehandler_struct* self, ...@@ -4381,7 +4385,6 @@ cmsBool ReadMPEElem(struct _cms_typehandler_struct* self,
{ {
cmsStageSignature ElementSig; cmsStageSignature ElementSig;
cmsTagTypeHandler* TypeHandler; cmsTagTypeHandler* TypeHandler;
cmsStage *mpe = NULL;
cmsUInt32Number nItems; cmsUInt32Number nItems;
cmsPipeline *NewLUT = (cmsPipeline *) Cargo; cmsPipeline *NewLUT = (cmsPipeline *) Cargo;
...@@ -4409,11 +4412,8 @@ cmsBool ReadMPEElem(struct _cms_typehandler_struct* self, ...@@ -4409,11 +4412,8 @@ cmsBool ReadMPEElem(struct _cms_typehandler_struct* self,
if (TypeHandler ->ReadPtr != NULL) { if (TypeHandler ->ReadPtr != NULL) {
// This is a real element which should be read and processed // This is a real element which should be read and processed
mpe = (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag); if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag)))
if (mpe == NULL) return FALSE; return FALSE;
// All seems ok, insert element
cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
} }
return TRUE; return TRUE;
...@@ -4479,10 +4479,10 @@ cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, v ...@@ -4479,10 +4479,10 @@ cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, v
outputChan = cmsPipelineOutputChannels(Lut); outputChan = cmsPipelineOutputChannels(Lut);
ElemCount = cmsPipelineStageCount(Lut); ElemCount = cmsPipelineStageCount(Lut);
ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number *)); ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number));
if (ElementOffsets == NULL) goto Error; if (ElementOffsets == NULL) goto Error;
ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number *)); ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number));
if (ElementSizes == NULL) goto Error; if (ElementSizes == NULL) goto Error;
// Write the head // Write the head
...@@ -4825,10 +4825,10 @@ typedef struct { ...@@ -4825,10 +4825,10 @@ typedef struct {
static static
cmsBool AllocElem(cmsContext ContextID, _cmsDICelem* e, cmsUInt32Number Count) cmsBool AllocElem(cmsContext ContextID, _cmsDICelem* e, cmsUInt32Number Count)
{ {
e->Offsets = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number *)); e->Offsets = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number));
if (e->Offsets == NULL) return FALSE; if (e->Offsets == NULL) return FALSE;
e->Sizes = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number *)); e->Sizes = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number));
if (e->Sizes == NULL) { if (e->Sizes == NULL) {
_cmsFree(ContextID, e -> Offsets); _cmsFree(ContextID, e -> Offsets);
...@@ -4844,7 +4844,7 @@ static ...@@ -4844,7 +4844,7 @@ static
void FreeElem(_cmsDICelem* e) void FreeElem(_cmsDICelem* e)
{ {
if (e ->Offsets != NULL) _cmsFree(e -> ContextID, e -> Offsets); if (e ->Offsets != NULL) _cmsFree(e -> ContextID, e -> Offsets);
if (e ->Sizes != NULL) _cmsFree(e -> ContextID, e ->Sizes); if (e ->Sizes != NULL) _cmsFree(e -> ContextID, e -> Sizes);
e->Offsets = e ->Sizes = NULL; e->Offsets = e ->Sizes = NULL;
} }
...@@ -5084,7 +5084,7 @@ void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i ...@@ -5084,7 +5084,7 @@ void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i
if (!_cmsReadUInt32Number(io, &Count)) return NULL; if (!_cmsReadUInt32Number(io, &Count)) return NULL;
SizeOfTag -= sizeof(cmsUInt32Number); SizeOfTag -= sizeof(cmsUInt32Number);
// Get rec lenghth // Get rec length
if (!_cmsReadUInt32Number(io, &Length)) return NULL; if (!_cmsReadUInt32Number(io, &Length)) return NULL;
SizeOfTag -= sizeof(cmsUInt32Number); SizeOfTag -= sizeof(cmsUInt32Number);
...@@ -5118,14 +5118,22 @@ void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i ...@@ -5118,14 +5118,22 @@ void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i
if (!ReadOneMLUC(self, io, &a.DisplayValue, i, &DisplayValueMLU)) goto Error; if (!ReadOneMLUC(self, io, &a.DisplayValue, i, &DisplayValueMLU)) goto Error;
} }
if (NameWCS == NULL || ValueWCS == NULL) {
cmsSignalError(self->ContextID, cmsERROR_CORRUPTION_DETECTED, "Bad dictionary Name/Value");
rc = FALSE;
}
else {
rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU); rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU);
}
if (NameWCS != NULL) _cmsFree(self ->ContextID, NameWCS); if (NameWCS != NULL) _cmsFree(self ->ContextID, NameWCS);
if (ValueWCS != NULL) _cmsFree(self ->ContextID, ValueWCS); if (ValueWCS != NULL) _cmsFree(self ->ContextID, ValueWCS);
if (DisplayNameMLU != NULL) cmsMLUfree(DisplayNameMLU); if (DisplayNameMLU != NULL) cmsMLUfree(DisplayNameMLU);
if (DisplayValueMLU != NULL) cmsMLUfree(DisplayValueMLU); if (DisplayValueMLU != NULL) cmsMLUfree(DisplayValueMLU);
if (!rc) return FALSE; if (!rc) goto Error;
} }
FreeArray(&a); FreeArray(&a);
...@@ -5277,14 +5285,14 @@ static _cmsTagTypeLinkedList SupportedTagTypes[] = { ...@@ -5277,14 +5285,14 @@ static _cmsTagTypeLinkedList SupportedTagTypes[] = {
#define DEFAULT_TAG_TYPE_COUNT (sizeof(SupportedTagTypes) / sizeof(_cmsTagTypeLinkedList)) #define DEFAULT_TAG_TYPE_COUNT (sizeof(SupportedTagTypes) / sizeof(_cmsTagTypeLinkedList))
// Both kind of plug-ins share same structure // Both kind of plug-ins share same structure
cmsBool _cmsRegisterTagTypePlugin(cmsPluginBase* Data) cmsBool _cmsRegisterTagTypePlugin(cmsContext id, cmsPluginBase* Data)
{ {
return RegisterTypesPlugin(Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT); return RegisterTypesPlugin(id, Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT);
} }
cmsBool _cmsRegisterMultiProcessElementPlugin(cmsPluginBase* Data) cmsBool _cmsRegisterMultiProcessElementPlugin(cmsContext id, cmsPluginBase* Data)
{ {
return RegisterTypesPlugin(Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT); return RegisterTypesPlugin(id, Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT);
} }
...@@ -5391,7 +5399,9 @@ static _cmsTagLinkedList SupportedTags[] = { ...@@ -5391,7 +5399,9 @@ static _cmsTagLinkedList SupportedTags[] = {
{ cmsSigScreeningTag, { 1, 1, { cmsSigScreeningType}, NULL }, &SupportedTags[59]}, { cmsSigScreeningTag, { 1, 1, { cmsSigScreeningType}, NULL }, &SupportedTags[59]},
{ cmsSigVcgtTag, { 1, 1, { cmsSigVcgtType}, NULL }, &SupportedTags[60]}, { cmsSigVcgtTag, { 1, 1, { cmsSigVcgtType}, NULL }, &SupportedTags[60]},
{ cmsSigMetaTag, { 1, 1, { cmsSigDictType}, NULL }, &SupportedTags[61]}, { cmsSigMetaTag, { 1, 1, { cmsSigDictType}, NULL }, &SupportedTags[61]},
{ cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL}, NULL} { cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL }, &SupportedTags[62]},
{ cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, NULL}
}; };
...@@ -5406,7 +5416,7 @@ static _cmsTagLinkedList SupportedTags[] = { ...@@ -5406,7 +5416,7 @@ static _cmsTagLinkedList SupportedTags[] = {
#define DEFAULT_TAG_COUNT (sizeof(SupportedTags) / sizeof(_cmsTagLinkedList)) #define DEFAULT_TAG_COUNT (sizeof(SupportedTags) / sizeof(_cmsTagLinkedList))
cmsBool _cmsRegisterTagPlugin(cmsPluginBase* Data) cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data)
{ {
cmsPluginTag* Plugin = (cmsPluginTag*) Data; cmsPluginTag* Plugin = (cmsPluginTag*) Data;
_cmsTagLinkedList *pt, *Anterior; _cmsTagLinkedList *pt, *Anterior;
...@@ -5430,7 +5440,7 @@ cmsBool _cmsRegisterTagPlugin(cmsPluginBase* Data) ...@@ -5430,7 +5440,7 @@ cmsBool _cmsRegisterTagPlugin(cmsPluginBase* Data)
pt = pt ->Next; pt = pt ->Next;
} }
pt = (_cmsTagLinkedList*) _cmsPluginMalloc(sizeof(_cmsTagLinkedList)); pt = (_cmsTagLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagLinkedList));
if (pt == NULL) return FALSE; if (pt == NULL) return FALSE;
pt ->Signature = Plugin ->Signature; pt ->Signature = Plugin ->Signature;
......
...@@ -208,10 +208,27 @@ cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID, ...@@ -208,10 +208,27 @@ cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID,
if (TransferFunction) { if (TransferFunction) {
// Tries to minimize space. Thanks to Richard Hughes for this nice idea
if (!cmsWriteTag(hICC, cmsSigRedTRCTag, (void*) TransferFunction[0])) goto Error; if (!cmsWriteTag(hICC, cmsSigRedTRCTag, (void*) TransferFunction[0])) goto Error;
if (TransferFunction[1] == TransferFunction[0]) {
if (!cmsLinkTag (hICC, cmsSigGreenTRCTag, cmsSigRedTRCTag)) goto Error;
} else {
if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error; if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error;
}
if (TransferFunction[2] == TransferFunction[0]) {
if (!cmsLinkTag (hICC, cmsSigBlueTRCTag, cmsSigRedTRCTag)) goto Error;
} else {
if (!cmsWriteTag(hICC, cmsSigBlueTRCTag, (void*) TransferFunction[2])) goto Error; if (!cmsWriteTag(hICC, cmsSigBlueTRCTag, (void*) TransferFunction[2])) goto Error;
} }
}
if (Primaries) { if (Primaries) {
if (!cmsWriteTag(hICC, cmsSigChromaticityTag, (void*) Primaries)) goto Error; if (!cmsWriteTag(hICC, cmsSigChromaticityTag, (void*) Primaries)) goto Error;
...@@ -303,7 +320,6 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID, ...@@ -303,7 +320,6 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID,
{ {
cmsHPROFILE hICC; cmsHPROFILE hICC;
cmsPipeline* Pipeline; cmsPipeline* Pipeline;
cmsStage* Lin;
int nChannels; int nChannels;
hICC = cmsCreateProfilePlaceholder(ContextID); hICC = cmsCreateProfilePlaceholder(ContextID);
...@@ -327,10 +343,8 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID, ...@@ -327,10 +343,8 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID,
// Copy tables to Pipeline // Copy tables to Pipeline
Lin = cmsStageAllocToneCurves(ContextID, nChannels, TransferFunctions); if (!cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, cmsStageAllocToneCurves(ContextID, nChannels, TransferFunctions)))
if (Lin == NULL) goto Error; goto Error;
cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, Lin);
// Create tags // Create tags
if (!SetTextTags(hICC, L"Linearization built-in")) goto Error; if (!SetTextTags(hICC, L"Linearization built-in")) goto Error;
...@@ -344,6 +358,7 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID, ...@@ -344,6 +358,7 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID,
return hICC; return hICC;
Error: Error:
cmsPipelineFree(Pipeline);
if (hICC) if (hICC)
cmsCloseProfile(hICC); cmsCloseProfile(hICC);
...@@ -451,9 +466,10 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID, ...@@ -451,9 +466,10 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
if (!cmsStageSampleCLut16bit(CLUT, InkLimitingSampler, (void*) &Limit, 0)) goto Error; if (!cmsStageSampleCLut16bit(CLUT, InkLimitingSampler, (void*) &Limit, 0)) goto Error;
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, nChannels)); if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, nChannels)) ||
cmsPipelineInsertStage(LUT, cmsAT_END, CLUT); !cmsPipelineInsertStage(LUT, cmsAT_END, CLUT) ||
cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, nChannels)); !cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, nChannels)))
goto Error;
// Create tags // Create tags
if (!SetTextTags(hICC, L"ink-limiting built-in")) goto Error; if (!SetTextTags(hICC, L"ink-limiting built-in")) goto Error;
...@@ -504,7 +520,8 @@ cmsHPROFILE CMSEXPORT cmsCreateLab2ProfileTHR(cmsContext ContextID, const cmsCIE ...@@ -504,7 +520,8 @@ cmsHPROFILE CMSEXPORT cmsCreateLab2ProfileTHR(cmsContext ContextID, const cmsCIE
LUT = cmsPipelineAlloc(ContextID, 3, 3); LUT = cmsPipelineAlloc(ContextID, 3, 3);
if (LUT == NULL) goto Error; if (LUT == NULL) goto Error;
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3)); if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3)))
goto Error;
if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error; if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
cmsPipelineFree(LUT); cmsPipelineFree(LUT);
...@@ -550,7 +567,8 @@ cmsHPROFILE CMSEXPORT cmsCreateLab4ProfileTHR(cmsContext ContextID, const cmsCIE ...@@ -550,7 +567,8 @@ cmsHPROFILE CMSEXPORT cmsCreateLab4ProfileTHR(cmsContext ContextID, const cmsCIE
LUT = cmsPipelineAlloc(ContextID, 3, 3); LUT = cmsPipelineAlloc(ContextID, 3, 3);
if (LUT == NULL) goto Error; if (LUT == NULL) goto Error;
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3)); if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3)))
goto Error;
if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error; if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
cmsPipelineFree(LUT); cmsPipelineFree(LUT);
...@@ -595,7 +613,8 @@ cmsHPROFILE CMSEXPORT cmsCreateXYZProfileTHR(cmsContext ContextID) ...@@ -595,7 +613,8 @@ cmsHPROFILE CMSEXPORT cmsCreateXYZProfileTHR(cmsContext ContextID)
LUT = cmsPipelineAlloc(ContextID, 3, 3); LUT = cmsPipelineAlloc(ContextID, 3, 3);
if (LUT == NULL) goto Error; if (LUT == NULL) goto Error;
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3)); if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3)))
goto Error;
if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error; if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
cmsPipelineFree(LUT); cmsPipelineFree(LUT);
...@@ -750,7 +769,6 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, ...@@ -750,7 +769,6 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS]; cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
int i; int i;
bchsw.Brightness = Bright; bchsw.Brightness = Bright;
bchsw.Contrast = Contrast; bchsw.Contrast = Contrast;
bchsw.Hue = Hue; bchsw.Hue = Hue;
...@@ -773,7 +791,6 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, ...@@ -773,7 +791,6 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL); cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
// Creates a Pipeline with 3D grid only // Creates a Pipeline with 3D grid only
Pipeline = cmsPipelineAlloc(ContextID, 3, 3); Pipeline = cmsPipelineAlloc(ContextID, 3, 3);
if (Pipeline == NULL) { if (Pipeline == NULL) {
...@@ -789,15 +806,14 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, ...@@ -789,15 +806,14 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) { if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) {
// Shouldn't reach here // Shouldn't reach here
cmsPipelineFree(Pipeline); goto Error;
cmsCloseProfile(hICC);
return NULL;
} }
cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT); if (!cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT)) {
goto Error;
}
// Create tags // Create tags
if (!SetTextTags(hICC, L"BCHS built-in")) return NULL; if (!SetTextTags(hICC, L"BCHS built-in")) return NULL;
cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) cmsD50_XYZ()); cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) cmsD50_XYZ());
...@@ -809,6 +825,11 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, ...@@ -809,6 +825,11 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
// Ok, done // Ok, done
return hICC; return hICC;
Error:
cmsPipelineFree(Pipeline);
cmsCloseProfile(hICC);
return NULL;
} }
...@@ -856,7 +877,8 @@ cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID) ...@@ -856,7 +877,8 @@ cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID)
PostLin = cmsStageAllocToneCurves(ContextID, 1, &EmptyTab); PostLin = cmsStageAllocToneCurves(ContextID, 1, &EmptyTab);
cmsFreeToneCurve(EmptyTab); cmsFreeToneCurve(EmptyTab);
cmsPipelineInsertStage(LUT, cmsAT_END, PostLin); if (!cmsPipelineInsertStage(LUT, cmsAT_END, PostLin))
goto Error;
if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, (void*) LUT)) goto Error; if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, (void*) LUT)) goto Error;
if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error; if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error;
...@@ -999,6 +1021,7 @@ static const cmsAllowedLUT AllowedLUTTypes[] = { ...@@ -999,6 +1021,7 @@ static const cmsAllowedLUT AllowedLUTTypes[] = {
{ FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, { FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
{ FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, { FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
{ FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}},
{ TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }}, { TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }},
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } }, { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } },
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } }, { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } },
...@@ -1059,6 +1082,7 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat ...@@ -1059,6 +1082,7 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
cmsContext ContextID = cmsGetTransformContextID(hTransform); cmsContext ContextID = cmsGetTransformContextID(hTransform);
const cmsAllowedLUT* AllowedLUT; const cmsAllowedLUT* AllowedLUT;
cmsTagSignature DestinationTag; cmsTagSignature DestinationTag;
cmsProfileClassSignature deviceClass;
_cmsAssert(hTransform != NULL); _cmsAssert(hTransform != NULL);
...@@ -1080,13 +1104,15 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat ...@@ -1080,13 +1104,15 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
// Time to fix the Lab2/Lab4 issue. // Time to fix the Lab2/Lab4 issue.
if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) { if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) {
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID)); if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID)))
goto Error;
} }
// On the output side too // On the output side too
if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) { if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) {
cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID)); if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID)))
goto Error;
} }
...@@ -1108,8 +1134,9 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat ...@@ -1108,8 +1134,9 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
FrmIn = COLORSPACE_SH(ColorSpaceBitsIn) | CHANNELS_SH(ChansIn)|BYTES_SH(2); FrmIn = COLORSPACE_SH(ColorSpaceBitsIn) | CHANNELS_SH(ChansIn)|BYTES_SH(2);
FrmOut = COLORSPACE_SH(ColorSpaceBitsOut) | CHANNELS_SH(ChansOut)|BYTES_SH(2); FrmOut = COLORSPACE_SH(ColorSpaceBitsOut) | CHANNELS_SH(ChansOut)|BYTES_SH(2);
deviceClass = cmsGetDeviceClass(hProfile);
if (cmsGetDeviceClass(hProfile) == cmsSigOutputClass) if (deviceClass == cmsSigOutputClass)
DestinationTag = cmsSigBToA0Tag; DestinationTag = cmsSigBToA0Tag;
else else
DestinationTag = cmsSigAToB0Tag; DestinationTag = cmsSigAToB0Tag;
...@@ -1136,10 +1163,12 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat ...@@ -1136,10 +1163,12 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
// Put identity curves if needed // Put identity curves if needed
if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType) if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType)
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn)); if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn)))
goto Error;
if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType) if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType)
cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut)); if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut)))
goto Error;
AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);
} }
...@@ -1168,10 +1197,22 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat ...@@ -1168,10 +1197,22 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
if (!cmsWriteTag(hProfile, cmsSigColorantTableOutTag, xform->OutputColorant)) goto Error; if (!cmsWriteTag(hProfile, cmsSigColorantTableOutTag, xform->OutputColorant)) goto Error;
} }
if (xform ->Sequence != NULL) { if ((deviceClass == cmsSigLinkClass) && (xform ->Sequence != NULL)) {
if (!_cmsWriteProfileSequence(hProfile, xform ->Sequence)) goto Error; if (!_cmsWriteProfileSequence(hProfile, xform ->Sequence)) goto Error;
} }
// Set the white point
if (deviceClass == cmsSigInputClass) {
if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->EntryWhitePoint)) goto Error;
}
else {
if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->ExitWhitePoint)) goto Error;
}
// Per 7.2.15 in spec 4.3
cmsSetHeaderRenderingIntent(hProfile, xform ->RenderingIntent);
cmsPipelineFree(LUT); cmsPipelineFree(LUT);
return hProfile; return hProfile;
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// //
// Little Color Management System // Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer // Copyright (c) 1998-2012 Marti Maria Saguer
// //
// Permission is hereby granted, free of charge, to any person obtaining // Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"), // a copy of this software and associated documentation files (the "Software"),
......
...@@ -396,7 +396,7 @@ typedef struct _cmsTransformCollection_st { ...@@ -396,7 +396,7 @@ typedef struct _cmsTransformCollection_st {
static _cmsTransformCollection* TransformCollection = NULL; static _cmsTransformCollection* TransformCollection = NULL;
// Register new ways to transform // Register new ways to transform
cmsBool _cmsRegisterTransformPlugin(cmsPluginBase* Data) cmsBool _cmsRegisterTransformPlugin(cmsContext id, cmsPluginBase* Data)
{ {
cmsPluginTransform* Plugin = (cmsPluginTransform*) Data; cmsPluginTransform* Plugin = (cmsPluginTransform*) Data;
_cmsTransformCollection* fl; _cmsTransformCollection* fl;
...@@ -412,7 +412,7 @@ cmsBool _cmsRegisterTransformPlugin(cmsPluginBase* Data) ...@@ -412,7 +412,7 @@ cmsBool _cmsRegisterTransformPlugin(cmsPluginBase* Data)
if (Plugin ->Factory == NULL) return FALSE; if (Plugin ->Factory == NULL) return FALSE;
fl = (_cmsTransformCollection*) _cmsPluginMalloc(sizeof(_cmsTransformCollection)); fl = (_cmsTransformCollection*) _cmsPluginMalloc(id, sizeof(_cmsTransformCollection));
if (fl == NULL) return FALSE; if (fl == NULL) return FALSE;
// Copy the parameters // Copy the parameters
...@@ -651,6 +651,22 @@ cmsBool IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwForm ...@@ -651,6 +651,22 @@ cmsBool IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwForm
// ---------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------
static
void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src)
{
if (src == NULL) {
wtPt ->X = cmsD50X;
wtPt ->Y = cmsD50Y;
wtPt ->Z = cmsD50Z;
}
else {
wtPt ->X = src->X;
wtPt ->Y = src->Y;
wtPt ->Z = src->Z;
}
}
// New to lcms 2.0 -- have all parameters available. // New to lcms 2.0 -- have all parameters available.
cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[],
...@@ -664,7 +680,6 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, ...@@ -664,7 +680,6 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
cmsUInt32Number dwFlags) cmsUInt32Number dwFlags)
{ {
_cmsTRANSFORM* xform; _cmsTRANSFORM* xform;
cmsBool FloatTransform;
cmsColorSpaceSignature EntryColorSpace; cmsColorSpaceSignature EntryColorSpace;
cmsColorSpaceSignature ExitColorSpace; cmsColorSpaceSignature ExitColorSpace;
cmsPipeline* Lut; cmsPipeline* Lut;
...@@ -681,9 +696,7 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, ...@@ -681,9 +696,7 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK; if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK;
} }
// On floating point transforms, inhibit optimizations // On floating point transforms, inhibit cache
FloatTransform = (_cmsFormatterIsFloat(InputFormat) && _cmsFormatterIsFloat(OutputFormat));
if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat)) if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat))
dwFlags |= cmsFLAGS_NOCACHE; dwFlags |= cmsFLAGS_NOCACHE;
...@@ -730,6 +743,10 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, ...@@ -730,6 +743,10 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
xform ->ExitColorSpace = ExitColorSpace; xform ->ExitColorSpace = ExitColorSpace;
xform ->RenderingIntent = Intents[nProfiles-1]; xform ->RenderingIntent = Intents[nProfiles-1];
// Take white points
SetWhitePoint(&xform->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[0], cmsSigMediaWhitePointTag));
SetWhitePoint(&xform->ExitWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[nProfiles-1], cmsSigMediaWhitePointTag));
// Create a gamut check LUT if requested // Create a gamut check LUT if requested
if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK)) if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK))
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// //
// Little Color Management System // Little Color Management System
// Copyright (c) 1998-2011 Marti Maria Saguer // Copyright (c) 1998-2013 Marti Maria Saguer
// //
// Permission is hereby granted, free of charge, to any person obtaining // Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"), // a copy of this software and associated documentation files (the "Software"),
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
// //
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// //
// Version 2.4 // Version 2.5
// //
#ifndef _lcms2_H #ifndef _lcms2_H
...@@ -101,7 +101,7 @@ extern "C" { ...@@ -101,7 +101,7 @@ extern "C" {
#endif #endif
// Version/release // Version/release
#define LCMS_VERSION 2040 #define LCMS_VERSION 2050
// I will give the chance of redefining basic types for compilers that are not fully C99 compliant // I will give the chance of redefining basic types for compilers that are not fully C99 compliant
#ifndef CMS_BASIC_TYPES_ALREADY_DEFINED #ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
...@@ -367,6 +367,7 @@ typedef enum { ...@@ -367,6 +367,7 @@ typedef enum {
cmsSigPreview1Tag = 0x70726531, // 'pre1' cmsSigPreview1Tag = 0x70726531, // 'pre1'
cmsSigPreview2Tag = 0x70726532, // 'pre2' cmsSigPreview2Tag = 0x70726532, // 'pre2'
cmsSigProfileDescriptionTag = 0x64657363, // 'desc' cmsSigProfileDescriptionTag = 0x64657363, // 'desc'
cmsSigProfileDescriptionMLTag = 0x6473636d, // 'dscm'
cmsSigProfileSequenceDescTag = 0x70736571, // 'pseq' cmsSigProfileSequenceDescTag = 0x70736571, // 'pseq'
cmsSigProfileSequenceIdTag = 0x70736964, // 'psid' cmsSigProfileSequenceIdTag = 0x70736964, // 'psid'
cmsSigPs2CRD0Tag = 0x70736430, // 'psd0' cmsSigPs2CRD0Tag = 0x70736430, // 'psd0'
...@@ -1014,6 +1015,7 @@ CMSAPI long int CMSEXPORT cmsfilelength(FILE* f); ...@@ -1014,6 +1015,7 @@ CMSAPI long int CMSEXPORT cmsfilelength(FILE* f);
// Plug-In registering --------------------------------------------------------------------------------------------------- // Plug-In registering ---------------------------------------------------------------------------------------------------
CMSAPI cmsBool CMSEXPORT cmsPlugin(void* Plugin); CMSAPI cmsBool CMSEXPORT cmsPlugin(void* Plugin);
CMSAPI cmsBool CMSEXPORT cmsPluginTHR(cmsContext ContextID, void* Plugin);
CMSAPI void CMSEXPORT cmsUnregisterPlugins(void); CMSAPI void CMSEXPORT cmsUnregisterPlugins(void);
// Error logging ---------------------------------------------------------------------------------------------------------- // Error logging ----------------------------------------------------------------------------------------------------------
...@@ -1190,7 +1192,7 @@ CMSAPI cmsBool CMSEXPORT cmsPipelineSetSaveAs8bitsFlag(cmsPipeline* lu ...@@ -1190,7 +1192,7 @@ CMSAPI cmsBool CMSEXPORT cmsPipelineSetSaveAs8bitsFlag(cmsPipeline* lu
// Where to place/locate the stages in the pipeline chain // Where to place/locate the stages in the pipeline chain
typedef enum { cmsAT_BEGIN, cmsAT_END } cmsStageLoc; typedef enum { cmsAT_BEGIN, cmsAT_END } cmsStageLoc;
CMSAPI void CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe); CMSAPI int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe);
CMSAPI void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe); CMSAPI void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe);
// This function is quite useful to analyze the structure of a Pipeline and retrieve the Stage elements // This function is quite useful to analyze the structure of a Pipeline and retrieve the Stage elements
...@@ -1274,6 +1276,13 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu, ...@@ -1274,6 +1276,13 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
const char LanguageCode[3], const char CountryCode[3], const char LanguageCode[3], const char CountryCode[3],
char ObtainedLanguage[3], char ObtainedCountry[3]); char ObtainedLanguage[3], char ObtainedCountry[3]);
CMSAPI cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu);
CMSAPI cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu,
cmsUInt32Number idx,
char LanguageCode[3],
char CountryCode[3]);
// Undercolorremoval & black generation ------------------------------------------------------------------------------------- // Undercolorremoval & black generation -------------------------------------------------------------------------------------
typedef struct { typedef struct {
...@@ -1424,6 +1433,7 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderRenderingIntent(cmsHPROFILE hProf ...@@ -1424,6 +1433,7 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderRenderingIntent(cmsHPROFILE hProf
CMSAPI void CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags); CMSAPI void CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags);
CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile); CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile);
CMSAPI void CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer); CMSAPI void CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer);
CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderCreator(cmsHPROFILE hProfile);
CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile); CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile);
CMSAPI void CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model); CMSAPI void CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model);
CMSAPI void CMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number Flags); CMSAPI void CMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number Flags);
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
// However, the following notice accompanied the original version of this // However, the following notice accompanied the original version of this
// file: // file:
// //
//---------------------------------------------------------------------------------
// //
// Little Color Management System // Little Color Management System
// Copyright (c) 1998-2011 Marti Maria Saguer // Copyright (c) 1998-2011 Marti Maria Saguer
...@@ -196,7 +196,7 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d) ...@@ -196,7 +196,7 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d)
// Plug-In registering --------------------------------------------------------------- // Plug-In registering ---------------------------------------------------------------
// Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once. // Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once.
void* _cmsPluginMalloc(cmsUInt32Number size); void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size);
// Memory management // Memory management
cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin); cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
...@@ -205,28 +205,28 @@ cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin); ...@@ -205,28 +205,28 @@ cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Plugin); cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Plugin);
// Parametric curves // Parametric curves
cmsBool _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Plugin); cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Formatters management // Formatters management
cmsBool _cmsRegisterFormattersPlugin(cmsPluginBase* Plugin); cmsBool _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Tag type management // Tag type management
cmsBool _cmsRegisterTagTypePlugin(cmsPluginBase* Plugin); cmsBool _cmsRegisterTagTypePlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Tag management // Tag management
cmsBool _cmsRegisterTagPlugin(cmsPluginBase* Plugin); cmsBool _cmsRegisterTagPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Intent management // Intent management
cmsBool _cmsRegisterRenderingIntentPlugin(cmsPluginBase* Plugin); cmsBool _cmsRegisterRenderingIntentPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Multi Process elements // Multi Process elements
cmsBool _cmsRegisterMultiProcessElementPlugin(cmsPluginBase* Plugin); cmsBool _cmsRegisterMultiProcessElementPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Optimization // Optimization
cmsBool _cmsRegisterOptimizationPlugin(cmsPluginBase* Plugin); cmsBool _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Transform // Transform
cmsBool _cmsRegisterTransformPlugin(cmsPluginBase* Plugin); cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// --------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------
...@@ -263,7 +263,7 @@ typedef struct { ...@@ -263,7 +263,7 @@ typedef struct {
cmsUInt16Number Country; cmsUInt16Number Country;
cmsUInt32Number StrW; // Offset to current unicode string cmsUInt32Number StrW; // Offset to current unicode string
cmsUInt32Number Len; // Lenght in bytes cmsUInt32Number Len; // Length in bytes
} _cmsMLUentry; } _cmsMLUentry;
...@@ -330,9 +330,11 @@ typedef struct _cms_iccprofile_struct { ...@@ -330,9 +330,11 @@ typedef struct _cms_iccprofile_struct {
cmsColorSpaceSignature ColorSpace; cmsColorSpaceSignature ColorSpace;
cmsColorSpaceSignature PCS; cmsColorSpaceSignature PCS;
cmsUInt32Number RenderingIntent; cmsUInt32Number RenderingIntent;
cmsUInt32Number flags; cmsUInt32Number flags;
cmsUInt32Number manufacturer, model; cmsUInt32Number manufacturer, model;
cmsUInt64Number attributes; cmsUInt64Number attributes;
cmsUInt32Number creator;
cmsProfileID ProfileID; cmsProfileID ProfileID;
...@@ -585,6 +587,10 @@ typedef struct _cmstransform_struct { ...@@ -585,6 +587,10 @@ typedef struct _cmstransform_struct {
cmsColorSpaceSignature EntryColorSpace; cmsColorSpaceSignature EntryColorSpace;
cmsColorSpaceSignature ExitColorSpace; cmsColorSpaceSignature ExitColorSpace;
// White points (informative only)
cmsCIEXYZ EntryWhitePoint;
cmsCIEXYZ ExitWhitePoint;
// Profiles used to create the transform // Profiles used to create the transform
cmsSEQ* Sequence; cmsSEQ* Sequence;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册