summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin@ghostscript.com>2011-05-11 16:17:05 +0000
committerRobin Watts <robin@ghostscript.com>2011-05-11 16:20:10 +0000
commit6469f738123e0c212473f11d38e88bb3650a9087 (patch)
treec2236b37bc148d7bfcbb4f3dd32a46e1296bcff0
parent1d07f53add51362ce5887b599f2dcb360f9cf348 (diff)
downloadghostpdl-6469f738123e0c212473f11d38e88bb3650a9087.tar.gz
LCMS (v1) optimisations for CachedXFORM etc.
Optimise CachedXFORM (and related functions) by using a 'template' header file and repeatedly including it with different options to generate different specific versions of the code. This gives a 10% improvement on 568.40345_VO_nr_3_vpeSR18.xl (a file where most of the time is spent in clipping). No expected cluster differences.
-rw-r--r--gs/base/lcms.mak2
-rw-r--r--gs/lcms/include/lcms.h2
-rw-r--r--gs/lcms/src/cmspack.c109
-rw-r--r--gs/lcms/src/cmsxform.c667
-rw-r--r--gs/lcms/src/cmsxform.h230
5 files changed, 553 insertions, 457 deletions
diff --git a/gs/base/lcms.mak b/gs/base/lcms.mak
index c7e8e6e71..5014c0ada 100644
--- a/gs/base/lcms.mak
+++ b/gs/base/lcms.mak
@@ -125,7 +125,7 @@ $(LCMSOBJ)cmsmatsh.$(OBJ) : $(LCMSSRC)cmsmatsh.c $(lcms_HDRS)
$(LCMSOBJ)cmsmtrx.$(OBJ) : $(LCMSSRC)cmsmtrx.c $(lcms_HDRS)
$(LCMS_CC) $(LCMSO_)cmsmtrx.$(OBJ) $(C_) $(LCMSSRC)cmsmtrx.c
-$(LCMSOBJ)cmspack.$(OBJ) : $(LCMSSRC)cmspack.c $(lcms_HDRS)
+$(LCMSOBJ)cmspack.$(OBJ) : $(LCMSSRC)cmspack.c $(LCMSSRC)cmsxform.h $(lcms_HDRS)
$(LCMS_CC) $(LCMSO_)cmspack.$(OBJ) $(C_) $(LCMSSRC)cmspack.c
$(LCMSOBJ)cmspcs.$(OBJ) : $(LCMSSRC)cmspcs.c $(lcms_HDRS)
diff --git a/gs/lcms/include/lcms.h b/gs/lcms/include/lcms.h
index 7a061e6a1..269299425 100644
--- a/gs/lcms/include/lcms.h
+++ b/gs/lcms/include/lcms.h
@@ -2056,6 +2056,8 @@ LPGAMMATABLE _cmsBuildKToneCurve(cmsHTRANSFORM hCMYK2CMYK, int nPoints);
// Validates a LUT
LCMSBOOL cdecl _cmsValidateLUT(LPLUT NewLUT);
+// Choose the transform function to use
+void _cmsSetPrecalculatedTransform(_LPcmsTRANSFORM p);
// These are two VITAL macros, from converting between 8 and 16 bit
// representation.
diff --git a/gs/lcms/src/cmspack.c b/gs/lcms/src/cmspack.c
index c4c16f9d4..5c409b372 100644
--- a/gs/lcms/src/cmspack.c
+++ b/gs/lcms/src/cmspack.c
@@ -2135,6 +2135,113 @@ void LCMSEXPORT cmsGetUserFormatters(cmsHTRANSFORM hTransform,
}
+extern WORD _cmsAlarmR, _cmsAlarmG, _cmsAlarmB;
+
+// RJW: Move the core transform routines in here, so they can benefit from
+// being in the same compilation unit as the pack/unpack routines.
+#define FUNCTION_NAME PrecalculatedXFORM
+#include "cmsxform.h"
+
+#define FUNCTION_NAME PrecalculatedXFORMGamutCheck
+#define GAMUTCHECK
+#include "cmsxform.h"
+
+#define FUNCTION_NAME CachedXFORM
+#define CACHED
+#include "cmsxform.h"
+
+#define FUNCTION_NAME CachedXFORM4
+#define CACHED
+#define INBYTES 4
+#include "cmsxform.h"
+
+#define FUNCTION_NAME CachedXFORM8
+#define CACHED
+#define INBYTES 8
+#include "cmsxform.h"
+
+#define FUNCTION_NAME CachedXFORMGamutCheck
+#define CACHED
+#define GAMUTCHECK
+#include "cmsxform.h"
+
+#define FUNCTION_NAME CachedXFORM3to1
+#define CACHED
+#define INBYTES 6
+#define UNPACK(T,D,S) \
+do { \
+ (D)[0] = RGB_8_TO_16(*(S)); (S)++; /* R */ \
+ (D)[1] = RGB_8_TO_16(*(S)); (S)++; /* G */ \
+ (D)[2] = RGB_8_TO_16(*(S)); (S)++; /* B */ \
+} while (0)
+#define PACKFN Pack1Byte
+#include "cmsxform.h"
+
+// Auxiliar: Handle precalculated gamut check
+
+void TransformOnePixelWithGamutCheck(_LPcmsTRANSFORM p, WORD wIn[], WORD wOut[])
+{
+ WORD wOutOfGamut;
+
+ cmsEvalLUT(p ->GamutCheck, wIn, &wOutOfGamut);
+
+ if (wOutOfGamut >= 1) {
+
+ ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
+
+ wOut[0] = _cmsAlarmR;
+ wOut[1] = _cmsAlarmG;
+ wOut[2] = _cmsAlarmB;
+
+ }
+ else
+ cmsEvalLUT(p -> DeviceLink, wIn, wOut);
+
+}
+
+// Identify whatever a transform is to be cached
+
+void _cmsSetPrecalculatedTransform(_LPcmsTRANSFORM p)
+{
+ if ((p->dwOriginalFlags & cmsFLAGS_GAMUTCHECK) && p ->GamutCheck != NULL) {
+
+ p -> xform = PrecalculatedXFORMGamutCheck;
+
+ if (!(p->dwOriginalFlags & cmsFLAGS_NOTCACHE)) {
+
+ ZeroMemory(p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
+ TransformOnePixelWithGamutCheck(p, p->CacheIn, p ->CacheOut);
+ p ->xform = CachedXFORMGamutCheck;
+ }
+
+ }
+ else {
+
+ p -> xform = PrecalculatedXFORM;
+
+ if (!(p->dwOriginalFlags & cmsFLAGS_NOTCACHE)) {
+
+ ZeroMemory(p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
+ cmsEvalLUT(p ->DeviceLink, p->CacheIn, p ->CacheOut);
+ if ((p->FromInput == Unroll3Bytes) &&
+ (p->ToOutput == Pack1Byte))
+ {
+ p->xform = CachedXFORM3to1;
+ } else {
+ int inbytes = (T_CHANNELS(p->InputFormat) *
+ T_BYTES(p->InputFormat));
+ if (inbytes <= 4)
+ p->xform = CachedXFORM4;
+ else if (inbytes <= 8)
+ p->xform = CachedXFORM8;
+ else
+ p->xform = CachedXFORM;
+ }
+ }
+ }
+}
+
+
// Change format of yet existing transform. No colorspace checking is performed
void LCMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform,
@@ -2147,4 +2254,6 @@ void LCMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform,
(cmsFORMATTER) _cmsIdentifyInputFormat((_LPcmsTRANSFORM) hTransform, dwInputFormat),
dwOutputFormat,
(cmsFORMATTER) _cmsIdentifyOutputFormat((_LPcmsTRANSFORM) hTransform, dwOutputFormat));
+
+ _cmsSetPrecalculatedTransform((_LPcmsTRANSFORM) hTransform);
}
diff --git a/gs/lcms/src/cmsxform.c b/gs/lcms/src/cmsxform.c
index 8977c9347..0ca889dde 100644
--- a/gs/lcms/src/cmsxform.c
+++ b/gs/lcms/src/cmsxform.c
@@ -2,22 +2,22 @@
// Little cms
// Copyright (C) 1998-2007 Marti Maria
//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the Software
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
-// The above copyright notice and this permission notice shall be included in
+// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -63,7 +63,7 @@ LCMSBOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
// Alarm RGB codes
-static WORD AlarmR = 0x8fff, AlarmG = 0x8fff, AlarmB = 0x8fff;
+WORD _cmsAlarmR = 0x8fff, _cmsAlarmG = 0x8fff, _cmsAlarmB = 0x8fff;
// Tag tables, soted by intents
@@ -91,7 +91,7 @@ static volatile double GlobalAdaptationState = 0;
// --------------------------------Stages--------------------------------------
-// Following routines does implement several kind of steps inside
+// Following routines does implement several kind of steps inside
// transform. On building the transform, code chooses adequate.
@@ -113,7 +113,7 @@ void LUTtoPCS(struct _cmstransform_struct *p,
cmsEvalLUT(p -> Device2PCS, In, Out);
}
-// From indexed named color to PCS
+// From indexed named color to PCS
static
void NC2toPCS(struct _cmstransform_struct *p,
@@ -234,12 +234,12 @@ void NormalXFORM(_LPcmsTRANSFORM p,
// Gamut check, enabled across CLUT
cmsEvalLUT(p -> Gamut, wPCS, wGamut);
-
- if (wGamut[0] >= 1) {
-
- wOut[0] = AlarmR; // Gamut alarm
- wOut[1] = AlarmG;
- wOut[2] = AlarmB;
+
+ if (wGamut[0] >= 1) {
+
+ wOut[0] = _cmsAlarmR; // Gamut alarm
+ wOut[1] = _cmsAlarmG;
+ wOut[2] = _cmsAlarmB;
wOut[3] = 0;
output = p -> ToOutput((_LPcmsTRANSFORM)p, wOut, output);
@@ -258,7 +258,7 @@ void NormalXFORM(_LPcmsTRANSFORM p,
if (p -> Stage2) {
p -> Stage2(wPCS, wStageLMN, &p->m2, &p->of2);
-
+
if (wPCS[0] == 0xFFFF &&
wPCS[1] == 0xFFFF &&
wPCS[2] == 0xFFFF) {
@@ -284,219 +284,6 @@ void NormalXFORM(_LPcmsTRANSFORM p,
}
}
-// Using precalculated LUT
-
-static
-void PrecalculatedXFORM(_LPcmsTRANSFORM p,
- LPVOID in,
- LPVOID out, unsigned int Size)
-{
- register LPBYTE accum;
- register LPBYTE output;
- WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
- unsigned int i, n;
-
-
- accum = (LPBYTE) in;
- output = (LPBYTE) out;
- n = Size; // Buffer len
-
-
- for (i=0; i < n; i++) {
-
- accum = p -> FromInput(p, wIn, accum);
-
- // Try to speedup things on plain devicelinks
-
- if (p ->DeviceLink ->wFlags == LUT_HAS3DGRID) {
-
- p ->DeviceLink ->CLut16params.Interp3D(wIn, wOut,
- p ->DeviceLink -> T,
- &p ->DeviceLink -> CLut16params);
- }
- else
- cmsEvalLUT(p -> DeviceLink, wIn, wOut);
-
-
- output = p -> ToOutput(p, wOut, output);
- }
-}
-
-// Auxiliar: Handle precalculated gamut check
-
-static
-void TransformOnePixelWithGamutCheck(_LPcmsTRANSFORM p, WORD wIn[], WORD wOut[])
-{
- WORD wOutOfGamut;
-
- cmsEvalLUT(p ->GamutCheck, wIn, &wOutOfGamut);
-
- if (wOutOfGamut >= 1) {
-
- ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
-
- wOut[0] = AlarmR;
- wOut[1] = AlarmG;
- wOut[2] = AlarmB;
-
- }
- else
- cmsEvalLUT(p -> DeviceLink, wIn, wOut);
-
-}
-
-
-static
-void PrecalculatedXFORMGamutCheck(_LPcmsTRANSFORM p,
- LPVOID in,
- LPVOID out, unsigned int Size)
-{
- register LPBYTE accum;
- register LPBYTE output;
- WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
- register unsigned int i, n;
-
-
- accum = (LPBYTE) in;
- output = (LPBYTE) out;
- n = Size; // Buffer len
-
- for (i=0; i < n; i++) {
-
- accum = p -> FromInput(p, wIn, accum);
-
- TransformOnePixelWithGamutCheck(p, wIn, wOut);
-
- output = p -> ToOutput(p, wOut, output);
- }
-}
-
-
-
-// Using precalculated LUT + Cache
-
-static
-void CachedXFORM(_LPcmsTRANSFORM p,
- LPVOID in,
- LPVOID out, unsigned int Size)
-{
- register LPBYTE accum;
- register LPBYTE output;
- WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
- register unsigned int i, n;
- WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
-
-
- accum = (LPBYTE) in;
- output = (LPBYTE) out;
- n = Size; // Buffer len
-
- // Empty buffers for quick memcmp
-
- ZeroMemory(wIn, sizeof(WORD) * MAXCHANNELS);
- ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
-
-
- LCMS_READ_LOCK(&p ->rwlock);
- CopyMemory(CacheIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
- CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
- LCMS_UNLOCK(&p ->rwlock);
-
- for (i=0; i < n; i++) {
-
- accum = p -> FromInput(p, wIn, accum);
-
-
- if (memcmp(wIn, CacheIn, sizeof(WORD) * MAXCHANNELS) == 0) {
-
- CopyMemory(wOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
- }
- else {
-
- // Try to speedup things on plain devicelinks
-
- if (p ->DeviceLink ->wFlags == LUT_HAS3DGRID) {
-
- p ->DeviceLink ->CLut16params.Interp3D(wIn, wOut,
- p ->DeviceLink -> T,
- &p ->DeviceLink -> CLut16params);
- }
- else
- cmsEvalLUT(p -> DeviceLink, wIn, wOut);
-
-
- CopyMemory(CacheIn, wIn, sizeof(WORD) * MAXCHANNELS);
- CopyMemory(CacheOut, wOut, sizeof(WORD) * MAXCHANNELS);
- }
-
- output = p -> ToOutput(p, wOut, output);
- }
-
-
- LCMS_WRITE_LOCK(&p ->rwlock);
- CopyMemory(p->CacheIn, CacheIn, sizeof(WORD) * MAXCHANNELS);
- CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
- LCMS_UNLOCK(&p ->rwlock);
-
-}
-
-
-
-// Using precalculated LUT + Cache
-
-static
-void CachedXFORMGamutCheck(_LPcmsTRANSFORM p,
- LPVOID in,
- LPVOID out, unsigned int Size)
-{
- register LPBYTE accum;
- register LPBYTE output;
- WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
- register unsigned int i, n;
- WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
-
-
- accum = (LPBYTE) in;
- output = (LPBYTE) out;
- n = Size; // Buffer len
-
- // Empty buffers for quick memcmp
-
- ZeroMemory(wIn, sizeof(WORD) * MAXCHANNELS);
- ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
-
- LCMS_READ_LOCK(&p ->rwlock);
- CopyMemory(CacheIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
- CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
- LCMS_UNLOCK(&p ->rwlock);
-
-
- for (i=0; i < n; i++) {
-
- accum = p -> FromInput(p, wIn, accum);
-
- if (memcmp(wIn, CacheIn, sizeof(WORD) * MAXCHANNELS) == 0) {
-
- CopyMemory(wOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
- }
- else {
-
- TransformOnePixelWithGamutCheck(p, wIn, wOut);
-
- CopyMemory(CacheIn, wIn, sizeof(WORD) * MAXCHANNELS);
- CopyMemory(CacheOut, wOut, sizeof(WORD) * MAXCHANNELS);
- }
-
- output = p -> ToOutput(p, wOut, output);
- }
-
- LCMS_WRITE_LOCK(&p ->rwlock);
- CopyMemory(p->CacheIn, CacheIn, sizeof(WORD) * MAXCHANNELS);
- CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
- LCMS_UNLOCK(&p ->rwlock);
-}
-
-
// Using smelted Matrix/Shaper
static
@@ -542,11 +329,11 @@ void NC2deviceXform(_LPcmsTRANSFORM p,
for (i=0; i < Size; i++) {
- accum = p -> FromInput(p, wIn, accum);
+ accum = p -> FromInput(p, wIn, accum);
CopyMemory(wOut, p ->NamedColorList->List[wIn[0]].DeviceColorant, sizeof(WORD) * MAXCHANNELS);
output = p -> ToOutput(p, wOut, output);
}
-
+
}
@@ -617,12 +404,12 @@ LPMATSHAPER cmsBuildGrayInputMatrixShaper(cmsHPROFILE hProfile)
else {
Shapes[0] = cmsDupGamma(GrayTRC);
Shapes[1] = cmsDupGamma(GrayTRC);
- Shapes[2] = cmsDupGamma(GrayTRC);
+ Shapes[2] = cmsDupGamma(GrayTRC);
}
-
+
if (!Shapes[0] || !Shapes[1] || !Shapes[2])
return NULL;
-
+
cmsFreeGamma(GrayTRC);
// R=G=B as precondition
@@ -630,8 +417,8 @@ LPMATSHAPER cmsBuildGrayInputMatrixShaper(cmsHPROFILE hProfile)
VEC3init(&Scale.v[0], Illuminant.X/3, Illuminant.X/3, Illuminant.X/3);
VEC3init(&Scale.v[1], Illuminant.Y/3, Illuminant.Y/3, Illuminant.Y/3);
VEC3init(&Scale.v[2], Illuminant.Z/3, Illuminant.Z/3, Illuminant.Z/3);
-
-
+
+
MatShaper = cmsAllocMatShaper(&Scale, Shapes, MATSHAPER_INPUT);
cmsFreeGammaTriple(Shapes);
return MatShaper;
@@ -648,27 +435,27 @@ LPMATSHAPER cmsBuildGrayOutputMatrixShaper(cmsHPROFILE hProfile)
LPGAMMATABLE GrayTRC, Shapes[3];
LPMATSHAPER MatShaper;
MAT3 Scale;
-
+
cmsTakeIluminant(&Illuminant, hProfile);
- // That is a special case for non-compliant profiles.
+ // That is a special case for non-compliant profiles.
if (cmsGetPCS(hProfile) == icSigLabData) {
-
+
LPGAMMATABLE Shapes1[3];
GrayTRC = cmsReadICCGamma(hProfile, icSigGrayTRCTag);
FromLstarToXYZ(GrayTRC, Shapes1);
- if (GrayTRC == NULL)
- return NULL;
+ if (GrayTRC == NULL)
+ return NULL;
// Reversing must be done after curve translation
Shapes[0] = cmsReverseGamma(Shapes1[0]->nEntries, Shapes1[0]);
Shapes[1] = cmsReverseGamma(Shapes1[1]->nEntries, Shapes1[1]);
Shapes[2] = cmsReverseGamma(Shapes1[2]->nEntries, Shapes1[2]);
-
+
cmsFreeGammaTriple(Shapes1);
}
@@ -678,24 +465,24 @@ LPMATSHAPER cmsBuildGrayOutputMatrixShaper(cmsHPROFILE hProfile)
GrayTRC = cmsReadICCGammaReversed(hProfile, icSigGrayTRCTag); // Y
- if (GrayTRC == NULL)
- return NULL;
+ if (GrayTRC == NULL)
+ return NULL;
Shapes[0] = cmsDupGamma(GrayTRC);
Shapes[1] = cmsDupGamma(GrayTRC);
- Shapes[2] = cmsDupGamma(GrayTRC);
+ Shapes[2] = cmsDupGamma(GrayTRC);
}
-
+
if (!Shapes[0] || !Shapes[1] || !Shapes[2])
return NULL;
-
+
cmsFreeGamma(GrayTRC);
VEC3init(&Scale.v[0], 0, 1.0/Illuminant.Y, 0);
VEC3init(&Scale.v[1], 0, 1.0/Illuminant.Y, 0);
VEC3init(&Scale.v[2], 0, 1.0/Illuminant.Y, 0);
-
-
+
+
MatShaper = cmsAllocMatShaper(&Scale, Shapes, MATSHAPER_OUTPUT);
cmsFreeGammaTriple(Shapes);
return MatShaper;
@@ -717,8 +504,8 @@ LPMATSHAPER cmsBuildInputMatrixShaper(cmsHPROFILE InputProfile)
// iluminant, scaled across GrayTRC
if (cmsGetColorSpace(InputProfile) == icSigGrayData)
- {
- return cmsBuildGrayInputMatrixShaper(InputProfile);
+ {
+ return cmsBuildGrayInputMatrixShaper(InputProfile);
}
if (!cmsReadICCMatrixRGB2XYZ(&DoubleMat, InputProfile))
@@ -734,7 +521,7 @@ LPMATSHAPER cmsBuildInputMatrixShaper(cmsHPROFILE InputProfile)
InMatSh = cmsAllocMatShaper(&DoubleMat, Shapes, MATSHAPER_INPUT);
cmsFreeGammaTriple(Shapes);
-
+
return InMatSh;
}
@@ -748,11 +535,11 @@ LPMATSHAPER cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile)
LPGAMMATABLE InverseShapes[3];
LPMATSHAPER OutMatSh;
-
+
if (cmsGetColorSpace(OutputProfile) == icSigGrayData)
- {
- return cmsBuildGrayOutputMatrixShaper(OutputProfile);
+ {
+ return cmsBuildGrayOutputMatrixShaper(OutputProfile);
}
@@ -762,11 +549,11 @@ LPMATSHAPER cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile)
if (MAT3inverse(&DoubleMat, &DoubleInv) < 0)
return NULL;
-
+
InverseShapes[0] = cmsReadICCGammaReversed(OutputProfile, icSigRedTRCTag);
InverseShapes[1] = cmsReadICCGammaReversed(OutputProfile, icSigGreenTRCTag);
InverseShapes[2] = cmsReadICCGammaReversed(OutputProfile, icSigBlueTRCTag);
-
+
if (InverseShapes[0] == NULL ||
InverseShapes[1] == NULL ||
InverseShapes[2] == NULL) return NULL;
@@ -774,7 +561,7 @@ LPMATSHAPER cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile)
OutMatSh = cmsAllocMatShaper(&DoubleInv, InverseShapes, MATSHAPER_OUTPUT);
cmsFreeGammaTriple(InverseShapes);
-
+
return OutMatSh;
}
@@ -787,8 +574,8 @@ LCMSBOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
{
MAT3 From, To, ToInv, Transfer;
LPGAMMATABLE In[3], InverseOut[3];
-
-
+
+
if (!cmsReadICCMatrixRGB2XYZ(&From, p -> InputProfile))
return FALSE;
@@ -797,14 +584,14 @@ LCMSBOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
return FALSE;
// invert dest
-
+
if (MAT3inverse(&To, &ToInv) < 0)
return FALSE;
// Multiply
- MAT3per(&Transfer, &ToInv, &From);
-
-
+ MAT3per(&Transfer, &ToInv, &From);
+
+
// Read gamma curves
In[0] = cmsReadICCGamma(p -> InputProfile, icSigRedTRCTag);
@@ -813,14 +600,14 @@ LCMSBOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
if (!In[0] || !In[1] || !In[2])
return FALSE;
-
+
InverseOut[0] = cmsReadICCGammaReversed(p -> OutputProfile, icSigRedTRCTag);
InverseOut[1] = cmsReadICCGammaReversed(p -> OutputProfile, icSigGreenTRCTag);
InverseOut[2] = cmsReadICCGammaReversed(p -> OutputProfile, icSigBlueTRCTag);
if (!InverseOut[0] || !InverseOut[1] || !InverseOut[2]) {
- cmsFreeGammaTriple(In);
+ cmsFreeGammaTriple(In);
return FALSE;
}
@@ -828,7 +615,7 @@ LCMSBOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
cmsFreeGammaTriple(In);
cmsFreeGammaTriple(InverseOut);
-
+
return (p -> SmeltMatShaper != NULL);
}
@@ -841,7 +628,7 @@ LCMSBOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
static
int GetPhase(cmsHPROFILE hProfile)
-{
+{
switch (cmsGetPCS(hProfile)) {
case icSigXYZData: return XYZRel;
@@ -877,9 +664,9 @@ void TakeConversionRoutines(_LPcmsTRANSFORM p, int DoBPC)
cmsTakeMediaBlackPoint(&BlackPointOut, p -> OutputProfile);
cmsReadChromaticAdaptationMatrix(&ChromaticAdaptationMatrixOut, p -> OutputProfile);
-
+
if (p -> Preview == NULL && p ->Gamut == NULL) // Non-proofing
- {
+ {
if (p ->Intent == INTENT_PERCEPTUAL ||
p ->Intent == INTENT_SATURATION) {
@@ -896,34 +683,34 @@ void TakeConversionRoutines(_LPcmsTRANSFORM p, int DoBPC)
// Black point compensation does not apply to absolute intent
- if (p ->Intent == INTENT_ABSOLUTE_COLORIMETRIC)
+ if (p ->Intent == INTENT_ABSOLUTE_COLORIMETRIC)
DoBPC = FALSE;
// Black point compensation does not apply to devicelink profiles
-
+
if (cmsGetDeviceClass(p ->InputProfile) == icSigLinkClass)
DoBPC = FALSE;
if (cmsGetDeviceClass(p ->OutputProfile) == icSigLinkClass)
DoBPC = FALSE;
-
+
if (DoBPC) {
-
+
// Detect Black points
cmsDetectBlackPoint(&BlackPointIn, p->InputProfile, p->Intent, 0);
- cmsDetectBlackPoint(&BlackPointOut, p->OutputProfile, p->Intent, 0);
+ cmsDetectBlackPoint(&BlackPointOut, p->OutputProfile, p->Intent, 0);
// If equal black points, then do nothing. This often applies to BP=0
if (BlackPointIn.X == BlackPointOut.X &&
BlackPointIn.Y == BlackPointOut.Y &&
- BlackPointIn.Z == BlackPointOut.Z)
+ BlackPointIn.Z == BlackPointOut.Z)
DoBPC = FALSE;
}
-
+
cmsChooseCnvrt(p -> Intent == INTENT_ABSOLUTE_COLORIMETRIC,
p -> Phase1,
@@ -947,7 +734,7 @@ void TakeConversionRoutines(_LPcmsTRANSFORM p, int DoBPC)
else // Proofing
{
-
+
cmsTakeIluminant(&IlluminantProof, p -> PreviewProfile);
cmsTakeMediaWhitePoint(&WhitePointProof, p -> PreviewProfile);
cmsTakeMediaBlackPoint(&BlackPointProof, p -> PreviewProfile);
@@ -957,19 +744,19 @@ void TakeConversionRoutines(_LPcmsTRANSFORM p, int DoBPC)
cmsDetectBlackPoint(&BlackPointProof, p->PreviewProfile, p->Intent, 0);
cmsDetectBlackPoint(&BlackPointIn, p->InputProfile, p->Intent, 0);
- cmsDetectBlackPoint(&BlackPointOut, p->OutputProfile, p->Intent, 0);
-
+ cmsDetectBlackPoint(&BlackPointOut, p->OutputProfile, p->Intent, 0);
+
// Reality check
if (BlackPointIn.X == BlackPointProof.X &&
BlackPointIn.Y == BlackPointProof.Y &&
- BlackPointIn.Z == BlackPointProof.Z)
+ BlackPointIn.Z == BlackPointProof.Z)
DoBPC = FALSE;
}
-
+
cmsChooseCnvrt(p -> Intent == INTENT_ABSOLUTE_COLORIMETRIC,
@@ -1068,43 +855,11 @@ _LPcmsTRANSFORM AllocEmptyTransform(void)
return p;
}
-
-// Identify whatever a transform is to be cached
-
-static
-void SetPrecalculatedTransform(_LPcmsTRANSFORM p)
-{
- if ((p->dwOriginalFlags & cmsFLAGS_GAMUTCHECK) && p ->GamutCheck != NULL) {
-
- p -> xform = PrecalculatedXFORMGamutCheck;
-
- if (!(p->dwOriginalFlags & cmsFLAGS_NOTCACHE)) {
-
- ZeroMemory(p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
- TransformOnePixelWithGamutCheck(p, p->CacheIn, p ->CacheOut);
- p ->xform = CachedXFORMGamutCheck;
- }
-
- }
- else {
-
- p -> xform = PrecalculatedXFORM;
-
- if (!(p->dwOriginalFlags & cmsFLAGS_NOTCACHE)) {
-
- ZeroMemory(p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
- cmsEvalLUT(p ->DeviceLink, p->CacheIn, p ->CacheOut);
- p ->xform = CachedXFORM;
- }
- }
-}
-
-
// Transform is identified as device-link
-static
+static
cmsHPROFILE CreateDeviceLinkTransform(_LPcmsTRANSFORM p)
{
-
+
if (!IsProperColorSpace(p->InputProfile, p->InputFormat, FALSE)) {
cmsSignalError(LCMS_ERRC_ABORTED, "Device link is operating on wrong colorspace on input");
return NULL;
@@ -1138,17 +893,17 @@ cmsHPROFILE CreateDeviceLinkTransform(_LPcmsTRANSFORM p)
p -> Phase2 = -1;
p -> Phase3 = -1;
- SetPrecalculatedTransform(p);
-
+ _cmsSetPrecalculatedTransform(p);
+
p -> EntryColorSpace = cmsGetColorSpace(p -> InputProfile);
p -> ExitColorSpace = cmsGetPCS(p -> InputProfile);
-
+
if (p ->EntryColorSpace == icSigRgbData ||
p ->EntryColorSpace == icSigCmyData) {
-
+
p->DeviceLink -> CLut16params.Interp3D = cmsTetrahedralInterp16;
}
-
+
// Precalculated device-link profile is ready
return (cmsHTRANSFORM) p;
}
@@ -1160,13 +915,13 @@ void CreateProof(_LPcmsTRANSFORM p, icTagSignature *ToTagPtr)
{
icTagSignature ProofTag;
-
+
if (p -> dwOriginalFlags & cmsFLAGS_SOFTPROOFING) {
// Apr-15, 2002 - Too much profiles does have bogus content
// on preview tag, so I do compute it by my own.
- p -> Preview = _cmsComputeSoftProofLUT(p ->PreviewProfile, p ->Intent);
+ p -> Preview = _cmsComputeSoftProofLUT(p ->PreviewProfile, p ->Intent);
p -> Phase2 = LabRel;
// That's a proofing transfor, so use second intent for output.
@@ -1174,7 +929,7 @@ void CreateProof(_LPcmsTRANSFORM p, icTagSignature *ToTagPtr)
*ToTagPtr = PCS2Device[p->ProofIntent];
if (p -> Preview == NULL) {
-
+
ProofTag = Preview[p -> Intent];
if (!cmsIsTag(p ->PreviewProfile, ProofTag)) {
@@ -1188,7 +943,7 @@ void CreateProof(_LPcmsTRANSFORM p, icTagSignature *ToTagPtr)
p -> Preview = cmsReadICCLut(p ->PreviewProfile, ProofTag);
p -> Phase2 = GetPhase(p ->PreviewProfile);
-
+
}
else
{
@@ -1197,7 +952,7 @@ void CreateProof(_LPcmsTRANSFORM p, icTagSignature *ToTagPtr)
cmsSignalError(LCMS_ERRC_WARNING, "Sorry, the proof profile has not previewing capabilities");
}
}
-
+
}
@@ -1206,23 +961,23 @@ void CreateProof(_LPcmsTRANSFORM p, icTagSignature *ToTagPtr)
if ((p -> dwOriginalFlags & cmsFLAGS_GAMUTCHECK) && (p -> dwOriginalFlags & cmsFLAGS_NOTPRECALC)) {
-
- p -> Gamut = _cmsComputeGamutLUT(p->PreviewProfile, p ->Intent);
+
+ p -> Gamut = _cmsComputeGamutLUT(p->PreviewProfile, p ->Intent);
p -> Phase2 = LabRel;
if (p -> Gamut == NULL) {
- // Profile goes only in one direction... try to see
+ // Profile goes only in one direction... try to see
// if profile has the tag, and use it, no matter it
// could be bogus. This is the last chance!
if (cmsIsTag(p ->PreviewProfile, icSigGamutTag)) {
p -> Gamut = cmsReadICCLut(p ->PreviewProfile, icSigGamutTag);
-
+
}
else {
-
+
// Nope, cannot be done.
cmsSignalError(LCMS_ERRC_WARNING, "Sorry, the proof profile has not gamut checking capabilities");
@@ -1237,13 +992,13 @@ void CreateProof(_LPcmsTRANSFORM p, icTagSignature *ToTagPtr)
// Choose the adequate transform routine
static
-_LPcmsTRANSFORM PickTransformRoutine(_LPcmsTRANSFORM p,
+_LPcmsTRANSFORM PickTransformRoutine(_LPcmsTRANSFORM p,
icTagSignature *FromTagPtr,
icTagSignature *ToTagPtr)
{
-
-
+
+
// Is a named color profile?
if (cmsGetDeviceClass(p->InputProfile) == icSigNamedColorClass) {
@@ -1254,11 +1009,11 @@ _LPcmsTRANSFORM PickTransformRoutine(_LPcmsTRANSFORM p,
else {
// Can we optimize matrix-shaper only transform?
- if ((*FromTagPtr == 0) &&
- (*ToTagPtr == 0) &&
- (!p->PreviewProfile) &&
- (p -> Intent != INTENT_ABSOLUTE_COLORIMETRIC) &&
- (p -> EntryColorSpace == icSigRgbData) &&
+ if ((*FromTagPtr == 0) &&
+ (*ToTagPtr == 0) &&
+ (!p->PreviewProfile) &&
+ (p -> Intent != INTENT_ABSOLUTE_COLORIMETRIC) &&
+ (p -> EntryColorSpace == icSigRgbData) &&
(p -> ExitColorSpace == icSigRgbData) &&
!(p -> dwOriginalFlags & cmsFLAGS_BLACKPOINTCOMPENSATION)) {
@@ -1268,7 +1023,7 @@ _LPcmsTRANSFORM PickTransformRoutine(_LPcmsTRANSFORM p,
if (!cmsBuildSmeltMatShaper(p))
{
- cmsSignalError(LCMS_ERRC_ABORTED, "unable to smelt shaper-matrix, required tags missing");
+ cmsSignalError(LCMS_ERRC_ABORTED, "unable to smelt shaper-matrix, required tags missing");
return NULL;
}
@@ -1285,7 +1040,7 @@ _LPcmsTRANSFORM PickTransformRoutine(_LPcmsTRANSFORM p,
p -> Device2PCS = cmsReadICCLut(p -> InputProfile, *FromTagPtr);
if (!p -> Device2PCS) {
- cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for input");
+ cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for input");
return NULL;
}
@@ -1296,7 +1051,7 @@ _LPcmsTRANSFORM PickTransformRoutine(_LPcmsTRANSFORM p,
p -> InMatShaper = cmsBuildInputMatrixShaper(p -> InputProfile);
if (!p ->InMatShaper) {
- cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for input");
+ cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for input");
return NULL;
}
@@ -1310,7 +1065,7 @@ _LPcmsTRANSFORM PickTransformRoutine(_LPcmsTRANSFORM p,
p -> ToDevice = PCStoLUT;
p -> PCS2Device = cmsReadICCLut(p -> OutputProfile, *ToTagPtr);
if (!p -> PCS2Device) {
- cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for output");
+ cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for output");
return NULL;
}
@@ -1321,13 +1076,13 @@ _LPcmsTRANSFORM PickTransformRoutine(_LPcmsTRANSFORM p,
p -> OutMatShaper = cmsBuildOutputMatrixShaper(p->OutputProfile);
if (!p -> OutMatShaper) {
- cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for output");
+ cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for output");
return NULL;
}
p -> Phase3 = XYZRel;
-
+
}
-
+
return p;
}
@@ -1350,7 +1105,7 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
_LPcmsTRANSFORM p;
icTagSignature FromTag;
icTagSignature ToTag;
-
+
if (nIntent < 0 || nIntent > 3 ||
ProofingIntent < 0 || ProofingIntent > 3) {
@@ -1367,7 +1122,7 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
p -> DoGamutCheck = FALSE;
p -> InputProfile = InputProfile;
p -> OutputProfile = OutputProfile;
- p -> PreviewProfile = ProofingProfile;
+ p -> PreviewProfile = ProofingProfile;
p -> InputFormat = InputFormat;
p -> OutputFormat = OutputFormat;
p -> dwOriginalFlags = dwFlags;
@@ -1389,7 +1144,7 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
// From here we need at least one input profile
if (InputProfile == NULL) {
-
+
cmsSignalError(LCMS_ERRC_ABORTED, "Input profile cannot be NULL!");
cmsDeleteTransform((cmsHTRANSFORM) p);
return NULL;
@@ -1401,7 +1156,7 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
return CreateDeviceLinkTransform(p);
}
-
+
if (!IsProperColorSpace(InputProfile, InputFormat, FALSE)) {
cmsSignalError(LCMS_ERRC_ABORTED, "Input profile is operating on wrong colorspace");
@@ -1418,7 +1173,7 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
p ->NamedColorList = cmsAllocNamedColorList(0);
cmsReadICCnamedColorList(p, InputProfile, icSigNamedColor2Tag);
-
+
// Special case. If output profile == NULL, then the transform gives
// device values from named colors.
@@ -1433,18 +1188,18 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
p -> dwOriginalFlags |= cmsFLAGS_NOTPRECALC;
}
-
+
// From here we need also output profile.
- if (OutputProfile == NULL) {
+ if (OutputProfile == NULL) {
cmsSignalError(LCMS_ERRC_ABORTED, "Output profile cannot be NULL!");
cmsDeleteTransform((cmsHTRANSFORM) p);
return NULL;
}
-
+
if (!IsProperColorSpace(OutputProfile, OutputFormat, FALSE)) {
cmsSignalError(LCMS_ERRC_ABORTED, "Output profile is operating on wrong colorspace");
- cmsDeleteTransform((cmsHTRANSFORM) p);
+ cmsDeleteTransform((cmsHTRANSFORM) p);
return NULL;
}
@@ -1477,22 +1232,22 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
}
// If proofing is needed, add required tags/parameters
- if (ProofingProfile)
- CreateProof(p, &ToTag);
-
+ if (ProofingProfile)
+ CreateProof(p, &ToTag);
+
if (!cmsIsTag(OutputProfile, ToTag)) {
ToTag = PCS2Device[0];
- // 12-Dec-2003, Abstract profiles can be placed as output and still using AToB0
+ // 12-Dec-2003, Abstract profiles can be placed as output and still using AToB0
if (cmsGetDeviceClass(OutputProfile) == icSigAbstractClass) {
-
+
if (!cmsIsTag(OutputProfile, ToTag)) {
ToTag = (icTagSignature) icSigAToB0Tag;
- }
+ }
}
-
+
if (!cmsIsTag(OutputProfile, ToTag))
ToTag = (icTagSignature)0;
}
@@ -1504,8 +1259,8 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
if (p -> dwOriginalFlags & cmsFLAGS_MATRIXOUTPUT)
ToTag = (icTagSignature)0;
-
-
+
+
if (PickTransformRoutine(p, &FromTag, &ToTag) == NULL) {
cmsDeleteTransform((cmsHTRANSFORM) p);
@@ -1517,9 +1272,9 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
if (!(p -> dwOriginalFlags & cmsFLAGS_NOTPRECALC)) {
- LPLUT DeviceLink;
+ LPLUT DeviceLink;
LPLUT GamutCheck = NULL;
-
+
if (p ->EntryColorSpace == icSigCmykData &&
p ->ExitColorSpace == icSigCmykData &&
@@ -1528,44 +1283,44 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
DeviceLink = _cmsPrecalculateBlackPreservingDeviceLink((cmsHTRANSFORM) p, dwFlags);
// Cannot be done at all?
- if (DeviceLink == NULL)
+ if (DeviceLink == NULL)
DeviceLink = _cmsPrecalculateDeviceLink((cmsHTRANSFORM) p, dwFlags);
- }
+ }
else {
DeviceLink = _cmsPrecalculateDeviceLink((cmsHTRANSFORM) p, dwFlags);
}
-
- // Allow to specify cmsFLAGS_GAMUTCHECK, even if no proofing profile is given
+
+ // Allow to specify cmsFLAGS_GAMUTCHECK, even if no proofing profile is given
if ((p ->PreviewProfile != NULL) && (p -> dwOriginalFlags & cmsFLAGS_GAMUTCHECK)) {
GamutCheck = _cmsPrecalculateGamutCheck((cmsHTRANSFORM) p);
}
// If input colorspace is Rgb, Cmy, then use tetrahedral interpolation
- // for speed reasons (it only works well on spaces on Luma is diagonal, and
+ // for speed reasons (it only works well on spaces on Luma is diagonal, and
// not if luma is in separate channel)
if (p ->EntryColorSpace == icSigRgbData ||
p ->EntryColorSpace == icSigCmyData) {
-
-
+
+
cmsCalcCLUT16ParamsEx(DeviceLink->CLut16params.nSamples,
DeviceLink->CLut16params.nInputs,
- DeviceLink->CLut16params.nOutputs,
+ DeviceLink->CLut16params.nOutputs,
TRUE, &DeviceLink->CLut16params);
-
+
}
-
+
// If this is a 8-bit transform, optimize LUT further.
-
+
if ((T_BYTES(InputFormat) == 1) && (T_CHANNELS(InputFormat) == 3)) {
DeviceLink = _cmsBlessLUT8(DeviceLink);
if (DeviceLink == NULL) return NULL;
}
-
+
p ->GamutCheck = GamutCheck;
@@ -1573,7 +1328,7 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
p ->DeviceLink = DeviceLink;
- if ((nIntent != INTENT_ABSOLUTE_COLORIMETRIC) &&
+ if ((nIntent != INTENT_ABSOLUTE_COLORIMETRIC) &&
!(p -> dwOriginalFlags & cmsFLAGS_NOWHITEONWHITEFIXUP))
_cmsFixWhiteMisalignment(p);
@@ -1591,8 +1346,8 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
}
- SetPrecalculatedTransform(p);
-
+ _cmsSetPrecalculatedTransform(p);
+
}
@@ -1600,7 +1355,7 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
p -> FromInput = _cmsIdentifyInputFormat(p, InputFormat);
p -> ToOutput = _cmsIdentifyOutputFormat(p, OutputFormat);
-
+
return p;
}
@@ -1648,7 +1403,7 @@ void LCMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform)
if (p ->NamedColorList)
cmsFreeNamedColorList(p ->NamedColorList);
if (p -> GamutCheck)
- cmsFreeLUT(p -> GamutCheck);
+ cmsFreeLUT(p -> GamutCheck);
LCMS_FREE_LOCK(&p->rwlock);
@@ -1666,7 +1421,7 @@ void LCMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform,
_LPcmsTRANSFORM p = (_LPcmsTRANSFORM) (LPSTR) Transform;
p -> StrideIn = p -> StrideOut = Size;
-
+
p -> xform(p, InputBuffer, OutputBuffer, Size);
}
@@ -1674,26 +1429,26 @@ void LCMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform,
void LCMSEXPORT cmsSetAlarmCodes(int r, int g, int b)
{
- AlarmR = RGB_8_TO_16(r);
- AlarmG = RGB_8_TO_16(g);
- AlarmB = RGB_8_TO_16(b);
+ _cmsAlarmR = RGB_8_TO_16(r);
+ _cmsAlarmG = RGB_8_TO_16(g);
+ _cmsAlarmB = RGB_8_TO_16(b);
}
void LCMSEXPORT cmsGetAlarmCodes(int *r, int *g, int *b)
{
- *r = RGB_16_TO_8(AlarmR);
- *g = RGB_16_TO_8(AlarmG);
- *b = RGB_16_TO_8(AlarmB);
+ *r = RGB_16_TO_8(_cmsAlarmR);
+ *g = RGB_16_TO_8(_cmsAlarmG);
+ *b = RGB_16_TO_8(_cmsAlarmB);
}
// Returns TRUE if the profile is implemented as matrix-shaper
LCMSBOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile)
-{
+{
switch (cmsGetColorSpace(hProfile)) {
case icSigGrayData:
-
+
return cmsIsTag(hProfile, icSigGrayTRCTag);
case icSigRgbData:
@@ -1740,20 +1495,20 @@ LCMSBOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
return (cmsTakeRenderingIntent(hProfile) == Intent);
}
-// Multiple profile transform.
+// Multiple profile transform.
static
int MultiprofileSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
{
cmsHTRANSFORM* Transforms = (cmsHTRANSFORM*) Cargo;
int i;
-
+
cmsDoTransform(Transforms[0], In, Out, 1);
for (i=1; Transforms[i]; i++)
cmsDoTransform(Transforms[i], Out, Out, 1);
-
+
return TRUE;
}
@@ -1783,14 +1538,14 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
cmsHTRANSFORM Transforms[257];
DWORD dwPrecalcFlags = (dwFlags|cmsFLAGS_NOTPRECALC|cmsFLAGS_NOTCACHE);
DWORD FormatInput, FormatOutput;
- cmsHPROFILE hLab, hXYZ, hProfile;
+ cmsHPROFILE hLab, hXYZ, hProfile;
icColorSpaceSignature ColorSpace, CurrentColorSpace;
- icColorSpaceSignature ColorSpaceIn, ColorSpaceOut;
+ icColorSpaceSignature ColorSpaceIn, ColorSpaceOut;
LPLUT Grid;
- int nGridPoints, ChannelsInput, ChannelsOutput = 3, i;
- _LPcmsTRANSFORM p;
+ int nGridPoints, ChannelsInput, ChannelsOutput = 3, i;
+ _LPcmsTRANSFORM p;
int nNamedColor;
-
+
if (nProfiles > 255) {
cmsSignalError(LCMS_ERRC_ABORTED, "What are you trying to do with more that 255 profiles?!?, of course aborted");
return NULL;
@@ -1799,7 +1554,7 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
// There is a simple case with just two profiles, try to catch it in order of getting
// black preservation to work on this function, at least with two profiles.
-
+
if (nProfiles == 2) {
icProfileClassSignature Class1 = cmsGetDeviceClass(hProfiles[0]);
@@ -1807,20 +1562,20 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
// Only input, output and display are allowed
- if (IsAllowedInSingleXform(Class1) &&
- IsAllowedInSingleXform(Class2))
+ if (IsAllowedInSingleXform(Class1) &&
+ IsAllowedInSingleXform(Class2))
return cmsCreateTransform(hProfiles[0], dwInput, hProfiles[1], dwOutput, Intent, dwFlags);
}
-
+
// Creates a phantom transform for latter filling
- p = (_LPcmsTRANSFORM) cmsCreateTransform(NULL, dwInput,
+ p = (_LPcmsTRANSFORM) cmsCreateTransform(NULL, dwInput,
NULL, dwOutput, Intent, cmsFLAGS_NULLTRANSFORM);
// If user wants null one, give it
if (dwFlags & cmsFLAGS_NULLTRANSFORM) return (cmsHPROFILE) p;
- // Is a bunch of named color profiles?
+ // Is a bunch of named color profiles?
nNamedColor = 0;
for (i=0; i < nProfiles; i++) {
if (cmsGetDeviceClass(hProfiles[i]) == icSigNamedColorClass)
@@ -1863,8 +1618,8 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
// Take some info....
- p ->EntryColorSpace = CurrentColorSpace = cmsGetColorSpace(hProfiles[0]);
-
+ p ->EntryColorSpace = CurrentColorSpace = cmsGetColorSpace(hProfiles[0]);
+
for (i=0; i < nProfiles; i++) {
@@ -1884,99 +1639,99 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
}
else {
-
+
ColorSpaceIn = cmsGetPCS(hProfile);
ColorSpaceOut = cmsGetColorSpace(hProfile);
}
ChannelsInput = _cmsChannelsOf(ColorSpaceIn);
ChannelsOutput = _cmsChannelsOf(ColorSpaceOut);
-
+
FormatInput = BYTES_SH(2)|CHANNELS_SH(ChannelsInput);
FormatOutput = BYTES_SH(2)|CHANNELS_SH(ChannelsOutput);
-
+
ColorSpace = ColorSpaceIn;
-
+
if (ColorSpace == CurrentColorSpace) {
-
+
if (lIsDeviceLink) {
- Transforms[i] = cmsCreateTransform(hProfile, FormatInput,
- NULL, FormatOutput,
- Intent, dwPrecalcFlags);
+ Transforms[i] = cmsCreateTransform(hProfile, FormatInput,
+ NULL, FormatOutput,
+ Intent, dwPrecalcFlags);
}
else {
if (lIsInput) {
- Transforms[i] = cmsCreateTransform(hProfile, FormatInput,
- (ColorSpaceOut == icSigLabData ? hLab : hXYZ), FormatOutput,
- Intent, dwPrecalcFlags);
+ Transforms[i] = cmsCreateTransform(hProfile, FormatInput,
+ (ColorSpaceOut == icSigLabData ? hLab : hXYZ), FormatOutput,
+ Intent, dwPrecalcFlags);
}
else {
- Transforms[i] = cmsCreateTransform((ColorSpaceIn == icSigLabData ? hLab : hXYZ), FormatInput,
- hProfile, FormatOutput,
- Intent, dwPrecalcFlags);
-
+ Transforms[i] = cmsCreateTransform((ColorSpaceIn == icSigLabData ? hLab : hXYZ), FormatInput,
+ hProfile, FormatOutput,
+ Intent, dwPrecalcFlags);
+
}
- }
-
-
+ }
+
+
}
else // Can come from pcs?
if (CurrentColorSpace == icSigXYZData) {
- Transforms[i] = cmsCreateTransform(hXYZ, FormatInput,
- hProfile, FormatOutput,
- Intent, dwPrecalcFlags);
-
+ Transforms[i] = cmsCreateTransform(hXYZ, FormatInput,
+ hProfile, FormatOutput,
+ Intent, dwPrecalcFlags);
+
}
else
if (CurrentColorSpace == icSigLabData) {
- Transforms[i] = cmsCreateTransform(hLab, FormatInput,
- hProfile, FormatOutput,
+ Transforms[i] = cmsCreateTransform(hLab, FormatInput,
+ hProfile, FormatOutput,
Intent, dwPrecalcFlags);
-
- }
+
+ }
else {
cmsSignalError(LCMS_ERRC_ABORTED, "cmsCreateMultiprofileTransform: ColorSpace mismatch");
goto ErrorCleanup;
}
CurrentColorSpace = ColorSpaceOut;
-
+
}
p ->ExitColorSpace = CurrentColorSpace;
- Transforms[i] = NULL; // End marker
+ Transforms[i] = NULL; // End marker
p ->InputProfile = hProfiles[0];
p ->OutputProfile = hProfiles[nProfiles - 1];
nGridPoints = _cmsReasonableGridpointsByColorspace(p ->EntryColorSpace, dwFlags);
-
+
ChannelsInput = _cmsChannelsOf(cmsGetColorSpace(p ->InputProfile));
-
+
Grid = cmsAlloc3DGrid(Grid, nGridPoints, ChannelsInput, ChannelsOutput);
if (!(dwFlags & cmsFLAGS_NOPRELINEARIZATION))
_cmsComputePrelinearizationTablesFromXFORM(Transforms, nProfiles, Grid);
-
- // Compute device link on 16-bit basis
+
+ // Compute device link on 16-bit basis
if (!cmsSample3DGrid(Grid, MultiprofileSampler, (LPVOID) Transforms, Grid -> wFlags)) {
cmsFreeLUT(Grid);
goto ErrorCleanup;
}
- // All ok, store the newly created LUT
+ // All ok, store the newly created LUT
p -> DeviceLink = Grid;
- SetPrecalculatedTransform(p);
-
+ _cmsSetPrecalculatedTransform(p);
+
for (i=nProfiles-1; i >= 0; --i)
cmsDeleteTransform(Transforms[i]);
@@ -1984,15 +1739,15 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
if (hLab) cmsCloseProfile(hLab);
if (hXYZ) cmsCloseProfile(hXYZ);
-
+
if (p ->EntryColorSpace == icSigRgbData ||
p ->EntryColorSpace == icSigCmyData) {
-
+
p->DeviceLink -> CLut16params.Interp3D = cmsTetrahedralInterp16;
}
-
- if ((Intent != INTENT_ABSOLUTE_COLORIMETRIC) &&
+
+ if ((Intent != INTENT_ABSOLUTE_COLORIMETRIC) &&
!(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP))
_cmsFixWhiteMisalignment(p);
@@ -2007,14 +1762,14 @@ ErrorCleanup:
}
-
+
double LCMSEXPORT cmsSetAdaptationState(double d)
{
double OldVal = GlobalAdaptationState;
- if (d >= 0)
+ if (d >= 0)
GlobalAdaptationState = d;
return OldVal;
-
+
}
diff --git a/gs/lcms/src/cmsxform.h b/gs/lcms/src/cmsxform.h
new file mode 100644
index 000000000..bf958cd91
--- /dev/null
+++ b/gs/lcms/src/cmsxform.h
@@ -0,0 +1,230 @@
+//
+// Little cms
+
+// Chameleonic header file to instantiate different versions of the
+// transform routines.
+//
+// As a bare minimum the following must be defined on entry:
+// FUNCTION_NAME the name of the function
+//
+// In addition, a range of other symbols can be optionally defined on entry
+// to make the generated code more efficient. All these symbols (and
+// FUNCTION_NAME) will be automatically undefined at the end of the file so
+// that repeated #includes of this file are made simple.
+//
+// If caching is wanted, define CACHED. (INBYTES will only have an effect
+// if CACHED is defined).
+//
+// To reduce the amount of surplus memory checking done, set INBYTES to the
+// number of bytes in an unpacked data chunk.
+//
+// If you know the code to be used to unpack (or pack, or both) data to/from
+// the simple 16 bit transform input/output format, then you can choose
+// to this directly by defining UNPACK/PACK macros as follows:
+// UNPACK(T,TO,FROM) (Opt) code to unpack input data (T = Transform
+// TO = buffer to unpack into, FROM = data)
+// PACK(T,FROM,TO) (Opt) code to pack transformed input data
+// (T = Transform, FROM = transformed data,
+// TO = output buffer to pack into)
+//
+// As an alternative to the above, if you know the function name that would
+// be called, supply that in UNPACKFN and PACKFN and inlining compilers
+// should hopefully do the hard work for you.
+// UNPACKFN (Opt) function to unpack input data
+// PACKFN (Opt) function to pack input data
+//
+// Finally, GAMUTCHECK can be predefined if a gamut check needs to be done.
+
+#ifndef CACHED
+#undef INBYTES
+#endif
+
+#ifdef INBYTES
+#if INBYTES <= 4
+#define COMPARE(A,B) (*((int *)(A)) != *((int *)(B)))
+#elif INBYTES <= 8
+#define COMPARE(A,B) (*((LCMSULONGLONG *)(A)) != *((LCMSULONGLONG *)(B)))
+/* Or we could use #define COMPARE(A,B) ((((int *)(A))[0] != ((int *)(B))[0]) || (((int *)(A))[1] != ((int *)(B))[1])) */
+#else
+#undef INBYTES
+#endif
+#endif
+
+#ifndef COMPARE
+#define COMPARE(A,B) memcmp((A),(B), (sizeof(WORD)*MAXCHANNELS))
+#endif
+
+#ifndef UNPACK
+#ifdef UNPACKFN
+#define UNPACK(T,TO,FROM) \
+ do { (FROM) = UNPACKFN((T),(TO),(FROM)); } while (0)
+#else
+#define UNPACK(T,TO,FROM) \
+ do { (FROM) = (T)->FromInput((T),(TO),(FROM)); } while (0)
+#endif
+#endif
+
+#ifndef PACK
+#ifdef PACKFN
+#define PACK(T,FROM,TO) \
+ do { (TO) = PACKFN((T),(FROM),(TO)); } while (0)
+#else
+#define PACK(T,FROM,TO) \
+ do { (TO) = (T)->ToOutput((T),(FROM),(TO)); } while (0)
+#endif
+#endif
+
+static
+void FUNCTION_NAME(_LPcmsTRANSFORM p,
+ LPVOID in,
+ LPVOID out,
+ unsigned int n)
+{
+ register LPBYTE accum;
+ register LPBYTE output;
+ LCMSULONGLONG wIn[sizeof(WORD)*MAXCHANNELS*2/sizeof(LCMSULONGLONG)];
+#define wIn0 (&((WORD *)wIn)[0])
+#define wIn1 (&((WORD *)wIn)[MAXCHANNELS])
+ WORD *currIn;
+#ifdef CACHED
+ WORD *prevIn;
+#ifdef INBYTES
+ int cacheValid = 1;
+#endif /* INBYTES */
+#endif /* CACHED */
+ WORD wOut[MAXCHANNELS];
+ LPLUT devLink = p->DeviceLink;
+ accum = (LPBYTE) in;
+ output = (LPBYTE) out;
+
+ if (n == 0)
+ return;
+
+#ifdef CACHED
+ // Empty buffers for quick memcmp
+ ZeroMemory(wIn1, sizeof(WORD) * MAXCHANNELS);
+
+ LCMS_READ_LOCK(&p ->rwlock);
+ CopyMemory(wIn0, p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
+ CopyMemory(wOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
+ LCMS_UNLOCK(&p ->rwlock);
+
+#ifdef INBYTES
+ /* We only check the first 'inBytes' of the cached version in the loop,
+ * and the cached version might differ after that point. So check the
+ * rest of the bytes now. */
+ if (memcmp(((LPBYTE)wIn0)+INBYTES, wIn1,
+ sizeof(WORD) * MAXCHANNELS - INBYTES) != 0)
+ {
+ cacheValid = 0;
+ /* Zero the rest of the cached bytes to ensure what we copy back is
+ * correct. */
+ ZeroMemory(((LPBYTE)wIn0)+INBYTES,
+ sizeof(WORD) * MAXCHANNELS - INBYTES);
+ }
+#endif /* INBYTES */
+
+ prevIn = wIn0;
+#endif /* CACHED */
+ currIn = wIn1;
+
+ // Try to speedup things on plain devicelinks
+#ifdef INBYTES
+ UNPACK(p,currIn,accum);
+#endif
+#ifndef GAMUTCHECK
+ if (devLink->wFlags == LUT_HAS3DGRID) {
+#ifdef INBYTES
+ if (cacheValid)
+ goto enterCacheValid3d;
+ else
+ goto enterCacheInvalid3d;
+#endif
+ do {
+ UNPACK(p,currIn,accum);
+#ifdef INBYTES
+ enterCacheValid3d:
+#endif /* INBYTES */
+#ifdef CACHED
+ if (COMPARE(currIn, prevIn))
+#endif /* CACHED */
+ {
+#ifdef INBYTES
+ enterCacheInvalid3d:
+#endif /* INBYTES */
+ devLink->CLut16params.Interp3D(currIn, wOut,
+ devLink -> T,
+ &devLink -> CLut16params);
+#ifdef CACHED
+ {WORD *tmp = currIn; currIn = prevIn; prevIn = tmp;}
+#endif /* CACHED */
+ }
+ PACK(p,wOut,output);
+ } while (--n);
+ }
+ else
+#endif /* GAMUTCHECK */
+ {
+#ifdef INBYTES
+ if (cacheValid)
+ goto enterCacheValid;
+ else
+ goto enterCacheInvalid;
+#endif /* INBYTES */
+ do {
+ UNPACK(p,currIn,accum);
+#ifdef INBYTES
+ enterCacheValid:
+#endif
+#ifdef CACHED
+ if (COMPARE(currIn, prevIn))
+#endif /* CACHED */
+ {
+#ifdef INBYTES
+ enterCacheInvalid:
+#endif /* INBYTES */
+#ifdef GAMUTCHECK
+ {
+ WORD wOutOfGamut;
+
+ cmsEvalLUT(p->GamutCheck, currIn, &wOutOfGamut);
+ if (wOutOfGamut >= 1) {
+ ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
+
+ wOut[0] = _cmsAlarmR;
+ wOut[1] = _cmsAlarmG;
+ wOut[2] = _cmsAlarmB;
+ } else {
+#endif /* GAMUTCHECK */
+ cmsEvalLUT(devLink, currIn, wOut);
+#ifdef GAMUTCHECK
+ }
+ }
+#endif /* GAMUTCHECK */
+#ifdef CACHED
+ {WORD *tmp = currIn; currIn = prevIn; prevIn = tmp;}
+#endif /* CACHED */
+ }
+ PACK(p,wOut,output);
+ } while (--n);
+ }
+#ifdef CACHED
+ LCMS_WRITE_LOCK(&p ->rwlock);
+ CopyMemory(p->CacheIn, prevIn, sizeof(WORD) * MAXCHANNELS);
+ CopyMemory(p->CacheOut, wOut, sizeof(WORD) * MAXCHANNELS);
+ LCMS_UNLOCK(&p ->rwlock);
+#endif /* CACHED */
+}
+
+#undef wIn0
+#undef wIn1
+
+#undef FUNCTION_NAME
+#undef COMPARE
+#undef INBYTES
+#undef UNPACK
+#undef PACK
+#undef UNPACKFN
+#undef PACKFN
+#undef GAMUTCHECK
+#undef CACHED