8078331: Upgrade JDK to use LittleCMS 2.7
Reviewed-by: serb, bae
This commit is contained in:
parent
e8787ce018
commit
5e68af873f
@ -353,7 +353,7 @@ static const char* PredefinedSampleID[] = {
|
||||
"XYZ_X", // X component of tristimulus data
|
||||
"XYZ_Y", // Y 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_CAPY", // Y component of tristimulus data
|
||||
"LAB_L", // L* component of Lab data
|
||||
@ -2334,7 +2334,6 @@ cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt3
|
||||
|
||||
it8 = (cmsIT8*) hIT8;
|
||||
it8 ->MemoryBlock = (char*) _cmsMalloc(ContextID, len + 1);
|
||||
if (it8 ->MemoryBlock == NULL) return NULL;
|
||||
|
||||
strncpy(it8 ->MemoryBlock, (const char*) Ptr, len);
|
||||
it8 ->MemoryBlock[len] = 0;
|
||||
|
@ -298,6 +298,8 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState,
|
||||
{
|
||||
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
|
||||
if (AdaptationState == 1.0) {
|
||||
|
||||
@ -559,7 +561,7 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID,
|
||||
cmsHPROFILE hProfile;
|
||||
cmsMAT3 m;
|
||||
cmsVEC3 off;
|
||||
cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut, CurrentColorSpace;
|
||||
cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut = cmsSigLabData, CurrentColorSpace;
|
||||
cmsProfileClassSignature ClassSig;
|
||||
cmsUInt32Number i, Intent;
|
||||
|
||||
@ -661,6 +663,22 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID,
|
||||
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;
|
||||
|
||||
Error:
|
||||
@ -1074,7 +1092,7 @@ cmsPipeline* _cmsLinkProfiles(cmsContext ContextID,
|
||||
if (TheIntents[i] == INTENT_PERCEPTUAL || TheIntents[i] == INTENT_SATURATION) {
|
||||
|
||||
// Force BPC for V4 profiles in perceptual and saturation
|
||||
if (cmsGetProfileVersion(hProfiles[i]) >= 4.0)
|
||||
if (cmsGetEncodedICCversion(hProfiles[i]) >= 0x4000000)
|
||||
BPC[i] = TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
//---------------------------------------------------------------------------------
|
||||
//
|
||||
// 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
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
@ -54,6 +54,13 @@
|
||||
|
||||
#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
|
||||
// that hopefully would be fully portable.
|
||||
|
||||
|
@ -958,7 +958,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[],
|
||||
|
||||
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[],
|
||||
|
||||
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)
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID)
|
||||
{
|
||||
@ -651,25 +659,26 @@ cmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig)
|
||||
return _cmsSearchTag(Icc, sig, FALSE) >= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enforces that the profile version is per. spec.
|
||||
* Operates on the big endian bytes from the profile.
|
||||
* Called before converting to platform endianness.
|
||||
* Byte 0 is BCD major version, so max 9.
|
||||
* Byte 1 is 2 BCD digits, one per nibble.
|
||||
* Reserved bytes 2 & 3 must be 0.
|
||||
*/
|
||||
static cmsUInt32Number _validatedVersion(cmsUInt32Number DWord)
|
||||
|
||||
|
||||
// Enforces that the profile version is per. spec.
|
||||
// Operates on the big endian bytes from the profile.
|
||||
// Called before converting to platform endianness.
|
||||
// Byte 0 is BCD major version, so max 9.
|
||||
// Byte 1 is 2 BCD digits, one per nibble.
|
||||
// Reserved bytes 2 & 3 must be 0.
|
||||
static
|
||||
cmsUInt32Number _validatedVersion(cmsUInt32Number DWord)
|
||||
{
|
||||
cmsUInt8Number* pByte = (cmsUInt8Number*)&DWord;
|
||||
cmsUInt8Number* pByte = (cmsUInt8Number*) &DWord;
|
||||
cmsUInt8Number temp1;
|
||||
cmsUInt8Number temp2;
|
||||
|
||||
if (*pByte > 0x09) *pByte = (cmsUInt8Number)9;
|
||||
if (*pByte > 0x09) *pByte = (cmsUInt8Number) 0x09;
|
||||
temp1 = *(pByte+1) & 0xf0;
|
||||
temp2 = *(pByte+1) & 0x0f;
|
||||
if (temp1 > 0x90) temp1 = 0x90;
|
||||
if (temp2 > 9) temp2 = 0x09;
|
||||
if (temp2 > 0x09) temp2 = 0x09;
|
||||
*(pByte+1) = (cmsUInt8Number)(temp1 | temp2);
|
||||
*(pByte+2) = (cmsUInt8Number)0;
|
||||
*(pByte+3) = (cmsUInt8Number)0;
|
||||
@ -1167,6 +1176,8 @@ cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void* MemPtr, cmsUInt32Number
|
||||
return cmsOpenProfileFromMemTHR(NULL, MemPtr, dwSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Dump tag contents. If the profile is being modified, untouched tags are copied from FileOrig
|
||||
static
|
||||
cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig)
|
||||
@ -1197,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.
|
||||
// In this case a blind copy of the block data is performed
|
||||
if (FileOrig != NULL && FileOrig->IOhandler != NULL && Icc -> TagOffsets[i]) {
|
||||
if (FileOrig != NULL && Icc -> TagOffsets[i]) {
|
||||
|
||||
cmsUInt32Number TagSize = FileOrig -> TagSizes[i];
|
||||
cmsUInt32Number TagOffset = FileOrig -> TagOffsets[i];
|
||||
@ -1846,13 +1857,12 @@ Error:
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size)
|
||||
{
|
||||
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
|
||||
int i;
|
||||
cmsBool ret = TRUE;
|
||||
|
||||
if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0;
|
||||
|
||||
@ -1868,11 +1878,15 @@ cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, cons
|
||||
|
||||
// Keep a copy of the block
|
||||
Icc ->TagPtrs[i] = _cmsDupMem(Icc ->ContextID, data, Size);
|
||||
if (!Icc ->TagPtrs[i]) ret = FALSE;
|
||||
Icc ->TagSizes[i] = Size;
|
||||
|
||||
_cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
|
||||
return ret;
|
||||
|
||||
if (Icc->TagPtrs[i] == NULL) {
|
||||
Icc->TagNames[i] = 0;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Using this function you can collapse several tag entries to the same block in the profile
|
||||
|
@ -339,8 +339,8 @@ Error:
|
||||
cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
|
||||
{
|
||||
cmsTagTypeSignature OriginalType;
|
||||
cmsTagSignature tag16 = Device2PCS16[Intent];
|
||||
cmsTagSignature tagFloat = Device2PCSFloat[Intent];
|
||||
cmsTagSignature tag16;
|
||||
cmsTagSignature tagFloat;
|
||||
cmsContext ContextID = cmsGetProfileContextID(hProfile);
|
||||
|
||||
// On named color, take the appropiate tag
|
||||
@ -369,6 +369,9 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
|
||||
// matter other LUT are present and have precedence. Intent = -1 means just this.
|
||||
if (Intent != -1) {
|
||||
|
||||
tag16 = Device2PCS16[Intent];
|
||||
tagFloat = Device2PCSFloat[Intent];
|
||||
|
||||
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
|
||||
|
||||
// Floating point LUT are always V4, but the encoding range is no
|
||||
@ -611,13 +614,16 @@ Error:
|
||||
cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent)
|
||||
{
|
||||
cmsTagTypeSignature OriginalType;
|
||||
cmsTagSignature tag16 = PCS2Device16[Intent];
|
||||
cmsTagSignature tagFloat = PCS2DeviceFloat[Intent];
|
||||
cmsContext ContextID = cmsGetProfileContextID(hProfile);
|
||||
cmsTagSignature tag16;
|
||||
cmsTagSignature tagFloat;
|
||||
cmsContext ContextID = cmsGetProfileContextID(hProfile);
|
||||
|
||||
|
||||
if (Intent != -1) {
|
||||
|
||||
tag16 = PCS2Device16[Intent];
|
||||
tagFloat = PCS2DeviceFloat[Intent];
|
||||
|
||||
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
|
||||
|
||||
// Floating point LUT are always V4
|
||||
@ -935,7 +941,7 @@ cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq)
|
||||
{
|
||||
if (!cmsWriteTag(hProfile, cmsSigProfileSequenceDescTag, seq)) return FALSE;
|
||||
|
||||
if (cmsGetProfileVersion(hProfile) >= 4.0) {
|
||||
if (cmsGetEncodedICCversion(hProfile) >= 0x4000000) {
|
||||
|
||||
if (!cmsWriteTag(hProfile, cmsSigProfileSequenceIdTag, seq)) return FALSE;
|
||||
}
|
||||
|
@ -1154,7 +1154,23 @@ cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID)
|
||||
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
|
||||
|
@ -543,8 +543,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn
|
||||
v ->nColors = 0;
|
||||
v ->ContextID = ContextID;
|
||||
|
||||
while (v -> Allocated < n)
|
||||
GrowNamedColorList(v);
|
||||
while (v -> Allocated < n){
|
||||
if (!GrowNamedColorList(v)) return NULL;
|
||||
}
|
||||
|
||||
strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1);
|
||||
strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix)-1);
|
||||
@ -573,8 +574,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v)
|
||||
if (NewNC == NULL) return NULL;
|
||||
|
||||
// For really large tables we need this
|
||||
while (NewNC ->Allocated < v ->Allocated)
|
||||
GrowNamedColorList(NewNC);
|
||||
while (NewNC ->Allocated < v ->Allocated){
|
||||
if (!GrowNamedColorList(NewNC)) return NULL;
|
||||
}
|
||||
|
||||
memmove(NewNC ->Prefix, v ->Prefix, sizeof(v ->Prefix));
|
||||
memmove(NewNC ->Suffix, v ->Suffix, sizeof(v ->Suffix));
|
||||
|
@ -192,6 +192,88 @@ cmsBool _Remove2Op(cmsPipeline* Lut, cmsStageSignature Op1, cmsStageSignature Op
|
||||
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
|
||||
// by a v4 to v2 and vice-versa. The elements are then discarded.
|
||||
static
|
||||
@ -224,6 +306,9 @@ cmsBool PreOptimize(cmsPipeline* Lut)
|
||||
// Remove float pcs Lab conversions
|
||||
Opt |= _Remove2Op(Lut, cmsSigXYZ2FloatPCS, cmsSigFloatPCS2XYZ);
|
||||
|
||||
// Simplify matrix.
|
||||
Opt |= _MultiplyMatrix(Lut);
|
||||
|
||||
if (Opt) AnyOpt = TRUE;
|
||||
|
||||
} while (Opt);
|
||||
@ -280,12 +365,12 @@ static
|
||||
void* Prelin16dup(cmsContext ContextID, const void* 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;
|
||||
|
||||
Duped ->EvalCurveOut16 = _cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16));
|
||||
Duped ->ParamsCurveOut16 = _cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* ));
|
||||
Duped->EvalCurveOut16 = (_cmsInterpFn16*) _cmsDupMem(ContextID, p16->EvalCurveOut16, p16->nOutputs * sizeof(_cmsInterpFn16));
|
||||
Duped->ParamsCurveOut16 = (cmsInterpParams**)_cmsDupMem(ContextID, p16->ParamsCurveOut16, p16->nOutputs * sizeof(cmsInterpParams*));
|
||||
|
||||
return Duped;
|
||||
}
|
||||
@ -298,7 +383,7 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID,
|
||||
int nOutputs, cmsToneCurve** Out )
|
||||
{
|
||||
int i;
|
||||
Prelin16Data* p16 = _cmsMallocZero(ContextID, sizeof(Prelin16Data));
|
||||
Prelin16Data* p16 = (Prelin16Data*)_cmsMallocZero(ContextID, sizeof(Prelin16Data));
|
||||
if (p16 == NULL) return NULL;
|
||||
|
||||
p16 ->nInputs = nInputs;
|
||||
@ -787,7 +872,7 @@ Prelin8Data* PrelinOpt8alloc(cmsContext ContextID, const cmsInterpParams* p, cms
|
||||
cmsS15Fixed16Number v1, v2, v3;
|
||||
Prelin8Data* p8;
|
||||
|
||||
p8 = _cmsMallocZero(ContextID, sizeof(Prelin8Data));
|
||||
p8 = (Prelin8Data*)_cmsMallocZero(ContextID, sizeof(Prelin8Data));
|
||||
if (p8 == NULL) return NULL;
|
||||
|
||||
// Since this only works for 8 bit input, values comes always as x * 257,
|
||||
@ -861,7 +946,7 @@ void PrelinEval8(register const cmsUInt16Number Input[],
|
||||
Prelin8Data* p8 = (Prelin8Data*) D;
|
||||
register const cmsInterpParams* p = p8 ->p;
|
||||
int TotalOut = p -> nOutputs;
|
||||
const cmsUInt16Number* LutTable = p -> Table;
|
||||
const cmsUInt16Number* LutTable = (const cmsUInt16Number*) p->Table;
|
||||
|
||||
r = Input[0] >> 8;
|
||||
g = Input[1] >> 8;
|
||||
@ -1180,29 +1265,15 @@ void CurvesFree(cmsContext ContextID, void* ptr)
|
||||
static
|
||||
void* CurvesDup(cmsContext ContextID, const void* ptr)
|
||||
{
|
||||
Curves16Data* Data = _cmsDupMem(ContextID, ptr, sizeof(Curves16Data));
|
||||
int i, j;
|
||||
Curves16Data* Data = (Curves16Data*)_cmsDupMem(ContextID, ptr, sizeof(Curves16Data));
|
||||
int i;
|
||||
|
||||
if (Data == NULL) return NULL;
|
||||
|
||||
Data ->Curves = _cmsDupMem(ContextID, Data ->Curves, Data ->nCurves * sizeof(cmsUInt16Number*));
|
||||
if (Data -> Curves == NULL) {
|
||||
_cmsFree(ContextID, Data);
|
||||
return NULL;
|
||||
}
|
||||
Data->Curves = (cmsUInt16Number**) _cmsDupMem(ContextID, Data->Curves, Data->nCurves * sizeof(cmsUInt16Number*));
|
||||
|
||||
for (i=0; i < Data -> nCurves; i++) {
|
||||
Data ->Curves[i] = _cmsDupMem(ContextID, Data ->Curves[i], Data -> nElements * sizeof(cmsUInt16Number));
|
||||
if (Data->Curves[i] == NULL) {
|
||||
|
||||
for (j=0; j < i; j++) {
|
||||
_cmsFree(ContextID, Data->Curves[j]);
|
||||
}
|
||||
_cmsFree(ContextID, Data->Curves);
|
||||
_cmsFree(ContextID, Data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Data->Curves[i] = (cmsUInt16Number*) _cmsDupMem(ContextID, Data->Curves[i], Data->nElements * sizeof(cmsUInt16Number));
|
||||
}
|
||||
|
||||
return (void*) Data;
|
||||
@ -1215,18 +1286,18 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsT
|
||||
int i, j;
|
||||
Curves16Data* c16;
|
||||
|
||||
c16 = _cmsMallocZero(ContextID, sizeof(Curves16Data));
|
||||
c16 = (Curves16Data*)_cmsMallocZero(ContextID, sizeof(Curves16Data));
|
||||
if (c16 == NULL) return NULL;
|
||||
|
||||
c16 ->nCurves = nCurves;
|
||||
c16 ->nElements = nElements;
|
||||
|
||||
c16 ->Curves = _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*));
|
||||
c16->Curves = (cmsUInt16Number**) _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*));
|
||||
if (c16 ->Curves == NULL) return NULL;
|
||||
|
||||
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) {
|
||||
|
||||
@ -1574,49 +1645,83 @@ 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!
|
||||
// TODO: Allow a third matrix for abs. colorimetric
|
||||
static
|
||||
cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
|
||||
{
|
||||
cmsStage* Curve1, *Curve2;
|
||||
cmsStage* Matrix1, *Matrix2;
|
||||
_cmsStageMatrixData* Data1;
|
||||
_cmsStageMatrixData* Data2;
|
||||
cmsMAT3 res;
|
||||
cmsBool IdentityMat;
|
||||
cmsPipeline* Dest, *Src;
|
||||
cmsStage* Curve1, *Curve2;
|
||||
cmsStage* Matrix1, *Matrix2;
|
||||
cmsMAT3 res;
|
||||
cmsBool IdentityMat;
|
||||
cmsPipeline* Dest, *Src;
|
||||
cmsFloat64Number* Offset;
|
||||
|
||||
// Only works on RGB to RGB
|
||||
if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE;
|
||||
// Only works on RGB to RGB
|
||||
if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE;
|
||||
|
||||
// Only works on 8 bit input
|
||||
if (!_cmsFormatterIs8bit(*InputFormat)) return FALSE;
|
||||
// Only works on 8 bit input
|
||||
if (!_cmsFormatterIs8bit(*InputFormat)) return FALSE;
|
||||
|
||||
// Seems suitable, proceed
|
||||
Src = *Lut;
|
||||
// Seems suitable, proceed
|
||||
Src = *Lut;
|
||||
|
||||
// Check for shaper-matrix-matrix-shaper structure, that is what this optimizer stands for
|
||||
if (!cmsPipelineCheckAndRetreiveStages(Src, 4,
|
||||
cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
|
||||
&Curve1, &Matrix1, &Matrix2, &Curve2)) return FALSE;
|
||||
// Check for:
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Get both matrices
|
||||
Data1 = (_cmsStageMatrixData*) cmsStageData(Matrix1);
|
||||
Data2 = (_cmsStageMatrixData*) cmsStageData(Matrix2);
|
||||
IdentityMat = FALSE;
|
||||
if (cmsPipelineCheckAndRetreiveStages(Src, 4,
|
||||
cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
|
||||
&Curve1, &Matrix1, &Matrix2, &Curve2)) {
|
||||
|
||||
// Input offset should be zero
|
||||
if (Data1 ->Offset != NULL) return FALSE;
|
||||
// Get both matrices
|
||||
_cmsStageMatrixData* Data1 = (_cmsStageMatrixData*)cmsStageData(Matrix1);
|
||||
_cmsStageMatrixData* Data2 = (_cmsStageMatrixData*)cmsStageData(Matrix2);
|
||||
|
||||
// Multiply both matrices to get the result
|
||||
_cmsMAT3per(&res, (cmsMAT3*) Data2 ->Double, (cmsMAT3*) Data1 ->Double);
|
||||
// Input offset should be zero
|
||||
if (Data1->Offset != NULL) return FALSE;
|
||||
|
||||
// Now the result is in res + Data2 -> Offset. Maybe is a plain identity?
|
||||
IdentityMat = FALSE;
|
||||
if (_cmsMAT3isIdentity(&res) && Data2 ->Offset == NULL) {
|
||||
// Multiply both matrices to get the result
|
||||
_cmsMAT3per(&res, (cmsMAT3*)Data2->Double, (cmsMAT3*)Data1->Double);
|
||||
|
||||
// We can get rid of full matrix
|
||||
IdentityMat = TRUE;
|
||||
}
|
||||
// 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?
|
||||
if (_cmsMAT3isIdentity(&res) && Offset == NULL) {
|
||||
|
||||
// We can get rid of full matrix
|
||||
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
|
||||
Dest = cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
|
||||
@ -1626,9 +1731,12 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
|
||||
if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1)))
|
||||
goto Error;
|
||||
|
||||
if (!IdentityMat)
|
||||
if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset)))
|
||||
goto Error;
|
||||
if (!IdentityMat) {
|
||||
|
||||
if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest->ContextID, 3, 3, (const cmsFloat64Number*)&res, Offset)))
|
||||
goto Error;
|
||||
}
|
||||
|
||||
if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2)))
|
||||
goto Error;
|
||||
|
||||
@ -1646,7 +1754,7 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
|
||||
*dwFlags |= cmsFLAGS_NOCACHE;
|
||||
|
||||
// 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);
|
||||
|
@ -2438,9 +2438,6 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info,
|
||||
((cmsFloat64Number*) output)[i + start] = v;
|
||||
}
|
||||
|
||||
if (!ExtraFirst) {
|
||||
output += Extra * sizeof(cmsFloat64Number);
|
||||
}
|
||||
|
||||
if (Extra == 0 && SwapFirst) {
|
||||
|
||||
@ -2451,7 +2448,7 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info,
|
||||
if (T_PLANAR(info -> OutputFormat))
|
||||
return output + sizeof(cmsFloat64Number);
|
||||
else
|
||||
return output + nChan * sizeof(cmsFloat64Number);
|
||||
return output + (nChan + Extra) * sizeof(cmsFloat64Number);
|
||||
|
||||
}
|
||||
|
||||
@ -2462,50 +2459,47 @@ cmsUInt8Number* PackFloatFrom16(register _cmsTRANSFORM* info,
|
||||
register cmsUInt8Number* output,
|
||||
register cmsUInt32Number Stride)
|
||||
{
|
||||
int nChan = T_CHANNELS(info -> OutputFormat);
|
||||
int DoSwap = T_DOSWAP(info ->OutputFormat);
|
||||
int Reverse = T_FLAVOR(info ->OutputFormat);
|
||||
int Extra = T_EXTRA(info -> OutputFormat);
|
||||
int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
|
||||
int Planar = T_PLANAR(info -> OutputFormat);
|
||||
int ExtraFirst = DoSwap ^ SwapFirst;
|
||||
cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0;
|
||||
cmsFloat64Number v = 0;
|
||||
cmsFloat32Number* swap1 = (cmsFloat32Number*) output;
|
||||
int i, start = 0;
|
||||
int nChan = T_CHANNELS(info->OutputFormat);
|
||||
int DoSwap = T_DOSWAP(info->OutputFormat);
|
||||
int Reverse = T_FLAVOR(info->OutputFormat);
|
||||
int Extra = T_EXTRA(info->OutputFormat);
|
||||
int SwapFirst = T_SWAPFIRST(info->OutputFormat);
|
||||
int Planar = T_PLANAR(info->OutputFormat);
|
||||
int ExtraFirst = DoSwap ^ SwapFirst;
|
||||
cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0;
|
||||
cmsFloat64Number v = 0;
|
||||
cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
|
||||
int i, start = 0;
|
||||
|
||||
if (ExtraFirst)
|
||||
start = Extra;
|
||||
if (ExtraFirst)
|
||||
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)
|
||||
v = maximum - v;
|
||||
if (Reverse)
|
||||
v = maximum - v;
|
||||
|
||||
if (Planar)
|
||||
((cmsFloat32Number*) output)[(i + start ) * Stride]= (cmsFloat32Number) v;
|
||||
else
|
||||
((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v;
|
||||
}
|
||||
if (Planar)
|
||||
((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v;
|
||||
else
|
||||
((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));
|
||||
*swap1 = (cmsFloat32Number) v;
|
||||
}
|
||||
memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));
|
||||
*swap1 = (cmsFloat32Number)v;
|
||||
}
|
||||
|
||||
if (T_PLANAR(info -> OutputFormat))
|
||||
return output + sizeof(cmsFloat32Number);
|
||||
else
|
||||
return output + nChan * sizeof(cmsFloat32Number);
|
||||
if (T_PLANAR(info->OutputFormat))
|
||||
return output + sizeof(cmsFloat32Number);
|
||||
else
|
||||
return output + (nChan + Extra) * sizeof(cmsFloat32Number);
|
||||
}
|
||||
|
||||
|
||||
@ -2518,50 +2512,47 @@ cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info,
|
||||
cmsUInt8Number* output,
|
||||
cmsUInt32Number Stride)
|
||||
{
|
||||
int nChan = T_CHANNELS(info -> OutputFormat);
|
||||
int DoSwap = T_DOSWAP(info ->OutputFormat);
|
||||
int Reverse = T_FLAVOR(info ->OutputFormat);
|
||||
int Extra = T_EXTRA(info -> OutputFormat);
|
||||
int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
|
||||
int Planar = T_PLANAR(info -> OutputFormat);
|
||||
int ExtraFirst = DoSwap ^ SwapFirst;
|
||||
cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
|
||||
cmsFloat32Number* swap1 = (cmsFloat32Number*) output;
|
||||
cmsFloat64Number v = 0;
|
||||
int i, start = 0;
|
||||
int nChan = T_CHANNELS(info->OutputFormat);
|
||||
int DoSwap = T_DOSWAP(info->OutputFormat);
|
||||
int Reverse = T_FLAVOR(info->OutputFormat);
|
||||
int Extra = T_EXTRA(info->OutputFormat);
|
||||
int SwapFirst = T_SWAPFIRST(info->OutputFormat);
|
||||
int Planar = T_PLANAR(info->OutputFormat);
|
||||
int ExtraFirst = DoSwap ^ SwapFirst;
|
||||
cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
|
||||
cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
|
||||
cmsFloat64Number v = 0;
|
||||
int i, start = 0;
|
||||
|
||||
if (ExtraFirst)
|
||||
start = Extra;
|
||||
if (ExtraFirst)
|
||||
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 = wOut[index] * maximum;
|
||||
v = wOut[index] * maximum;
|
||||
|
||||
if (Reverse)
|
||||
v = maximum - v;
|
||||
if (Reverse)
|
||||
v = maximum - v;
|
||||
|
||||
if (Planar)
|
||||
((cmsFloat32Number*) output)[(i + start)* Stride]= (cmsFloat32Number) v;
|
||||
else
|
||||
((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v;
|
||||
}
|
||||
if (Planar)
|
||||
((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v;
|
||||
else
|
||||
((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));
|
||||
*swap1 = (cmsFloat32Number) v;
|
||||
}
|
||||
memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));
|
||||
*swap1 = (cmsFloat32Number)v;
|
||||
}
|
||||
|
||||
if (T_PLANAR(info -> OutputFormat))
|
||||
return output + sizeof(cmsFloat32Number);
|
||||
else
|
||||
return output + nChan * sizeof(cmsFloat32Number);
|
||||
if (T_PLANAR(info->OutputFormat))
|
||||
return output + sizeof(cmsFloat32Number);
|
||||
else
|
||||
return output + (nChan + Extra) * sizeof(cmsFloat32Number);
|
||||
}
|
||||
|
||||
static
|
||||
@ -2570,51 +2561,47 @@ cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info,
|
||||
cmsUInt8Number* output,
|
||||
cmsUInt32Number Stride)
|
||||
{
|
||||
int nChan = T_CHANNELS(info -> OutputFormat);
|
||||
int DoSwap = T_DOSWAP(info ->OutputFormat);
|
||||
int Reverse = T_FLAVOR(info ->OutputFormat);
|
||||
int Extra = T_EXTRA(info -> OutputFormat);
|
||||
int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
|
||||
int Planar = T_PLANAR(info -> OutputFormat);
|
||||
int ExtraFirst = DoSwap ^ SwapFirst;
|
||||
cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
|
||||
cmsFloat64Number v = 0;
|
||||
cmsFloat64Number* swap1 = (cmsFloat64Number*) output;
|
||||
int i, start = 0;
|
||||
int nChan = T_CHANNELS(info->OutputFormat);
|
||||
int DoSwap = T_DOSWAP(info->OutputFormat);
|
||||
int Reverse = T_FLAVOR(info->OutputFormat);
|
||||
int Extra = T_EXTRA(info->OutputFormat);
|
||||
int SwapFirst = T_SWAPFIRST(info->OutputFormat);
|
||||
int Planar = T_PLANAR(info->OutputFormat);
|
||||
int ExtraFirst = DoSwap ^ SwapFirst;
|
||||
cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
|
||||
cmsFloat64Number v = 0;
|
||||
cmsFloat64Number* swap1 = (cmsFloat64Number*)output;
|
||||
int i, start = 0;
|
||||
|
||||
if (ExtraFirst)
|
||||
start = Extra;
|
||||
if (ExtraFirst)
|
||||
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 = wOut[index] * maximum;
|
||||
v = wOut[index] * maximum;
|
||||
|
||||
if (Reverse)
|
||||
v = maximum - v;
|
||||
if (Reverse)
|
||||
v = maximum - v;
|
||||
|
||||
if (Planar)
|
||||
((cmsFloat64Number*) output)[(i + start) * Stride] = v;
|
||||
else
|
||||
((cmsFloat64Number*) output)[i + start] = v;
|
||||
}
|
||||
if (Planar)
|
||||
((cmsFloat64Number*)output)[(i + start) * Stride] = v;
|
||||
else
|
||||
((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));
|
||||
*swap1 = v;
|
||||
}
|
||||
memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat64Number));
|
||||
*swap1 = v;
|
||||
}
|
||||
|
||||
|
||||
if (T_PLANAR(info -> OutputFormat))
|
||||
return output + sizeof(cmsFloat64Number);
|
||||
else
|
||||
return output + nChan * sizeof(cmsFloat64Number);
|
||||
if (T_PLANAR(info->OutputFormat))
|
||||
return output + sizeof(cmsFloat64Number);
|
||||
else
|
||||
return output + (nChan + Extra) * sizeof(cmsFloat64Number);
|
||||
|
||||
}
|
||||
|
||||
@ -2850,50 +2837,47 @@ cmsUInt8Number* PackHalfFrom16(register _cmsTRANSFORM* info,
|
||||
register cmsUInt8Number* output,
|
||||
register cmsUInt32Number Stride)
|
||||
{
|
||||
int nChan = T_CHANNELS(info -> OutputFormat);
|
||||
int DoSwap = T_DOSWAP(info ->OutputFormat);
|
||||
int Reverse = T_FLAVOR(info ->OutputFormat);
|
||||
int Extra = T_EXTRA(info -> OutputFormat);
|
||||
int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
|
||||
int Planar = T_PLANAR(info -> OutputFormat);
|
||||
int ExtraFirst = DoSwap ^ SwapFirst;
|
||||
cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35F : 65535.0F;
|
||||
cmsFloat32Number v = 0;
|
||||
cmsUInt16Number* swap1 = (cmsUInt16Number*) output;
|
||||
int i, start = 0;
|
||||
int nChan = T_CHANNELS(info->OutputFormat);
|
||||
int DoSwap = T_DOSWAP(info->OutputFormat);
|
||||
int Reverse = T_FLAVOR(info->OutputFormat);
|
||||
int Extra = T_EXTRA(info->OutputFormat);
|
||||
int SwapFirst = T_SWAPFIRST(info->OutputFormat);
|
||||
int Planar = T_PLANAR(info->OutputFormat);
|
||||
int ExtraFirst = DoSwap ^ SwapFirst;
|
||||
cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 655.35F : 65535.0F;
|
||||
cmsFloat32Number v = 0;
|
||||
cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
|
||||
int i, start = 0;
|
||||
|
||||
if (ExtraFirst)
|
||||
start = Extra;
|
||||
if (ExtraFirst)
|
||||
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)
|
||||
v = maximum - v;
|
||||
if (Reverse)
|
||||
v = maximum - v;
|
||||
|
||||
if (Planar)
|
||||
((cmsUInt16Number*) output)[(i + start ) * Stride]= _cmsFloat2Half(v);
|
||||
else
|
||||
((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half(v);
|
||||
}
|
||||
if (Planar)
|
||||
((cmsUInt16Number*)output)[(i + start) * Stride] = _cmsFloat2Half(v);
|
||||
else
|
||||
((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));
|
||||
*swap1 = _cmsFloat2Half(v);
|
||||
}
|
||||
memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));
|
||||
*swap1 = _cmsFloat2Half(v);
|
||||
}
|
||||
|
||||
if (T_PLANAR(info -> OutputFormat))
|
||||
return output + sizeof(cmsUInt16Number);
|
||||
else
|
||||
return output + nChan * sizeof(cmsUInt16Number);
|
||||
if (T_PLANAR(info->OutputFormat))
|
||||
return output + sizeof(cmsUInt16Number);
|
||||
else
|
||||
return output + (nChan + Extra) * sizeof(cmsUInt16Number);
|
||||
}
|
||||
|
||||
|
||||
@ -2904,50 +2888,47 @@ cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info,
|
||||
cmsUInt8Number* output,
|
||||
cmsUInt32Number Stride)
|
||||
{
|
||||
int nChan = T_CHANNELS(info -> OutputFormat);
|
||||
int DoSwap = T_DOSWAP(info ->OutputFormat);
|
||||
int Reverse = T_FLAVOR(info ->OutputFormat);
|
||||
int Extra = T_EXTRA(info -> OutputFormat);
|
||||
int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
|
||||
int Planar = T_PLANAR(info -> OutputFormat);
|
||||
int ExtraFirst = DoSwap ^ SwapFirst;
|
||||
cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0F : 1.0F;
|
||||
cmsUInt16Number* swap1 = (cmsUInt16Number*) output;
|
||||
cmsFloat32Number v = 0;
|
||||
int i, start = 0;
|
||||
int nChan = T_CHANNELS(info->OutputFormat);
|
||||
int DoSwap = T_DOSWAP(info->OutputFormat);
|
||||
int Reverse = T_FLAVOR(info->OutputFormat);
|
||||
int Extra = T_EXTRA(info->OutputFormat);
|
||||
int SwapFirst = T_SWAPFIRST(info->OutputFormat);
|
||||
int Planar = T_PLANAR(info->OutputFormat);
|
||||
int ExtraFirst = DoSwap ^ SwapFirst;
|
||||
cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 100.0F : 1.0F;
|
||||
cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
|
||||
cmsFloat32Number v = 0;
|
||||
int i, start = 0;
|
||||
|
||||
if (ExtraFirst)
|
||||
start = Extra;
|
||||
if (ExtraFirst)
|
||||
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 = wOut[index] * maximum;
|
||||
v = wOut[index] * maximum;
|
||||
|
||||
if (Reverse)
|
||||
v = maximum - v;
|
||||
if (Reverse)
|
||||
v = maximum - v;
|
||||
|
||||
if (Planar)
|
||||
((cmsUInt16Number*) output)[(i + start)* Stride]= _cmsFloat2Half( v );
|
||||
else
|
||||
((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half( v );
|
||||
}
|
||||
if (Planar)
|
||||
((cmsUInt16Number*)output)[(i + start)* Stride] = _cmsFloat2Half(v);
|
||||
else
|
||||
((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));
|
||||
*swap1 = (cmsUInt16Number) _cmsFloat2Half( v );
|
||||
}
|
||||
memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));
|
||||
*swap1 = (cmsUInt16Number)_cmsFloat2Half(v);
|
||||
}
|
||||
|
||||
if (T_PLANAR(info -> OutputFormat))
|
||||
return output + sizeof(cmsUInt16Number);
|
||||
else
|
||||
return output + nChan * sizeof(cmsUInt16Number);
|
||||
if (T_PLANAR(info->OutputFormat))
|
||||
return output + sizeof(cmsUInt16Number);
|
||||
else
|
||||
return output + (nChan + Extra)* sizeof(cmsUInt16Number);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -135,6 +135,15 @@ void CMSEXPORT cmsxyY2XYZ(cmsCIEXYZ* Dest, const cmsCIExyY* Source)
|
||||
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
|
||||
cmsFloat64Number f(cmsFloat64Number t)
|
||||
{
|
||||
|
@ -712,15 +712,21 @@ struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID)
|
||||
|
||||
|
||||
// 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)
|
||||
{
|
||||
struct _cmsContext_struct* ctx;
|
||||
void *ptr;
|
||||
|
||||
if (mc < 0 || mc >= MemoryClientMax) {
|
||||
cmsSignalError(ContextID, cmsERROR_RANGE, "Bad context client");
|
||||
return NULL;
|
||||
if ((int) mc < 0 || mc >= MemoryClientMax) {
|
||||
|
||||
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);
|
||||
@ -909,7 +915,7 @@ cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
static
|
||||
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!
|
||||
}
|
||||
*/
|
||||
|
||||
// Frees any resources associated with the given context,
|
||||
// and destroys the context placeholder.
|
||||
@ -961,8 +968,8 @@ void CMSEXPORT cmsDeleteContext(cmsContext ContextID)
|
||||
|
||||
// Search for previous
|
||||
for (prev = _cmsContextPoolHead;
|
||||
prev != NULL;
|
||||
prev = prev ->Next)
|
||||
prev != NULL;
|
||||
prev = prev ->Next)
|
||||
{
|
||||
if (prev -> Next == ctx) {
|
||||
prev -> Next = ctx ->Next;
|
||||
|
@ -30,7 +30,7 @@
|
||||
//---------------------------------------------------------------------------------
|
||||
//
|
||||
// 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
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
@ -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.
|
||||
// This algorithm comes from the Adobe paper disclosing its black point compensation method.
|
||||
@ -515,7 +494,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
|
||||
|
||||
|
||||
// Test for mid range straight (only on relative colorimetric)
|
||||
|
||||
NearlyStraightMidrange = TRUE;
|
||||
MinL = outRamp[0]; MaxL = outRamp[255];
|
||||
if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
|
||||
@ -531,7 +509,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
|
||||
// DestinationBlackPoint shall be the same as initialLab.
|
||||
// Otherwise, the DestinationBlackPoint shall be determined
|
||||
// using curve fitting.
|
||||
|
||||
if (NearlyStraightMidrange) {
|
||||
|
||||
cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
|
||||
@ -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,
|
||||
// with a corner and a nearly straight line to the white point.
|
||||
|
||||
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
|
||||
|
||||
if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
|
||||
lo = 0.1;
|
||||
hi = 0.5;
|
||||
|
@ -1718,10 +1718,7 @@ cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number
|
||||
else
|
||||
for (j=0; j < 256; j++) {
|
||||
|
||||
if (Tables != NULL)
|
||||
val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);
|
||||
else
|
||||
val = (cmsUInt8Number) j;
|
||||
val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);
|
||||
|
||||
if (!_cmsWriteUInt8Number(io, val)) return FALSE;
|
||||
}
|
||||
@ -3548,7 +3545,6 @@ void *Type_UcrBg_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
|
||||
if (n ->Desc == NULL) return NULL;
|
||||
|
||||
ASCIIString = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1);
|
||||
if (ASCIIString == NULL) return NULL;
|
||||
if (io ->Read(io, ASCIIString, sizeof(char), SizeOfTag) != SizeOfTag) return NULL;
|
||||
ASCIIString[SizeOfTag] = 0;
|
||||
cmsMLUsetASCII(n ->Desc, cmsNoLanguage, cmsNoCountry, ASCIIString);
|
||||
@ -3576,7 +3572,6 @@ cmsBool Type_UcrBg_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io
|
||||
// Now comes the text. The length is specified by the tag size
|
||||
TextSize = cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, NULL, 0);
|
||||
Text = (char*) _cmsMalloc(self ->ContextID, TextSize);
|
||||
if (Text == NULL) return FALSE;
|
||||
if (cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, Text, TextSize) != TextSize) return FALSE;
|
||||
|
||||
if (!io ->Write(io, TextSize, Text)) return FALSE;
|
||||
@ -3674,7 +3669,6 @@ cmsBool WriteCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER*
|
||||
|
||||
TextSize = cmsMLUgetASCII(mlu, "PS", Section, NULL, 0);
|
||||
Text = (char*) _cmsMalloc(self ->ContextID, TextSize);
|
||||
if (Text == NULL) return FALSE;
|
||||
|
||||
if (!_cmsWriteUInt32Number(io, TextSize)) return FALSE;
|
||||
|
||||
|
@ -671,7 +671,7 @@ cmsToneCurve* Build_sRGBGamma(cmsContext ContextID)
|
||||
// Create the ICC virtual profile for sRGB space
|
||||
cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID)
|
||||
{
|
||||
cmsCIExyY D65;
|
||||
cmsCIExyY D65 = { 0.3127, 0.3290, 1.0 };
|
||||
cmsCIExyYTRIPLE Rec709Primaries = {
|
||||
{0.6400, 0.3300, 1.0},
|
||||
{0.3000, 0.6000, 1.0},
|
||||
@ -680,7 +680,7 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID)
|
||||
cmsToneCurve* Gamma22[3];
|
||||
cmsHPROFILE hsRGB;
|
||||
|
||||
cmsWhitePointFromTemp(&D65, 6504);
|
||||
// cmsWhitePointFromTemp(&D65, 6504);
|
||||
Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID);
|
||||
if (Gamma22[0] == NULL) return NULL;
|
||||
|
||||
@ -708,6 +708,7 @@ typedef struct {
|
||||
cmsFloat64Number Contrast;
|
||||
cmsFloat64Number Hue;
|
||||
cmsFloat64Number Saturation;
|
||||
cmsBool lAdjustWP;
|
||||
cmsCIEXYZ WPsrc, WPdest;
|
||||
|
||||
} BCHSWADJUSTS, *LPBCHSWADJUSTS;
|
||||
@ -737,9 +738,10 @@ int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number O
|
||||
cmsLCh2Lab(&LabOut, &LChOut);
|
||||
|
||||
// Move white point in Lab
|
||||
|
||||
cmsLab2XYZ(&bchsw ->WPsrc, &XYZ, &LabOut);
|
||||
cmsXYZ2Lab(&bchsw ->WPdest, &LabOut, &XYZ);
|
||||
if (bchsw->lAdjustWP) {
|
||||
cmsLab2XYZ(&bchsw->WPsrc, &XYZ, &LabOut);
|
||||
cmsXYZ2Lab(&bchsw->WPdest, &LabOut, &XYZ);
|
||||
}
|
||||
|
||||
// Back to encoded
|
||||
|
||||
@ -773,18 +775,23 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
|
||||
bchsw.Contrast = Contrast;
|
||||
bchsw.Hue = Hue;
|
||||
bchsw.Saturation = Saturation;
|
||||
if (TempSrc == TempDest) {
|
||||
|
||||
cmsWhitePointFromTemp(&WhitePnt, TempSrc );
|
||||
cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
|
||||
bchsw.lAdjustWP = FALSE;
|
||||
}
|
||||
else {
|
||||
bchsw.lAdjustWP = TRUE;
|
||||
cmsWhitePointFromTemp(&WhitePnt, TempSrc);
|
||||
cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
|
||||
cmsWhitePointFromTemp(&WhitePnt, TempDest);
|
||||
cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
|
||||
|
||||
cmsWhitePointFromTemp(&WhitePnt, TempDest);
|
||||
cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
|
||||
}
|
||||
|
||||
hICC = cmsCreateProfilePlaceholder(ContextID);
|
||||
if (!hICC) // can't allocate
|
||||
return NULL;
|
||||
|
||||
|
||||
cmsSetDeviceClass(hICC, cmsSigAbstractClass);
|
||||
cmsSetColorSpace(hICC, cmsSigLabData);
|
||||
cmsSetPCS(hICC, cmsSigLabData);
|
||||
@ -1017,12 +1024,14 @@ typedef struct {
|
||||
|
||||
} cmsAllowedLUT;
|
||||
|
||||
#define cmsSig0 ((cmsTagSignature) 0)
|
||||
|
||||
static const cmsAllowedLUT AllowedLUTTypes[] = {
|
||||
|
||||
{ FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
|
||||
{ FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
|
||||
{ FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}},
|
||||
{ TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }},
|
||||
{ FALSE, cmsSig0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } },
|
||||
{ FALSE, cmsSig0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } },
|
||||
{ FALSE, cmsSig0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType } },
|
||||
{ TRUE, cmsSig0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType } },
|
||||
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } },
|
||||
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } },
|
||||
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 5, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }},
|
||||
|
@ -621,46 +621,48 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
|
||||
_cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin);
|
||||
_cmsTransformCollection* Plugin;
|
||||
|
||||
// Allocate needed memory
|
||||
_cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
|
||||
if (!p) return NULL;
|
||||
// Allocate needed memory
|
||||
_cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
|
||||
if (!p) return NULL;
|
||||
|
||||
// Store the proposed pipeline
|
||||
p ->Lut = lut;
|
||||
// Store the proposed pipeline
|
||||
p->Lut = lut;
|
||||
|
||||
// Let's see if any plug-in want to do the transform by itself
|
||||
for (Plugin = ctx ->TransformCollection;
|
||||
Plugin != NULL;
|
||||
Plugin = Plugin ->Next) {
|
||||
// Let's see if any plug-in want to do the transform by itself
|
||||
if (p->Lut != NULL) {
|
||||
|
||||
if (Plugin ->Factory(&p->xform, &p->UserData, &p ->FreeUserData, &p ->Lut, InputFormat, OutputFormat, dwFlags)) {
|
||||
for (Plugin = ctx->TransformCollection;
|
||||
Plugin != NULL;
|
||||
Plugin = Plugin->Next) {
|
||||
|
||||
// Last plugin in the declaration order takes control. We just keep
|
||||
// the original parameters as a logging.
|
||||
// Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default
|
||||
// an optimized transform is not reusable. The plug-in can, however, change
|
||||
// the flags and make it suitable.
|
||||
if (Plugin->Factory(&p->xform, &p->UserData, &p->FreeUserData, &p->Lut, InputFormat, OutputFormat, dwFlags)) {
|
||||
|
||||
p ->ContextID = ContextID;
|
||||
p ->InputFormat = *InputFormat;
|
||||
p ->OutputFormat = *OutputFormat;
|
||||
p ->dwOriginalFlags = *dwFlags;
|
||||
// Last plugin in the declaration order takes control. We just keep
|
||||
// the original parameters as a logging.
|
||||
// Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default
|
||||
// an optimized transform is not reusable. The plug-in can, however, change
|
||||
// the flags and make it suitable.
|
||||
|
||||
// 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
|
||||
// factory to decide what to do in those cases.
|
||||
p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, 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 ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
|
||||
p->ContextID = ContextID;
|
||||
p->InputFormat = *InputFormat;
|
||||
p->OutputFormat = *OutputFormat;
|
||||
p->dwOriginalFlags = *dwFlags;
|
||||
|
||||
return p;
|
||||
}
|
||||
}
|
||||
// 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
|
||||
// factory to decide what to do in those cases.
|
||||
p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, 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->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
|
||||
|
||||
// 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);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
// Not suitable for the transform plug-in, let's check the pipeline plug-in
|
||||
_cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
|
||||
}
|
||||
|
||||
// Check whatever this is a true floating point transform
|
||||
if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) {
|
||||
|
@ -52,7 +52,7 @@
|
||||
//
|
||||
//---------------------------------------------------------------------------------
|
||||
//
|
||||
// Version 2.6
|
||||
// Version 2.7
|
||||
//
|
||||
|
||||
#ifndef _lcms2_H
|
||||
@ -104,7 +104,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
// 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
|
||||
#ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
|
||||
@ -213,27 +213,19 @@ typedef int cmsBool;
|
||||
# define CMS_USE_BIG_ENDIAN 1
|
||||
#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 __powerpc__ || __ppc__ || TARGET_CPU_PPC
|
||||
# define CMS_USE_BIG_ENDIAN 1
|
||||
# if defined (__GNUC__) && defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN)
|
||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
// // Don't use big endian for PowerPC little endian mode
|
||||
# if defined (__GNUC__) && defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)
|
||||
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
// Don't use big endian for PowerPC little endian mode
|
||||
# undef CMS_USE_BIG_ENDIAN
|
||||
# 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
|
||||
|
||||
#ifdef macintosh
|
||||
# ifdef __BIG_ENDIAN__
|
||||
# define CMS_USE_BIG_ENDIAN 1
|
||||
@ -243,6 +235,12 @@ typedef int cmsBool;
|
||||
# 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
|
||||
#ifdef CMS_IS_WINDOWS_
|
||||
# if defined(CMS_DLL) || defined(CMS_DLL_BUILD)
|
||||
@ -553,7 +551,8 @@ typedef enum {
|
||||
cmsSigLab2FloatPCS = 0x64326C20, // 'd2l '
|
||||
cmsSigFloatPCS2Lab = 0x6C326420, // 'l2d '
|
||||
cmsSigXYZ2FloatPCS = 0x64327820, // 'd2x '
|
||||
cmsSigFloatPCS2XYZ = 0x78326420 // 'x2d '
|
||||
cmsSigFloatPCS2XYZ = 0x78326420, // 'x2d '
|
||||
cmsSigClipNegativesElemType = 0x636c7020 // 'clp '
|
||||
|
||||
} cmsStageSignature;
|
||||
|
||||
@ -1031,6 +1030,10 @@ typedef struct {
|
||||
|
||||
} cmsICCViewingConditions;
|
||||
|
||||
// Get LittleCMS version (for shared objects) -----------------------------------------------------------------------------
|
||||
|
||||
CMSAPI int CMSEXPORT cmsGetEncodedCMMversion(void);
|
||||
|
||||
// Support of non-standard functions --------------------------------------------------------------------------------------
|
||||
|
||||
CMSAPI int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2);
|
||||
@ -1509,7 +1512,7 @@ CMSAPI int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignat
|
||||
|
||||
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 cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat);
|
||||
|
||||
@ -1538,6 +1541,7 @@ CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID
|
||||
CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* Stream);
|
||||
CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buffer, cmsUInt32Number size, const char* AccessMode);
|
||||
CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID);
|
||||
CMSAPI cmsIOHANDLER* CMSEXPORT cmsGetProfileIOhandler(cmsHPROFILE hProfile);
|
||||
CMSAPI cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io);
|
||||
|
||||
// MD5 message digest --------------------------------------------------------------------------------------------------
|
||||
@ -1672,6 +1676,10 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID
|
||||
#define cmsFLAGS_CLUT_POST_LINEARIZATION 0x0001 // create postlinearization 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
|
||||
#define cmsFLAGS_GRIDPOINTS(n) (((n) & 0xFF) << 16)
|
||||
|
||||
|
@ -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
|
||||
// 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
|
||||
// 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;
|
||||
|
||||
#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)
|
||||
{
|
||||
@ -313,38 +319,38 @@ typedef int _cmsMutex;
|
||||
|
||||
cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
|
||||
{
|
||||
return 0;
|
||||
cmsUNUSED_PARAMETER(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
|
||||
{
|
||||
return 0;
|
||||
cmsUNUSED_PARAMETER(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
|
||||
{
|
||||
return 0;
|
||||
cmsUNUSED_PARAMETER(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
|
||||
{
|
||||
return 0;
|
||||
cmsUNUSED_PARAMETER(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
|
||||
{
|
||||
return 0;
|
||||
cmsUNUSED_PARAMETER(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
|
||||
{
|
||||
return 0;
|
||||
cmsUNUSED_PARAMETER(m);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -852,6 +858,8 @@ cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID);
|
||||
cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID);
|
||||
cmsStage* _cmsStageNormalizeToLabFloat(cmsContext ContextID);
|
||||
cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID);
|
||||
cmsStage* _cmsStageClipNegatives(cmsContext ContextID, int nChannels);
|
||||
|
||||
|
||||
// For curve set only
|
||||
cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe);
|
||||
|
Loading…
x
Reference in New Issue
Block a user