summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarti Maria <info@littlecms.com>2011-08-23 16:14:38 +0200
committerMarti Maria <info@littlecms.com>2011-08-23 16:14:38 +0200
commit1e4fab616c4eef7e3ea131386e92fcf34c54f96e (patch)
treea3273563945613eebf0fde8f05a651e1c7476b6a
parent119ebd85ba6ea97078677280365f0df042b8a829 (diff)
downloadlcms2-1e4fab616c4eef7e3ea131386e92fcf34c54f96e.tar.gz
Abs. colorimetric intent fixup
-rw-r--r--src/cmscnvrt.c56
-rw-r--r--src/cmsio1.c2
-rw-r--r--src/cmsopt.c4
-rw-r--r--src/cmsxform.c4
-rw-r--r--testbed/testcms2.c15
5 files changed, 53 insertions, 28 deletions
diff --git a/src/cmscnvrt.c b/src/cmscnvrt.c
index 488da86..1a8e6d8 100644
--- a/src/cmscnvrt.c
+++ b/src/cmscnvrt.c
@@ -164,17 +164,21 @@ void ComputeBlackPointCompensation(const cmsCIEXYZ* BlackPointIn,
static
cmsFloat64Number CHAD2Temp(const cmsMAT3* Chad)
{
- // Convert D50 across CHAD to get the absolute white point
- cmsVEC3 d, s;
- cmsCIEXYZ Dest;
- cmsCIExyY DestChromaticity;
- cmsFloat64Number TempK;
+ // Convert D50 across inverse CHAD to get the absolute white point
+ cmsVEC3 d, s;
+ cmsCIEXYZ Dest;
+ cmsCIExyY DestChromaticity;
+ cmsFloat64Number TempK;
+ cmsMAT3 m1, m2;
+
+ m1 = *Chad;
+ if (!_cmsMAT3inverse(&m1, &m2)) return FALSE;
s.n[VX] = cmsD50_XYZ() -> X;
s.n[VY] = cmsD50_XYZ() -> Y;
s.n[VZ] = cmsD50_XYZ() -> Z;
- _cmsMAT3eval(&d, Chad, &s);
+ _cmsMAT3eval(&d, &m2, &s);
Dest.X = d.n[VX];
Dest.Y = d.n[VY];
@@ -190,15 +194,14 @@ cmsFloat64Number CHAD2Temp(const cmsMAT3* Chad)
// Compute a CHAD based on a given temperature
static
-void Temp2CHAD(cmsMAT3* Chad, cmsFloat64Number Temp)
+ void Temp2CHAD(cmsMAT3* Chad, cmsFloat64Number Temp)
{
cmsCIEXYZ White;
cmsCIExyY ChromaticityOfWhite;
-
+
cmsWhitePointFromTemp(&ChromaticityOfWhite, Temp);
cmsxyY2XYZ(&White, &ChromaticityOfWhite);
- _cmsAdaptationMatrix(Chad, NULL, cmsD50_XYZ(), &White);
-
+ _cmsAdaptationMatrix(Chad, NULL, &White, cmsD50_XYZ());
}
// Join scalings to obtain relative input to absolute and then to relative output.
@@ -211,7 +214,7 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState,
const cmsMAT3* ChromaticAdaptationMatrixOut,
cmsMAT3* m)
{
- cmsMAT3 Scale, m1, m2, m3;
+ cmsMAT3 Scale, m1, m2, m3, m4;
// Adaptation state
if (AdaptationState == 1.0) {
@@ -230,21 +233,30 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState,
_cmsVEC3init(&Scale.v[1], 0, WhitePointIn->Y / WhitePointOut->Y, 0);
_cmsVEC3init(&Scale.v[2], 0, 0, WhitePointIn->Z / WhitePointOut->Z);
- m1 = *ChromaticAdaptationMatrixIn;
- if (!_cmsMAT3inverse(&m1, &m2)) return FALSE;
- _cmsMAT3per(&m3, &m2, &Scale);
- // m3 holds CHAD from output white to D50 times abs. col. scaling
if (AdaptationState == 0.0) {
+ m1 = *ChromaticAdaptationMatrixOut;
+ _cmsMAT3per(&m2, &m1, &Scale);
+ // m2 holds CHAD from output white to D50 times abs. col. scaling
+
// Observer is not adapted, undo the chromatic adaptation
_cmsMAT3per(m, &m3, ChromaticAdaptationMatrixOut);
+ m3 = *ChromaticAdaptationMatrixIn;
+ if (!_cmsMAT3inverse(&m3, &m4)) return FALSE;
+ _cmsMAT3per(m, &m2, &m4);
+
} else {
cmsMAT3 MixedCHAD;
cmsFloat64Number TempSrc, TempDest, Temp;
+ m1 = *ChromaticAdaptationMatrixIn;
+ if (!_cmsMAT3inverse(&m1, &m2)) return FALSE;
+ _cmsMAT3per(&m3, &m2, &Scale);
+ // m3 holds CHAD from input white to D50 times abs. col. scaling
+
TempSrc = CHAD2Temp(ChromaticAdaptationMatrixIn);
TempDest = CHAD2Temp(ChromaticAdaptationMatrixOut);
@@ -256,9 +268,9 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState,
return TRUE;
}
- Temp = AdaptationState * TempSrc + (1.0 - AdaptationState) * TempDest;
+ Temp = (1.0 - AdaptationState) * TempDest + AdaptationState * TempSrc;
- // Get a CHAD from D50 to whatever output temperature. This replaces output CHAD
+ // Get a CHAD from whatever output temperature to D50. This replaces output CHAD
Temp2CHAD(&MixedCHAD, Temp);
_cmsMAT3per(m, &m3, &MixedCHAD);
@@ -898,7 +910,7 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
// Same as anterior, but lab in the 0..1 range
bp.cmyk2Lab = cmsCreateTransformTHR(ContextID, hProfiles[nProfiles-1],
FLOAT_SH(1)|CHANNELS_SH(4)|BYTES_SH(4), hLab,
- FLOAT_SH(1)|CHANNELS_SH(3)|BYTES_SH(4),
+ FLOAT_SH(1)|CHANNELS_SH(3)|BYTES_SH(4),
INTENT_RELATIVE_COLORIMETRIC,
cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE);
if (bp.cmyk2Lab == NULL) goto Cleanup;
@@ -976,10 +988,10 @@ cmsPipeline* _cmsLinkProfiles(cmsContext ContextID,
// preserve primaries. This solution is not perfect, but works well on most cases.
Intent = SearchIntent(TheIntents[0]);
- if (Intent == NULL) {
- cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported intent '%d'", TheIntents[0]);
- return NULL;
- }
+ if (Intent == NULL) {
+ cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported intent '%d'", TheIntents[0]);
+ return NULL;
+ }
// Call the handler
return Intent ->Link(ContextID, nProfiles, TheIntents, hProfiles, BPC, AdaptationStates, dwFlags);
diff --git a/src/cmsio1.c b/src/cmsio1.c
index 9c7d245..ea92567 100644
--- a/src/cmsio1.c
+++ b/src/cmsio1.c
@@ -121,7 +121,7 @@ cmsBool _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile)
return TRUE;
}
- return _cmsAdaptationMatrix(Dest, NULL, cmsD50_XYZ(), White);
+ return _cmsAdaptationMatrix(Dest, NULL, White, cmsD50_XYZ());
}
}
diff --git a/src/cmsopt.c b/src/cmsopt.c
index 4c28a07..1b0d33e 100644
--- a/src/cmsopt.c
+++ b/src/cmsopt.c
@@ -434,13 +434,15 @@ cmsBool PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[],
return TRUE;
}
-// Auxiliar, to see if two values are equal.
+// Auxiliar, to see if two values are equal or very different
static
cmsBool WhitesAreEqual(int n, cmsUInt16Number White1[], cmsUInt16Number White2[] )
{
int i;
for (i=0; i < n; i++) {
+
+ if (abs(White1[i] - White2[i]) > 0xf000) return TRUE; // Values are so extremly different that the fixup should be avoided
if (White1[i] != White2[i]) return FALSE;
}
return TRUE;
diff --git a/src/cmsxform.c b/src/cmsxform.c
index e7f30c5..8a76dae 100644
--- a/src/cmsxform.c
+++ b/src/cmsxform.c
@@ -31,8 +31,8 @@
// Alarm codes for 16-bit transformations, because the fixed range of containers there are
// no values left to mark out of gamut. volatile is C99 per 6.2.5
-static volatile cmsUInt16Number Alarm[cmsMAXCHANNELS];
-static volatile cmsFloat64Number GlobalAdaptationState = 0;
+static volatile cmsUInt16Number Alarm[cmsMAXCHANNELS] = { 0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static volatile cmsFloat64Number GlobalAdaptationState = 1;
// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine
cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d)
diff --git a/testbed/testcms2.c b/testbed/testcms2.c
index 13fd7fc..fd6c16c 100644
--- a/testbed/testcms2.c
+++ b/testbed/testcms2.c
@@ -75,8 +75,18 @@ static cmsUInt32Number SingleHit, MaxAllocated=0, TotalMemory=0;
typedef struct {
cmsUInt32Number KeepSize;
cmsContext WhoAllocated;
- cmsUInt32Number Align8_1; // Some systems do need pointers aligned to 8-byte boundaries.
- cmsUInt32Number Align8_2;
+
+ union {
+ cmsUInt64Number HiSparc;
+
+ // '_cmsMemoryBlock' block is prepended by the
+ // allocator for any requested size. Thus, union holds
+ // "widest" type to guarantee proper '_cmsMemoryBlock'
+ // alignment for any requested size.
+
+ } alignment;
+
+
} _cmsMemoryBlock;
#define SIZE_OF_MEM_HEADER (sizeof(_cmsMemoryBlock))
@@ -5975,6 +5985,7 @@ int CheckRGBPrimaries(void)
cmsCIExyYTRIPLE tripxyY;
cmsBool result;
+ cmsSetAdaptationState(0);
hsRGB = cmsCreate_sRGBProfileTHR(DbgThread());
if (!hsRGB) return 0;