提交 6656a101 编写于 作者: P prr

8078331: Upgrade JDK to use LittleCMS 2.7

Reviewed-by: serb, bae
上级 5e414292
...@@ -353,7 +353,7 @@ static const char* PredefinedSampleID[] = { ...@@ -353,7 +353,7 @@ static const char* PredefinedSampleID[] = {
"XYZ_X", // X component of tristimulus data "XYZ_X", // X component of tristimulus data
"XYZ_Y", // Y component of tristimulus data "XYZ_Y", // Y component of tristimulus data
"XYZ_Z", // Z component of tristimulus data "XYZ_Z", // Z component of tristimulus data
"XYY_X" // x component of chromaticity data "XYY_X", // x component of chromaticity data
"XYY_Y", // y component of chromaticity data "XYY_Y", // y component of chromaticity data
"XYY_CAPY", // Y component of tristimulus data "XYY_CAPY", // Y component of tristimulus data
"LAB_L", // L* component of Lab data "LAB_L", // L* component of Lab data
......
...@@ -298,6 +298,8 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState, ...@@ -298,6 +298,8 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState,
{ {
cmsMAT3 Scale, m1, m2, m3, m4; cmsMAT3 Scale, m1, m2, m3, m4;
// TODO: Follow Marc Mahy's recommendation to check if CHAD is same by using M1*M2 == M2*M1. If so, do nothing.
// Adaptation state // Adaptation state
if (AdaptationState == 1.0) { if (AdaptationState == 1.0) {
...@@ -559,7 +561,7 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID, ...@@ -559,7 +561,7 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID,
cmsHPROFILE hProfile; cmsHPROFILE hProfile;
cmsMAT3 m; cmsMAT3 m;
cmsVEC3 off; cmsVEC3 off;
cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut, CurrentColorSpace; cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut = cmsSigLabData, CurrentColorSpace;
cmsProfileClassSignature ClassSig; cmsProfileClassSignature ClassSig;
cmsUInt32Number i, Intent; cmsUInt32Number i, Intent;
...@@ -661,6 +663,22 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID, ...@@ -661,6 +663,22 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID,
CurrentColorSpace = ColorSpaceOut; CurrentColorSpace = ColorSpaceOut;
} }
// Check for non-negatives clip
if (dwFlags & cmsFLAGS_NONEGATIVES) {
if (ColorSpaceOut == cmsSigGrayData ||
ColorSpaceOut == cmsSigRgbData ||
ColorSpaceOut == cmsSigCmykData) {
cmsStage* clip = _cmsStageClipNegatives(Result->ContextID, cmsChannelsOf(ColorSpaceOut));
if (clip == NULL) goto Error;
if (!cmsPipelineInsertStage(Result, cmsAT_END, clip))
goto Error;
}
}
return Result; return Result;
Error: Error:
...@@ -1074,7 +1092,7 @@ cmsPipeline* _cmsLinkProfiles(cmsContext ContextID, ...@@ -1074,7 +1092,7 @@ cmsPipeline* _cmsLinkProfiles(cmsContext ContextID,
if (TheIntents[i] == INTENT_PERCEPTUAL || TheIntents[i] == INTENT_SATURATION) { if (TheIntents[i] == INTENT_PERCEPTUAL || TheIntents[i] == INTENT_SATURATION) {
// Force BPC for V4 profiles in perceptual and saturation // Force BPC for V4 profiles in perceptual and saturation
if (cmsGetProfileVersion(hProfiles[i]) >= 4.0) if (cmsGetEncodedICCversion(hProfiles[i]) >= 0x4000000)
BPC[i] = TRUE; BPC[i] = TRUE;
} }
} }
......
...@@ -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-2015 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"),
...@@ -54,6 +54,13 @@ ...@@ -54,6 +54,13 @@
#include "lcms2_internal.h" #include "lcms2_internal.h"
// This function is here to help applications to prevent mixing lcms versions on header and shared objects.
int CMSEXPORT cmsGetEncodedCMMversion(void)
{
return LCMS_VERSION;
}
// I am so tired about incompatibilities on those functions that here are some replacements // I am so tired about incompatibilities on those functions that here are some replacements
// that hopefully would be fully portable. // that hopefully would be fully portable.
......
...@@ -958,7 +958,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[], ...@@ -958,7 +958,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[],
Rest = c1 * rx + c2 * ry + c3 * rz; Rest = c1 * rx + c2 * ry + c3 * rz;
Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)); Tmp1[OutChan] = (cmsUInt16Number) ( c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
} }
...@@ -1022,7 +1022,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[], ...@@ -1022,7 +1022,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[],
Rest = c1 * rx + c2 * ry + c3 * rz; Rest = c1 * rx + c2 * ry + c3 * rz;
Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)); Tmp2[OutChan] = (cmsUInt16Number) (c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
} }
......
...@@ -482,6 +482,14 @@ cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io) ...@@ -482,6 +482,14 @@ cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io)
// ------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------
cmsIOHANDLER* CMSEXPORT cmsGetProfileIOhandler(cmsHPROFILE hProfile)
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*)hProfile;
if (Icc == NULL) return NULL;
return Icc->IOhandler;
}
// Creates an empty structure holding all required parameters // Creates an empty structure holding all required parameters
cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID) cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID)
{ {
...@@ -651,25 +659,26 @@ cmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig) ...@@ -651,25 +659,26 @@ cmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig)
return _cmsSearchTag(Icc, sig, FALSE) >= 0; return _cmsSearchTag(Icc, sig, FALSE) >= 0;
} }
/*
* Enforces that the profile version is per. spec.
* Operates on the big endian bytes from the profile. // Enforces that the profile version is per. spec.
* Called before converting to platform endianness. // Operates on the big endian bytes from the profile.
* Byte 0 is BCD major version, so max 9. // Called before converting to platform endianness.
* Byte 1 is 2 BCD digits, one per nibble. // Byte 0 is BCD major version, so max 9.
* Reserved bytes 2 & 3 must be 0. // Byte 1 is 2 BCD digits, one per nibble.
*/ // Reserved bytes 2 & 3 must be 0.
static cmsUInt32Number _validatedVersion(cmsUInt32Number DWord) static
cmsUInt32Number _validatedVersion(cmsUInt32Number DWord)
{ {
cmsUInt8Number* pByte = (cmsUInt8Number*)&DWord; cmsUInt8Number* pByte = (cmsUInt8Number*) &DWord;
cmsUInt8Number temp1; cmsUInt8Number temp1;
cmsUInt8Number temp2; cmsUInt8Number temp2;
if (*pByte > 0x09) *pByte = (cmsUInt8Number)9; if (*pByte > 0x09) *pByte = (cmsUInt8Number) 0x09;
temp1 = *(pByte+1) & 0xf0; temp1 = *(pByte+1) & 0xf0;
temp2 = *(pByte+1) & 0x0f; temp2 = *(pByte+1) & 0x0f;
if (temp1 > 0x90) temp1 = 0x90; if (temp1 > 0x90) temp1 = 0x90;
if (temp2 > 9) temp2 = 0x09; if (temp2 > 0x09) temp2 = 0x09;
*(pByte+1) = (cmsUInt8Number)(temp1 | temp2); *(pByte+1) = (cmsUInt8Number)(temp1 | temp2);
*(pByte+2) = (cmsUInt8Number)0; *(pByte+2) = (cmsUInt8Number)0;
*(pByte+3) = (cmsUInt8Number)0; *(pByte+3) = (cmsUInt8Number)0;
...@@ -1167,33 +1176,7 @@ cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void* MemPtr, cmsUInt32Number ...@@ -1167,33 +1176,7 @@ cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void* MemPtr, cmsUInt32Number
return cmsOpenProfileFromMemTHR(NULL, MemPtr, dwSize); return cmsOpenProfileFromMemTHR(NULL, MemPtr, dwSize);
} }
static
cmsBool SanityCheck(_cmsICCPROFILE* profile)
{
cmsIOHANDLER* io;
if (!profile) {
return FALSE;
}
io = profile->IOhandler;
if (!io) {
return FALSE;
}
if (!io->Seek ||
!(io->Seek==NULLSeek || io->Seek==MemorySeek || io->Seek==FileSeek))
{
return FALSE;
}
if (!io->Read ||
!(io->Read==NULLRead || io->Read==MemoryRead || io->Read==FileRead))
{
return FALSE;
}
return TRUE;
}
// Dump tag contents. If the profile is being modified, untouched tags are copied from FileOrig // Dump tag contents. If the profile is being modified, untouched tags are copied from FileOrig
static static
...@@ -1225,7 +1208,7 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig) ...@@ -1225,7 +1208,7 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig)
// Reach here if we are copying a tag from a disk-based ICC profile which has not been modified by user. // Reach here if we are copying a tag from a disk-based ICC profile which has not been modified by user.
// In this case a blind copy of the block data is performed // In this case a blind copy of the block data is performed
if (SanityCheck(FileOrig) && Icc -> TagOffsets[i]) { if (FileOrig != NULL && Icc -> TagOffsets[i]) {
cmsUInt32Number TagSize = FileOrig -> TagSizes[i]; cmsUInt32Number TagSize = FileOrig -> TagSizes[i];
cmsUInt32Number TagOffset = FileOrig -> TagOffsets[i]; cmsUInt32Number TagOffset = FileOrig -> TagOffsets[i];
...@@ -1874,7 +1857,7 @@ Error: ...@@ -1874,7 +1857,7 @@ Error:
// Similar to the anterior. This function allows to write directly to the ICC profile any data, without // Similar to the anterior. This function allows to write directly to the ICC profile any data, without
// checking anything. As a rule, mixing Raw with cooked doesn't work, so writting a tag as raw and then reading // checking anything. As a rule, mixing Raw with cooked doesn't work, so writting a tag as raw and then reading
// it as cooked without serializing does result into an error. If that is wha you want, you will need to dump // it as cooked without serializing does result into an error. If that is what you want, you will need to dump
// the profile to memry or disk and then reopen it. // the profile to memry or disk and then reopen it.
cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size) cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size)
{ {
...@@ -1898,6 +1881,11 @@ cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, cons ...@@ -1898,6 +1881,11 @@ cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, cons
Icc ->TagSizes[i] = Size; Icc ->TagSizes[i] = Size;
_cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
if (Icc->TagPtrs[i] == NULL) {
Icc->TagNames[i] = 0;
return FALSE;
}
return TRUE; return TRUE;
} }
......
...@@ -339,8 +339,8 @@ Error: ...@@ -339,8 +339,8 @@ Error:
cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
{ {
cmsTagTypeSignature OriginalType; cmsTagTypeSignature OriginalType;
cmsTagSignature tag16 = Device2PCS16[Intent]; cmsTagSignature tag16;
cmsTagSignature tagFloat = Device2PCSFloat[Intent]; cmsTagSignature tagFloat;
cmsContext ContextID = cmsGetProfileContextID(hProfile); cmsContext ContextID = cmsGetProfileContextID(hProfile);
// On named color, take the appropiate tag // On named color, take the appropiate tag
...@@ -369,6 +369,9 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) ...@@ -369,6 +369,9 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
// matter other LUT are present and have precedence. Intent = -1 means just this. // matter other LUT are present and have precedence. Intent = -1 means just this.
if (Intent != -1) { if (Intent != -1) {
tag16 = Device2PCS16[Intent];
tagFloat = Device2PCSFloat[Intent];
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
// Floating point LUT are always V4, but the encoding range is no // Floating point LUT are always V4, but the encoding range is no
...@@ -611,13 +614,16 @@ Error: ...@@ -611,13 +614,16 @@ Error:
cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent) cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent)
{ {
cmsTagTypeSignature OriginalType; cmsTagTypeSignature OriginalType;
cmsTagSignature tag16 = PCS2Device16[Intent]; cmsTagSignature tag16;
cmsTagSignature tagFloat = PCS2DeviceFloat[Intent]; cmsTagSignature tagFloat;
cmsContext ContextID = cmsGetProfileContextID(hProfile); cmsContext ContextID = cmsGetProfileContextID(hProfile);
if (Intent != -1) { if (Intent != -1) {
tag16 = PCS2Device16[Intent];
tagFloat = PCS2DeviceFloat[Intent];
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
// Floating point LUT are always V4 // Floating point LUT are always V4
...@@ -935,7 +941,7 @@ cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq) ...@@ -935,7 +941,7 @@ cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq)
{ {
if (!cmsWriteTag(hProfile, cmsSigProfileSequenceDescTag, seq)) return FALSE; if (!cmsWriteTag(hProfile, cmsSigProfileSequenceDescTag, seq)) return FALSE;
if (cmsGetProfileVersion(hProfile) >= 4.0) { if (cmsGetEncodedICCversion(hProfile) >= 0x4000000) {
if (!cmsWriteTag(hProfile, cmsSigProfileSequenceIdTag, seq)) return FALSE; if (!cmsWriteTag(hProfile, cmsSigProfileSequenceIdTag, seq)) return FALSE;
} }
......
...@@ -1154,7 +1154,23 @@ cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID) ...@@ -1154,7 +1154,23 @@ cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID)
return mpe; return mpe;
} }
// Clips values smaller than zero
static
void Clipper(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
{
cmsUInt32Number i;
for (i = 0; i < mpe->InputChannels; i++) {
cmsFloat32Number n = In[i];
Out[i] = n < 0 ? 0 : n;
}
}
cmsStage* _cmsStageClipNegatives(cmsContext ContextID, int nChannels)
{
return _cmsStageAllocPlaceholder(ContextID, cmsSigClipNegativesElemType,
nChannels, nChannels, Clipper, NULL, NULL, NULL);
}
// ******************************************************************************** // ********************************************************************************
// Type cmsSigXYZ2LabElemType // Type cmsSigXYZ2LabElemType
......
...@@ -543,8 +543,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn ...@@ -543,8 +543,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn
v ->nColors = 0; v ->nColors = 0;
v ->ContextID = ContextID; v ->ContextID = ContextID;
while (v -> Allocated < n) while (v -> Allocated < n){
GrowNamedColorList(v); if (!GrowNamedColorList(v)) return NULL;
}
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);
...@@ -573,8 +574,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v) ...@@ -573,8 +574,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v)
if (NewNC == NULL) return NULL; if (NewNC == NULL) return NULL;
// For really large tables we need this // For really large tables we need this
while (NewNC ->Allocated < v ->Allocated) while (NewNC ->Allocated < v ->Allocated){
GrowNamedColorList(NewNC); if (!GrowNamedColorList(NewNC)) return NULL;
}
memmove(NewNC ->Prefix, v ->Prefix, sizeof(v ->Prefix)); memmove(NewNC ->Prefix, v ->Prefix, sizeof(v ->Prefix));
memmove(NewNC ->Suffix, v ->Suffix, sizeof(v ->Suffix)); memmove(NewNC ->Suffix, v ->Suffix, sizeof(v ->Suffix));
......
...@@ -192,6 +192,88 @@ cmsBool _Remove2Op(cmsPipeline* Lut, cmsStageSignature Op1, cmsStageSignature Op ...@@ -192,6 +192,88 @@ cmsBool _Remove2Op(cmsPipeline* Lut, cmsStageSignature Op1, cmsStageSignature Op
return AnyOpt; return AnyOpt;
} }
static
cmsBool CloseEnoughFloat(cmsFloat64Number a, cmsFloat64Number b)
{
return fabs(b - a) < 0.00001f;
}
static
cmsBool isFloatMatrixIdentity(const cmsMAT3* a)
{
cmsMAT3 Identity;
int i, j;
_cmsMAT3identity(&Identity);
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
if (!CloseEnoughFloat(a->v[i].n[j], Identity.v[i].n[j])) return FALSE;
return TRUE;
}
// if two adjacent matrices are found, multiply them.
static
cmsBool _MultiplyMatrix(cmsPipeline* Lut)
{
cmsStage** pt1;
cmsStage** pt2;
cmsStage* chain;
cmsBool AnyOpt = FALSE;
pt1 = &Lut->Elements;
if (*pt1 == NULL) return AnyOpt;
while (*pt1 != NULL) {
pt2 = &((*pt1)->Next);
if (*pt2 == NULL) return AnyOpt;
if ((*pt1)->Implements == cmsSigMatrixElemType && (*pt2)->Implements == cmsSigMatrixElemType) {
// Get both matrices
_cmsStageMatrixData* m1 = (_cmsStageMatrixData*) cmsStageData(*pt1);
_cmsStageMatrixData* m2 = (_cmsStageMatrixData*) cmsStageData(*pt2);
cmsMAT3 res;
// Input offset and output offset should be zero to use this optimization
if (m1->Offset != NULL || m2 ->Offset != NULL ||
cmsStageInputChannels(*pt1) != 3 || cmsStageOutputChannels(*pt1) != 3 ||
cmsStageInputChannels(*pt2) != 3 || cmsStageOutputChannels(*pt2) != 3)
return FALSE;
// Multiply both matrices to get the result
_cmsMAT3per(&res, (cmsMAT3*)m2->Double, (cmsMAT3*)m1->Double);
// Get the next in chain afer the matrices
chain = (*pt2)->Next;
// Remove both matrices
_RemoveElement(pt2);
_RemoveElement(pt1);
// Now what if the result is a plain identity?
if (!isFloatMatrixIdentity(&res)) {
// We can not get rid of full matrix
cmsStage* Multmat = cmsStageAllocMatrix(Lut->ContextID, 3, 3, (const cmsFloat64Number*) &res, NULL);
// Recover the chain
Multmat->Next = chain;
*pt1 = Multmat;
}
AnyOpt = TRUE;
}
else
pt1 = &((*pt1)->Next);
}
return AnyOpt;
}
// Preoptimize just gets rif of no-ops coming paired. Conversion from v2 to v4 followed // Preoptimize just gets rif of no-ops coming paired. Conversion from v2 to v4 followed
// by a v4 to v2 and vice-versa. The elements are then discarded. // by a v4 to v2 and vice-versa. The elements are then discarded.
static static
...@@ -224,6 +306,9 @@ cmsBool PreOptimize(cmsPipeline* Lut) ...@@ -224,6 +306,9 @@ cmsBool PreOptimize(cmsPipeline* Lut)
// Remove float pcs Lab conversions // Remove float pcs Lab conversions
Opt |= _Remove2Op(Lut, cmsSigXYZ2FloatPCS, cmsSigFloatPCS2XYZ); Opt |= _Remove2Op(Lut, cmsSigXYZ2FloatPCS, cmsSigFloatPCS2XYZ);
// Simplify matrix.
Opt |= _MultiplyMatrix(Lut);
if (Opt) AnyOpt = TRUE; if (Opt) AnyOpt = TRUE;
} while (Opt); } while (Opt);
...@@ -280,12 +365,12 @@ static ...@@ -280,12 +365,12 @@ static
void* Prelin16dup(cmsContext ContextID, const void* ptr) void* Prelin16dup(cmsContext ContextID, const void* ptr)
{ {
Prelin16Data* p16 = (Prelin16Data*) ptr; Prelin16Data* p16 = (Prelin16Data*) ptr;
Prelin16Data* Duped = _cmsDupMem(ContextID, p16, sizeof(Prelin16Data)); Prelin16Data* Duped = (Prelin16Data*) _cmsDupMem(ContextID, p16, sizeof(Prelin16Data));
if (Duped == NULL) return NULL; if (Duped == NULL) return NULL;
Duped ->EvalCurveOut16 = _cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16)); Duped->EvalCurveOut16 = (_cmsInterpFn16*) _cmsDupMem(ContextID, p16->EvalCurveOut16, p16->nOutputs * sizeof(_cmsInterpFn16));
Duped ->ParamsCurveOut16 = _cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* )); Duped->ParamsCurveOut16 = (cmsInterpParams**)_cmsDupMem(ContextID, p16->ParamsCurveOut16, p16->nOutputs * sizeof(cmsInterpParams*));
return Duped; return Duped;
} }
...@@ -298,7 +383,7 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID, ...@@ -298,7 +383,7 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID,
int nOutputs, cmsToneCurve** Out ) int nOutputs, cmsToneCurve** Out )
{ {
int i; int i;
Prelin16Data* p16 = _cmsMallocZero(ContextID, sizeof(Prelin16Data)); Prelin16Data* p16 = (Prelin16Data*)_cmsMallocZero(ContextID, sizeof(Prelin16Data));
if (p16 == NULL) return NULL; if (p16 == NULL) return NULL;
p16 ->nInputs = nInputs; p16 ->nInputs = nInputs;
...@@ -787,7 +872,7 @@ Prelin8Data* PrelinOpt8alloc(cmsContext ContextID, const cmsInterpParams* p, cms ...@@ -787,7 +872,7 @@ Prelin8Data* PrelinOpt8alloc(cmsContext ContextID, const cmsInterpParams* p, cms
cmsS15Fixed16Number v1, v2, v3; cmsS15Fixed16Number v1, v2, v3;
Prelin8Data* p8; Prelin8Data* p8;
p8 = _cmsMallocZero(ContextID, sizeof(Prelin8Data)); p8 = (Prelin8Data*)_cmsMallocZero(ContextID, sizeof(Prelin8Data));
if (p8 == NULL) return NULL; if (p8 == NULL) return NULL;
// Since this only works for 8 bit input, values comes always as x * 257, // Since this only works for 8 bit input, values comes always as x * 257,
...@@ -861,7 +946,7 @@ void PrelinEval8(register const cmsUInt16Number Input[], ...@@ -861,7 +946,7 @@ void PrelinEval8(register const cmsUInt16Number Input[],
Prelin8Data* p8 = (Prelin8Data*) D; Prelin8Data* p8 = (Prelin8Data*) D;
register const cmsInterpParams* p = p8 ->p; register const cmsInterpParams* p = p8 ->p;
int TotalOut = p -> nOutputs; int TotalOut = p -> nOutputs;
const cmsUInt16Number* LutTable = p -> Table; const cmsUInt16Number* LutTable = (const cmsUInt16Number*) p->Table;
r = Input[0] >> 8; r = Input[0] >> 8;
g = Input[1] >> 8; g = Input[1] >> 8;
...@@ -1180,15 +1265,15 @@ void CurvesFree(cmsContext ContextID, void* ptr) ...@@ -1180,15 +1265,15 @@ void CurvesFree(cmsContext ContextID, void* ptr)
static static
void* CurvesDup(cmsContext ContextID, const void* ptr) void* CurvesDup(cmsContext ContextID, const void* ptr)
{ {
Curves16Data* Data = _cmsDupMem(ContextID, ptr, sizeof(Curves16Data)); Curves16Data* Data = (Curves16Data*)_cmsDupMem(ContextID, ptr, sizeof(Curves16Data));
int i; int i;
if (Data == NULL) return NULL; if (Data == NULL) return NULL;
Data ->Curves = _cmsDupMem(ContextID, Data ->Curves, Data ->nCurves * sizeof(cmsUInt16Number*)); Data->Curves = (cmsUInt16Number**) _cmsDupMem(ContextID, Data->Curves, Data->nCurves * sizeof(cmsUInt16Number*));
for (i=0; i < Data -> nCurves; i++) { for (i=0; i < Data -> nCurves; i++) {
Data ->Curves[i] = _cmsDupMem(ContextID, Data ->Curves[i], Data -> nElements * sizeof(cmsUInt16Number)); Data->Curves[i] = (cmsUInt16Number*) _cmsDupMem(ContextID, Data->Curves[i], Data->nElements * sizeof(cmsUInt16Number));
} }
return (void*) Data; return (void*) Data;
...@@ -1201,18 +1286,18 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsT ...@@ -1201,18 +1286,18 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsT
int i, j; int i, j;
Curves16Data* c16; Curves16Data* c16;
c16 = _cmsMallocZero(ContextID, sizeof(Curves16Data)); c16 = (Curves16Data*)_cmsMallocZero(ContextID, sizeof(Curves16Data));
if (c16 == NULL) return NULL; if (c16 == NULL) return NULL;
c16 ->nCurves = nCurves; c16 ->nCurves = nCurves;
c16 ->nElements = nElements; c16 ->nElements = nElements;
c16 ->Curves = _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*)); c16->Curves = (cmsUInt16Number**) _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*));
if (c16 ->Curves == NULL) return NULL; if (c16 ->Curves == NULL) return NULL;
for (i=0; i < nCurves; i++) { for (i=0; i < nCurves; i++) {
c16->Curves[i] = _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number)); c16->Curves[i] = (cmsUInt16Number*) _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number));
if (c16->Curves[i] == NULL) { if (c16->Curves[i] == NULL) {
...@@ -1560,17 +1645,15 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c ...@@ -1560,17 +1645,15 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c
} }
// 8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast! // 8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast!
// TODO: Allow a third matrix for abs. colorimetric
static static
cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{ {
cmsStage* Curve1, *Curve2; cmsStage* Curve1, *Curve2;
cmsStage* Matrix1, *Matrix2; cmsStage* Matrix1, *Matrix2;
_cmsStageMatrixData* Data1;
_cmsStageMatrixData* Data2;
cmsMAT3 res; cmsMAT3 res;
cmsBool IdentityMat; cmsBool IdentityMat;
cmsPipeline* Dest, *Src; cmsPipeline* Dest, *Src;
cmsFloat64Number* Offset;
// Only works on RGB to RGB // Only works on RGB to RGB
if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE; if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE;
...@@ -1581,29 +1664,65 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 ...@@ -1581,29 +1664,65 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
// Seems suitable, proceed // Seems suitable, proceed
Src = *Lut; Src = *Lut;
// Check for shaper-matrix-matrix-shaper structure, that is what this optimizer stands for // Check for:
if (!cmsPipelineCheckAndRetreiveStages(Src, 4, //
// shaper-matrix-matrix-shaper
// shaper-matrix-shaper
//
// Both of those constructs are possible (first because abs. colorimetric).
// additionally, In the first case, the input matrix offset should be zero.
IdentityMat = FALSE;
if (cmsPipelineCheckAndRetreiveStages(Src, 4,
cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
&Curve1, &Matrix1, &Matrix2, &Curve2)) return FALSE; &Curve1, &Matrix1, &Matrix2, &Curve2)) {
// Get both matrices // Get both matrices
Data1 = (_cmsStageMatrixData*) cmsStageData(Matrix1); _cmsStageMatrixData* Data1 = (_cmsStageMatrixData*)cmsStageData(Matrix1);
Data2 = (_cmsStageMatrixData*) cmsStageData(Matrix2); _cmsStageMatrixData* Data2 = (_cmsStageMatrixData*)cmsStageData(Matrix2);
// Input offset should be zero // Input offset should be zero
if (Data1 ->Offset != NULL) return FALSE; if (Data1->Offset != NULL) return FALSE;
// Multiply both matrices to get the result // Multiply both matrices to get the result
_cmsMAT3per(&res, (cmsMAT3*) Data2 ->Double, (cmsMAT3*) Data1 ->Double); _cmsMAT3per(&res, (cmsMAT3*)Data2->Double, (cmsMAT3*)Data1->Double);
// Only 2nd matrix has offset, or it is zero
Offset = Data2->Offset;
// Now the result is in res + Data2 -> Offset. Maybe is a plain identity? // Now the result is in res + Data2 -> Offset. Maybe is a plain identity?
IdentityMat = FALSE; if (_cmsMAT3isIdentity(&res) && Offset == NULL) {
if (_cmsMAT3isIdentity(&res) && Data2 ->Offset == NULL) {
// We can get rid of full matrix // We can get rid of full matrix
IdentityMat = TRUE; IdentityMat = TRUE;
} }
}
else {
if (cmsPipelineCheckAndRetreiveStages(Src, 3,
cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
&Curve1, &Matrix1, &Curve2)) {
_cmsStageMatrixData* Data = (_cmsStageMatrixData*)cmsStageData(Matrix1);
// Copy the matrix to our result
memcpy(&res, Data->Double, sizeof(res));
// Preserve the Odffset (may be NULL as a zero offset)
Offset = Data->Offset;
if (_cmsMAT3isIdentity(&res) && Offset == NULL) {
// We can get rid of full matrix
IdentityMat = TRUE;
}
}
else
return FALSE; // Not optimizeable this time
}
// Allocate an empty LUT // Allocate an empty LUT
Dest = cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels); Dest = cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
if (!Dest) return FALSE; if (!Dest) return FALSE;
...@@ -1612,9 +1731,12 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 ...@@ -1612,9 +1731,12 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1))) if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1)))
goto Error; goto Error;
if (!IdentityMat) if (!IdentityMat) {
if (!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, Offset)))
goto Error; goto Error;
}
if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2))) if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2)))
goto Error; goto Error;
...@@ -1632,7 +1754,7 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 ...@@ -1632,7 +1754,7 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
*dwFlags |= cmsFLAGS_NOCACHE; *dwFlags |= cmsFLAGS_NOCACHE;
// Setup the optimizarion routines // Setup the optimizarion routines
SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Data2 ->Offset, mpeC2->TheCurves, OutputFormat); SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat);
} }
cmsPipelineFree(Src); cmsPipelineFree(Src);
......
...@@ -2438,9 +2438,6 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info, ...@@ -2438,9 +2438,6 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info,
((cmsFloat64Number*) output)[i + start] = v; ((cmsFloat64Number*) output)[i + start] = v;
} }
if (!ExtraFirst) {
output += Extra * sizeof(cmsFloat64Number);
}
if (Extra == 0 && SwapFirst) { if (Extra == 0 && SwapFirst) {
...@@ -2451,7 +2448,7 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info, ...@@ -2451,7 +2448,7 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info,
if (T_PLANAR(info -> OutputFormat)) if (T_PLANAR(info -> OutputFormat))
return output + sizeof(cmsFloat64Number); return output + sizeof(cmsFloat64Number);
else else
return output + nChan * sizeof(cmsFloat64Number); return output + (nChan + Extra) * sizeof(cmsFloat64Number);
} }
...@@ -2462,50 +2459,47 @@ cmsUInt8Number* PackFloatFrom16(register _cmsTRANSFORM* info, ...@@ -2462,50 +2459,47 @@ cmsUInt8Number* PackFloatFrom16(register _cmsTRANSFORM* info,
register cmsUInt8Number* output, register cmsUInt8Number* output,
register cmsUInt32Number Stride) register cmsUInt32Number Stride)
{ {
int nChan = T_CHANNELS(info -> OutputFormat); int nChan = T_CHANNELS(info->OutputFormat);
int DoSwap = T_DOSWAP(info ->OutputFormat); int DoSwap = T_DOSWAP(info->OutputFormat);
int Reverse = T_FLAVOR(info ->OutputFormat); int Reverse = T_FLAVOR(info->OutputFormat);
int Extra = T_EXTRA(info -> OutputFormat); int Extra = T_EXTRA(info->OutputFormat);
int SwapFirst = T_SWAPFIRST(info -> OutputFormat); int SwapFirst = T_SWAPFIRST(info->OutputFormat);
int Planar = T_PLANAR(info -> OutputFormat); int Planar = T_PLANAR(info->OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst; int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0; cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0;
cmsFloat64Number v = 0; cmsFloat64Number v = 0;
cmsFloat32Number* swap1 = (cmsFloat32Number*) output; cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
int i, start = 0; int i, start = 0;
if (ExtraFirst) if (ExtraFirst)
start = Extra; start = Extra;
for (i=0; i < nChan; i++) { for (i = 0; i < nChan; i++) {
int index = DoSwap ? (nChan - i - 1) : i; int index = DoSwap ? (nChan - i - 1) : i;
v = (cmsFloat64Number) wOut[index] / maximum; v = (cmsFloat64Number)wOut[index] / maximum;
if (Reverse) if (Reverse)
v = maximum - v; v = maximum - v;
if (Planar) if (Planar)
((cmsFloat32Number*) output)[(i + start ) * Stride]= (cmsFloat32Number) v; ((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v;
else else
((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v; ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
} }
if (!ExtraFirst) {
output += Extra * sizeof(cmsFloat32Number);
}
if (Extra == 0 && SwapFirst) { if (Extra == 0 && SwapFirst) {
memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number)); memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));
*swap1 = (cmsFloat32Number) v; *swap1 = (cmsFloat32Number)v;
} }
if (T_PLANAR(info -> OutputFormat)) if (T_PLANAR(info->OutputFormat))
return output + sizeof(cmsFloat32Number); return output + sizeof(cmsFloat32Number);
else else
return output + nChan * sizeof(cmsFloat32Number); return output + (nChan + Extra) * sizeof(cmsFloat32Number);
} }
...@@ -2518,22 +2512,22 @@ cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info, ...@@ -2518,22 +2512,22 @@ cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info,
cmsUInt8Number* output, cmsUInt8Number* output,
cmsUInt32Number Stride) cmsUInt32Number Stride)
{ {
int nChan = T_CHANNELS(info -> OutputFormat); int nChan = T_CHANNELS(info->OutputFormat);
int DoSwap = T_DOSWAP(info ->OutputFormat); int DoSwap = T_DOSWAP(info->OutputFormat);
int Reverse = T_FLAVOR(info ->OutputFormat); int Reverse = T_FLAVOR(info->OutputFormat);
int Extra = T_EXTRA(info -> OutputFormat); int Extra = T_EXTRA(info->OutputFormat);
int SwapFirst = T_SWAPFIRST(info -> OutputFormat); int SwapFirst = T_SWAPFIRST(info->OutputFormat);
int Planar = T_PLANAR(info -> OutputFormat); int Planar = T_PLANAR(info->OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst; int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0; cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
cmsFloat32Number* swap1 = (cmsFloat32Number*) output; cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
cmsFloat64Number v = 0; cmsFloat64Number v = 0;
int i, start = 0; int i, start = 0;
if (ExtraFirst) if (ExtraFirst)
start = Extra; start = Extra;
for (i=0; i < nChan; i++) { for (i = 0; i < nChan; i++) {
int index = DoSwap ? (nChan - i - 1) : i; int index = DoSwap ? (nChan - i - 1) : i;
...@@ -2543,25 +2537,22 @@ cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info, ...@@ -2543,25 +2537,22 @@ cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info,
v = maximum - v; v = maximum - v;
if (Planar) if (Planar)
((cmsFloat32Number*) output)[(i + start)* Stride]= (cmsFloat32Number) v; ((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v;
else else
((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v; ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
} }
if (!ExtraFirst) {
output += Extra * sizeof(cmsFloat32Number);
}
if (Extra == 0 && SwapFirst) { if (Extra == 0 && SwapFirst) {
memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number)); memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));
*swap1 = (cmsFloat32Number) v; *swap1 = (cmsFloat32Number)v;
} }
if (T_PLANAR(info -> OutputFormat)) if (T_PLANAR(info->OutputFormat))
return output + sizeof(cmsFloat32Number); return output + sizeof(cmsFloat32Number);
else else
return output + nChan * sizeof(cmsFloat32Number); return output + (nChan + Extra) * sizeof(cmsFloat32Number);
} }
static static
...@@ -2570,22 +2561,22 @@ cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info, ...@@ -2570,22 +2561,22 @@ cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info,
cmsUInt8Number* output, cmsUInt8Number* output,
cmsUInt32Number Stride) cmsUInt32Number Stride)
{ {
int nChan = T_CHANNELS(info -> OutputFormat); int nChan = T_CHANNELS(info->OutputFormat);
int DoSwap = T_DOSWAP(info ->OutputFormat); int DoSwap = T_DOSWAP(info->OutputFormat);
int Reverse = T_FLAVOR(info ->OutputFormat); int Reverse = T_FLAVOR(info->OutputFormat);
int Extra = T_EXTRA(info -> OutputFormat); int Extra = T_EXTRA(info->OutputFormat);
int SwapFirst = T_SWAPFIRST(info -> OutputFormat); int SwapFirst = T_SWAPFIRST(info->OutputFormat);
int Planar = T_PLANAR(info -> OutputFormat); int Planar = T_PLANAR(info->OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst; int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0; cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
cmsFloat64Number v = 0; cmsFloat64Number v = 0;
cmsFloat64Number* swap1 = (cmsFloat64Number*) output; cmsFloat64Number* swap1 = (cmsFloat64Number*)output;
int i, start = 0; int i, start = 0;
if (ExtraFirst) if (ExtraFirst)
start = Extra; start = Extra;
for (i=0; i < nChan; i++) { for (i = 0; i < nChan; i++) {
int index = DoSwap ? (nChan - i - 1) : i; int index = DoSwap ? (nChan - i - 1) : i;
...@@ -2595,26 +2586,22 @@ cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info, ...@@ -2595,26 +2586,22 @@ cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info,
v = maximum - v; v = maximum - v;
if (Planar) if (Planar)
((cmsFloat64Number*) output)[(i + start) * Stride] = v; ((cmsFloat64Number*)output)[(i + start) * Stride] = v;
else else
((cmsFloat64Number*) output)[i + start] = v; ((cmsFloat64Number*)output)[i + start] = v;
}
if (!ExtraFirst) {
output += Extra * sizeof(cmsFloat64Number);
} }
if (Extra == 0 && SwapFirst) { if (Extra == 0 && SwapFirst) {
memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number)); memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat64Number));
*swap1 = v; *swap1 = v;
} }
if (T_PLANAR(info -> OutputFormat)) if (T_PLANAR(info->OutputFormat))
return output + sizeof(cmsFloat64Number); return output + sizeof(cmsFloat64Number);
else else
return output + nChan * sizeof(cmsFloat64Number); return output + (nChan + Extra) * sizeof(cmsFloat64Number);
} }
...@@ -2850,50 +2837,47 @@ cmsUInt8Number* PackHalfFrom16(register _cmsTRANSFORM* info, ...@@ -2850,50 +2837,47 @@ cmsUInt8Number* PackHalfFrom16(register _cmsTRANSFORM* info,
register cmsUInt8Number* output, register cmsUInt8Number* output,
register cmsUInt32Number Stride) register cmsUInt32Number Stride)
{ {
int nChan = T_CHANNELS(info -> OutputFormat); int nChan = T_CHANNELS(info->OutputFormat);
int DoSwap = T_DOSWAP(info ->OutputFormat); int DoSwap = T_DOSWAP(info->OutputFormat);
int Reverse = T_FLAVOR(info ->OutputFormat); int Reverse = T_FLAVOR(info->OutputFormat);
int Extra = T_EXTRA(info -> OutputFormat); int Extra = T_EXTRA(info->OutputFormat);
int SwapFirst = T_SWAPFIRST(info -> OutputFormat); int SwapFirst = T_SWAPFIRST(info->OutputFormat);
int Planar = T_PLANAR(info -> OutputFormat); int Planar = T_PLANAR(info->OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst; int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35F : 65535.0F; cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 655.35F : 65535.0F;
cmsFloat32Number v = 0; cmsFloat32Number v = 0;
cmsUInt16Number* swap1 = (cmsUInt16Number*) output; cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
int i, start = 0; int i, start = 0;
if (ExtraFirst) if (ExtraFirst)
start = Extra; start = Extra;
for (i=0; i < nChan; i++) { for (i = 0; i < nChan; i++) {
int index = DoSwap ? (nChan - i - 1) : i; int index = DoSwap ? (nChan - i - 1) : i;
v = (cmsFloat32Number) wOut[index] / maximum; v = (cmsFloat32Number)wOut[index] / maximum;
if (Reverse) if (Reverse)
v = maximum - v; v = maximum - v;
if (Planar) if (Planar)
((cmsUInt16Number*) output)[(i + start ) * Stride]= _cmsFloat2Half(v); ((cmsUInt16Number*)output)[(i + start) * Stride] = _cmsFloat2Half(v);
else else
((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half(v); ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v);
} }
if (!ExtraFirst) {
output += Extra * sizeof(cmsUInt16Number);
}
if (Extra == 0 && SwapFirst) { if (Extra == 0 && SwapFirst) {
memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number)); memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));
*swap1 = _cmsFloat2Half(v); *swap1 = _cmsFloat2Half(v);
} }
if (T_PLANAR(info -> OutputFormat)) if (T_PLANAR(info->OutputFormat))
return output + sizeof(cmsUInt16Number); return output + sizeof(cmsUInt16Number);
else else
return output + nChan * sizeof(cmsUInt16Number); return output + (nChan + Extra) * sizeof(cmsUInt16Number);
} }
...@@ -2904,22 +2888,22 @@ cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info, ...@@ -2904,22 +2888,22 @@ cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info,
cmsUInt8Number* output, cmsUInt8Number* output,
cmsUInt32Number Stride) cmsUInt32Number Stride)
{ {
int nChan = T_CHANNELS(info -> OutputFormat); int nChan = T_CHANNELS(info->OutputFormat);
int DoSwap = T_DOSWAP(info ->OutputFormat); int DoSwap = T_DOSWAP(info->OutputFormat);
int Reverse = T_FLAVOR(info ->OutputFormat); int Reverse = T_FLAVOR(info->OutputFormat);
int Extra = T_EXTRA(info -> OutputFormat); int Extra = T_EXTRA(info->OutputFormat);
int SwapFirst = T_SWAPFIRST(info -> OutputFormat); int SwapFirst = T_SWAPFIRST(info->OutputFormat);
int Planar = T_PLANAR(info -> OutputFormat); int Planar = T_PLANAR(info->OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst; int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0F : 1.0F; cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 100.0F : 1.0F;
cmsUInt16Number* swap1 = (cmsUInt16Number*) output; cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
cmsFloat32Number v = 0; cmsFloat32Number v = 0;
int i, start = 0; int i, start = 0;
if (ExtraFirst) if (ExtraFirst)
start = Extra; start = Extra;
for (i=0; i < nChan; i++) { for (i = 0; i < nChan; i++) {
int index = DoSwap ? (nChan - i - 1) : i; int index = DoSwap ? (nChan - i - 1) : i;
...@@ -2929,25 +2913,22 @@ cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info, ...@@ -2929,25 +2913,22 @@ cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info,
v = maximum - v; v = maximum - v;
if (Planar) if (Planar)
((cmsUInt16Number*) output)[(i + start)* Stride]= _cmsFloat2Half( v ); ((cmsUInt16Number*)output)[(i + start)* Stride] = _cmsFloat2Half(v);
else else
((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half( v ); ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v);
} }
if (!ExtraFirst) {
output += Extra * sizeof(cmsUInt16Number);
}
if (Extra == 0 && SwapFirst) { if (Extra == 0 && SwapFirst) {
memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number)); memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));
*swap1 = (cmsUInt16Number) _cmsFloat2Half( v ); *swap1 = (cmsUInt16Number)_cmsFloat2Half(v);
} }
if (T_PLANAR(info -> OutputFormat)) if (T_PLANAR(info->OutputFormat))
return output + sizeof(cmsUInt16Number); return output + sizeof(cmsUInt16Number);
else else
return output + nChan * sizeof(cmsUInt16Number); return output + (nChan + Extra)* sizeof(cmsUInt16Number);
} }
#endif #endif
......
...@@ -135,6 +135,15 @@ void CMSEXPORT cmsxyY2XYZ(cmsCIEXYZ* Dest, const cmsCIExyY* Source) ...@@ -135,6 +135,15 @@ void CMSEXPORT cmsxyY2XYZ(cmsCIEXYZ* Dest, const cmsCIExyY* Source)
Dest -> Z = ((1 - Source -> x - Source -> y) / Source -> y) * Source -> Y; Dest -> Z = ((1 - Source -> x - Source -> y) / Source -> y) * Source -> Y;
} }
/*
The break point (24/116)^3 = (6/29)^3 is a very small amount of tristimulus
primary (0.008856). Generally, this only happens for
nearly ideal blacks and for some orange / amber colors in transmission mode.
For example, the Z value of the orange turn indicator lamp lens on an
automobile will often be below this value. But the Z does not
contribute to the perceived color directly.
*/
static static
cmsFloat64Number f(cmsFloat64Number t) cmsFloat64Number f(cmsFloat64Number t)
{ {
......
...@@ -712,15 +712,21 @@ struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID) ...@@ -712,15 +712,21 @@ struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID)
// Internal: get the memory area associanted with each context client // Internal: get the memory area associanted with each context client
// Returns the block assigned to the specific zone. // Returns the block assigned to the specific zone. Never return NULL.
void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc) void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc)
{ {
struct _cmsContext_struct* ctx; struct _cmsContext_struct* ctx;
void *ptr; void *ptr;
if (mc < 0 || mc >= MemoryClientMax) { if ((int) mc < 0 || mc >= MemoryClientMax) {
cmsSignalError(ContextID, cmsERROR_RANGE, "Bad context client");
return NULL; cmsSignalError(ContextID, cmsERROR_INTERNAL, "Bad context client -- possible corruption");
// This is catastrophic. Should never reach here
_cmsAssert(0);
// Reverts to global context
return globalContext.chunks[UserPtr];
} }
ctx = _cmsGetContext(ContextID); ctx = _cmsGetContext(ContextID);
...@@ -909,7 +915,7 @@ cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData) ...@@ -909,7 +915,7 @@ cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)
} }
/*
static static
struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id) struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id)
{ {
...@@ -926,6 +932,7 @@ struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id) ...@@ -926,6 +932,7 @@ struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id)
return NULL; // List is empty or only one element! return NULL; // List is empty or only one element!
} }
*/
// Frees any resources associated with the given context, // Frees any resources associated with the given context,
// and destroys the context placeholder. // and destroys the context placeholder.
......
...@@ -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-2014 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"),
...@@ -369,28 +369,7 @@ cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[] ...@@ -369,28 +369,7 @@ cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[]
} }
/*
static
cmsBool IsMonotonic(int n, const cmsFloat64Number Table[])
{
int i;
cmsFloat64Number last;
last = Table[n-1];
for (i = n-2; i >= 0; --i) {
if (Table[i] > last)
return FALSE;
else
last = Table[i];
}
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.
...@@ -515,7 +494,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF ...@@ -515,7 +494,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
// Test for mid range straight (only on relative colorimetric) // Test for mid range straight (only on relative colorimetric)
NearlyStraightMidrange = TRUE; NearlyStraightMidrange = TRUE;
MinL = outRamp[0]; MaxL = outRamp[255]; MinL = outRamp[0]; MaxL = outRamp[255];
if (Intent == INTENT_RELATIVE_COLORIMETRIC) { if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
...@@ -531,7 +509,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF ...@@ -531,7 +509,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
// DestinationBlackPoint shall be the same as initialLab. // DestinationBlackPoint shall be the same as initialLab.
// Otherwise, the DestinationBlackPoint shall be determined // Otherwise, the DestinationBlackPoint shall be determined
// using curve fitting. // using curve fitting.
if (NearlyStraightMidrange) { if (NearlyStraightMidrange) {
cmsLab2XYZ(NULL, BlackPoint, &InitialLab); cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
...@@ -543,14 +520,12 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF ...@@ -543,14 +520,12 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
// curve fitting: 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.
for (l=0; l < 256; l++) { for (l=0; l < 256; l++) {
yRamp[l] = (outRamp[l] - MinL) / (MaxL - MinL); 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
if (Intent == INTENT_RELATIVE_COLORIMETRIC) { if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
lo = 0.1; lo = 0.1;
hi = 0.5; hi = 0.5;
......
...@@ -1718,10 +1718,7 @@ cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number ...@@ -1718,10 +1718,7 @@ cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number
else else
for (j=0; j < 256; j++) { for (j=0; j < 256; j++) {
if (Tables != NULL)
val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]); val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);
else
val = (cmsUInt8Number) j;
if (!_cmsWriteUInt8Number(io, val)) return FALSE; if (!_cmsWriteUInt8Number(io, val)) return FALSE;
} }
......
...@@ -671,7 +671,7 @@ cmsToneCurve* Build_sRGBGamma(cmsContext ContextID) ...@@ -671,7 +671,7 @@ cmsToneCurve* Build_sRGBGamma(cmsContext ContextID)
// Create the ICC virtual profile for sRGB space // Create the ICC virtual profile for sRGB space
cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID) cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID)
{ {
cmsCIExyY D65; cmsCIExyY D65 = { 0.3127, 0.3290, 1.0 };
cmsCIExyYTRIPLE Rec709Primaries = { cmsCIExyYTRIPLE Rec709Primaries = {
{0.6400, 0.3300, 1.0}, {0.6400, 0.3300, 1.0},
{0.3000, 0.6000, 1.0}, {0.3000, 0.6000, 1.0},
...@@ -680,7 +680,7 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID) ...@@ -680,7 +680,7 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID)
cmsToneCurve* Gamma22[3]; cmsToneCurve* Gamma22[3];
cmsHPROFILE hsRGB; cmsHPROFILE hsRGB;
cmsWhitePointFromTemp(&D65, 6504); // cmsWhitePointFromTemp(&D65, 6504);
Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID); Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID);
if (Gamma22[0] == NULL) return NULL; if (Gamma22[0] == NULL) return NULL;
...@@ -708,6 +708,7 @@ typedef struct { ...@@ -708,6 +708,7 @@ typedef struct {
cmsFloat64Number Contrast; cmsFloat64Number Contrast;
cmsFloat64Number Hue; cmsFloat64Number Hue;
cmsFloat64Number Saturation; cmsFloat64Number Saturation;
cmsBool lAdjustWP;
cmsCIEXYZ WPsrc, WPdest; cmsCIEXYZ WPsrc, WPdest;
} BCHSWADJUSTS, *LPBCHSWADJUSTS; } BCHSWADJUSTS, *LPBCHSWADJUSTS;
...@@ -737,9 +738,10 @@ int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number O ...@@ -737,9 +738,10 @@ int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number O
cmsLCh2Lab(&LabOut, &LChOut); cmsLCh2Lab(&LabOut, &LChOut);
// Move white point in Lab // Move white point in Lab
if (bchsw->lAdjustWP) {
cmsLab2XYZ(&bchsw ->WPsrc, &XYZ, &LabOut); cmsLab2XYZ(&bchsw->WPsrc, &XYZ, &LabOut);
cmsXYZ2Lab(&bchsw ->WPdest, &LabOut, &XYZ); cmsXYZ2Lab(&bchsw->WPdest, &LabOut, &XYZ);
}
// Back to encoded // Back to encoded
...@@ -773,18 +775,23 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, ...@@ -773,18 +775,23 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
bchsw.Contrast = Contrast; bchsw.Contrast = Contrast;
bchsw.Hue = Hue; bchsw.Hue = Hue;
bchsw.Saturation = Saturation; bchsw.Saturation = Saturation;
if (TempSrc == TempDest) {
cmsWhitePointFromTemp(&WhitePnt, TempSrc ); bchsw.lAdjustWP = FALSE;
}
else {
bchsw.lAdjustWP = TRUE;
cmsWhitePointFromTemp(&WhitePnt, TempSrc);
cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt); cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
cmsWhitePointFromTemp(&WhitePnt, TempDest); cmsWhitePointFromTemp(&WhitePnt, TempDest);
cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt); cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
}
hICC = cmsCreateProfilePlaceholder(ContextID); hICC = cmsCreateProfilePlaceholder(ContextID);
if (!hICC) // can't allocate if (!hICC) // can't allocate
return NULL; return NULL;
cmsSetDeviceClass(hICC, cmsSigAbstractClass); cmsSetDeviceClass(hICC, cmsSigAbstractClass);
cmsSetColorSpace(hICC, cmsSigLabData); cmsSetColorSpace(hICC, cmsSigLabData);
cmsSetPCS(hICC, cmsSigLabData); cmsSetPCS(hICC, cmsSigLabData);
...@@ -1017,12 +1024,14 @@ typedef struct { ...@@ -1017,12 +1024,14 @@ typedef struct {
} cmsAllowedLUT; } cmsAllowedLUT;
#define cmsSig0 ((cmsTagSignature) 0)
static const cmsAllowedLUT AllowedLUTTypes[] = { static const cmsAllowedLUT AllowedLUTTypes[] = {
{ FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, { FALSE, cmsSig0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } },
{ FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, { FALSE, cmsSig0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } },
{ FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}}, { FALSE, cmsSig0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType } },
{ TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }}, { TRUE, cmsSig0, 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 } },
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 5, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }}, { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 5, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }},
......
...@@ -622,18 +622,20 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, ...@@ -622,18 +622,20 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
_cmsTransformCollection* Plugin; _cmsTransformCollection* Plugin;
// Allocate needed memory // Allocate needed memory
_cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
if (!p) return NULL; if (!p) return NULL;
// Store the proposed pipeline // Store the proposed pipeline
p ->Lut = lut; p->Lut = lut;
// Let's see if any plug-in want to do the transform by itself // Let's see if any plug-in want to do the transform by itself
for (Plugin = ctx ->TransformCollection; if (p->Lut != NULL) {
for (Plugin = ctx->TransformCollection;
Plugin != NULL; Plugin != NULL;
Plugin = Plugin ->Next) { Plugin = Plugin->Next) {
if (Plugin ->Factory(&p->xform, &p->UserData, &p ->FreeUserData, &p ->Lut, InputFormat, OutputFormat, dwFlags)) { if (Plugin->Factory(&p->xform, &p->UserData, &p->FreeUserData, &p->Lut, InputFormat, OutputFormat, dwFlags)) {
// Last plugin in the declaration order takes control. We just keep // Last plugin in the declaration order takes control. We just keep
// the original parameters as a logging. // the original parameters as a logging.
...@@ -641,26 +643,26 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, ...@@ -641,26 +643,26 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
// an optimized transform is not reusable. The plug-in can, however, change // an optimized transform is not reusable. The plug-in can, however, change
// the flags and make it suitable. // the flags and make it suitable.
p ->ContextID = ContextID; p->ContextID = ContextID;
p ->InputFormat = *InputFormat; p->InputFormat = *InputFormat;
p ->OutputFormat = *OutputFormat; p->OutputFormat = *OutputFormat;
p ->dwOriginalFlags = *dwFlags; p->dwOriginalFlags = *dwFlags;
// Fill the formatters just in case the optimized routine is interested. // Fill the formatters just in case the optimized routine is interested.
// No error is thrown if the formatter doesn't exist. It is up to the optimization // No error is thrown if the formatter doesn't exist. It is up to the optimization
// factory to decide what to do in those cases. // factory to decide what to do in those cases.
p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
return p; return p;
} }
} }
// Not suitable for the transform plug-in, let's check the pipeline plug-in // Not suitable for the transform plug-in, let's check the pipeline plug-in
if (p ->Lut != NULL)
_cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags); _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
}
// Check whatever this is a true floating point transform // Check whatever this is a true floating point transform
if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) { if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) {
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
// //
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// //
// Version 2.6 // Version 2.7
// //
#ifndef _lcms2_H #ifndef _lcms2_H
...@@ -104,7 +104,7 @@ extern "C" { ...@@ -104,7 +104,7 @@ extern "C" {
#endif #endif
// Version/release // Version/release
#define LCMS_VERSION 2060 #define LCMS_VERSION 2070
// 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
...@@ -213,25 +213,17 @@ typedef int cmsBool; ...@@ -213,25 +213,17 @@ typedef int cmsBool;
# define CMS_USE_BIG_ENDIAN 1 # define CMS_USE_BIG_ENDIAN 1
#endif #endif
# ifdef TARGET_CPU_PPC
# if TARGET_CPU_PPC
# define CMS_USE_BIG_ENDIAN 1
# endif
# endif
#if defined(__powerpc__) || defined(__ppc__) || defined(TARGET_CPU_PPC) #if defined(__powerpc__) || defined(__ppc__) || defined(TARGET_CPU_PPC)
# if __powerpc__ || __ppc__ || TARGET_CPU_PPC
# define CMS_USE_BIG_ENDIAN 1 # define CMS_USE_BIG_ENDIAN 1
# if defined (__GNUC__) && defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) # if defined (__GNUC__) && defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)
# if __BYTE_ORDER == __LITTLE_ENDIAN # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
// // Don't use big endian for PowerPC little endian mode // Don't use big endian for PowerPC little endian mode
# undef CMS_USE_BIG_ENDIAN # undef CMS_USE_BIG_ENDIAN
# endif # endif
# endif # endif
#endif # endif
// WORDS_BIGENDIAN takes precedence
#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN)
# define CMS_USE_BIG_ENDIAN 1
#endif #endif
#ifdef macintosh #ifdef macintosh
...@@ -243,6 +235,12 @@ typedef int cmsBool; ...@@ -243,6 +235,12 @@ typedef int cmsBool;
# endif # endif
#endif #endif
// WORDS_BIGENDIAN takes precedence
#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN)
# define CMS_USE_BIG_ENDIAN 1
#endif
// Calling convention -- this is hardly platform and compiler dependent // Calling convention -- this is hardly platform and compiler dependent
#ifdef CMS_IS_WINDOWS_ #ifdef CMS_IS_WINDOWS_
# if defined(CMS_DLL) || defined(CMS_DLL_BUILD) # if defined(CMS_DLL) || defined(CMS_DLL_BUILD)
...@@ -553,7 +551,8 @@ typedef enum { ...@@ -553,7 +551,8 @@ typedef enum {
cmsSigLab2FloatPCS = 0x64326C20, // 'd2l ' cmsSigLab2FloatPCS = 0x64326C20, // 'd2l '
cmsSigFloatPCS2Lab = 0x6C326420, // 'l2d ' cmsSigFloatPCS2Lab = 0x6C326420, // 'l2d '
cmsSigXYZ2FloatPCS = 0x64327820, // 'd2x ' cmsSigXYZ2FloatPCS = 0x64327820, // 'd2x '
cmsSigFloatPCS2XYZ = 0x78326420 // 'x2d ' cmsSigFloatPCS2XYZ = 0x78326420, // 'x2d '
cmsSigClipNegativesElemType = 0x636c7020 // 'clp '
} cmsStageSignature; } cmsStageSignature;
...@@ -1031,6 +1030,10 @@ typedef struct { ...@@ -1031,6 +1030,10 @@ typedef struct {
} cmsICCViewingConditions; } cmsICCViewingConditions;
// Get LittleCMS version (for shared objects) -----------------------------------------------------------------------------
CMSAPI int CMSEXPORT cmsGetEncodedCMMversion(void);
// Support of non-standard functions -------------------------------------------------------------------------------------- // Support of non-standard functions --------------------------------------------------------------------------------------
CMSAPI int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2); CMSAPI int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2);
...@@ -1509,7 +1512,7 @@ CMSAPI int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignat ...@@ -1509,7 +1512,7 @@ CMSAPI int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignat
CMSAPI cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace); CMSAPI cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace);
// Build a suitable formatter for the colorspace of this profile // Build a suitable formatter for the colorspace of this profile. nBytes=1 means 8 bits, nBytes=2 means 16 bits.
CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat); CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat);
CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat); CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat);
...@@ -1538,6 +1541,7 @@ CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID ...@@ -1538,6 +1541,7 @@ CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID
CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* Stream); CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* Stream);
CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buffer, cmsUInt32Number size, const char* AccessMode); CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buffer, cmsUInt32Number size, const char* AccessMode);
CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID); CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID);
CMSAPI cmsIOHANDLER* CMSEXPORT cmsGetProfileIOhandler(cmsHPROFILE hProfile);
CMSAPI cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io); CMSAPI cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io);
// MD5 message digest -------------------------------------------------------------------------------------------------- // MD5 message digest --------------------------------------------------------------------------------------------------
...@@ -1672,6 +1676,10 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID ...@@ -1672,6 +1676,10 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID
#define cmsFLAGS_CLUT_POST_LINEARIZATION 0x0001 // create postlinearization tables if possible #define cmsFLAGS_CLUT_POST_LINEARIZATION 0x0001 // create postlinearization tables if possible
#define cmsFLAGS_CLUT_PRE_LINEARIZATION 0x0010 // create prelinearization tables if possible #define cmsFLAGS_CLUT_PRE_LINEARIZATION 0x0010 // create prelinearization tables if possible
// Specific to unbounded mode
#define cmsFLAGS_NONEGATIVES 0x8000 // Prevent negative numbers in floating point transforms
// Fine-tune control over number of gridpoints // Fine-tune control over number of gridpoints
#define cmsFLAGS_GRIDPOINTS(n) (((n) & 0xFF) << 16) #define cmsFLAGS_GRIDPOINTS(n) (((n) & 0xFF) << 16)
......
...@@ -223,11 +223,17 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d) ...@@ -223,11 +223,17 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d)
// Microsoft felt that it was necessary to keep it set at -1 for an unlocked critical // Microsoft felt that it was necessary to keep it set at -1 for an unlocked critical
// section, even when they changed the underlying algorithm to be more scalable. // section, even when they changed the underlying algorithm to be more scalable.
// The final parts of the critical section object are unimportant, and can be set // The final parts of the critical section object are unimportant, and can be set
// to zero for their defaults. This yields an initialization macro: // to zero for their defaults. This yields to an initialization macro:
typedef CRITICAL_SECTION _cmsMutex; typedef CRITICAL_SECTION _cmsMutex;
#define CMS_MUTEX_INITIALIZER {(void*) -1,-1,0,0,0,0} #define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG) -1,-1,0,0,0,0}
#ifdef _MSC_VER
# if (_MSC_VER >= 1800)
# pragma warning(disable : 26135)
# endif
#endif
cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
{ {
...@@ -313,38 +319,38 @@ typedef int _cmsMutex; ...@@ -313,38 +319,38 @@ typedef int _cmsMutex;
cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
{ {
return 0;
cmsUNUSED_PARAMETER(m); cmsUNUSED_PARAMETER(m);
return 0;
} }
cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
{ {
return 0;
cmsUNUSED_PARAMETER(m); cmsUNUSED_PARAMETER(m);
return 0;
} }
cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
{ {
return 0;
cmsUNUSED_PARAMETER(m); cmsUNUSED_PARAMETER(m);
return 0;
} }
cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
{ {
return 0;
cmsUNUSED_PARAMETER(m); cmsUNUSED_PARAMETER(m);
return 0;
} }
cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
{ {
return 0;
cmsUNUSED_PARAMETER(m); cmsUNUSED_PARAMETER(m);
return 0;
} }
cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
{ {
return 0;
cmsUNUSED_PARAMETER(m); cmsUNUSED_PARAMETER(m);
return 0;
} }
#endif #endif
...@@ -852,6 +858,8 @@ cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID); ...@@ -852,6 +858,8 @@ cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID);
cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID); cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID);
cmsStage* _cmsStageNormalizeToLabFloat(cmsContext ContextID); cmsStage* _cmsStageNormalizeToLabFloat(cmsContext ContextID);
cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID); cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID);
cmsStage* _cmsStageClipNegatives(cmsContext ContextID, int nChannels);
// For curve set only // For curve set only
cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe); cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册