From 1e4fab616c4eef7e3ea131386e92fcf34c54f96e Mon Sep 17 00:00:00 2001 From: Marti Maria Date: Tue, 23 Aug 2011 16:14:38 +0200 Subject: Abs. colorimetric intent fixup --- src/cmscnvrt.c | 56 +++++++++++++++++++++++++++++++++--------------------- src/cmsio1.c | 2 +- src/cmsopt.c | 4 +++- src/cmsxform.c | 4 ++-- testbed/testcms2.c | 15 +++++++++++++-- 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; -- cgit v1.2.1