622
622
#define JACOBIAN_EPSILON 0.001
623
623
#define INVERSION_MAX_ITERATIONS 30
626
// Evaluates the CLUT part of a LUT (3x3 only)
629
void EvalLUTdoubleK(LPLUT Lut, const VEC3* In, WORD FixedK, LPVEC3 Out)
631
WORD wIn[4], wOut[3];
633
wIn[0] = (WORD) floor(In ->n[0] * 65535.0 + 0.5);
634
wIn[1] = (WORD) floor(In ->n[1] * 65535.0 + 0.5);
635
wIn[2] = (WORD) floor(In ->n[2] * 65535.0 + 0.5);
638
cmsEvalLUT(Lut, wIn, wOut);
640
Out ->n[0] = (double) wOut[0] / 65535.0;
641
Out ->n[1] = (double) wOut[1] / 65535.0;
642
Out ->n[2] = (double) wOut[2] / 65535.0;
646
627
// Increment with reflexion on boundary
662
// Builds a Jacobian CMY->Lab
665
void ComputeJacobian(LPLUT Lut, LPMAT3 Jacobian, const VEC3* Colorant, WORD K)
668
double DeltaColorant;
672
EvalLUTdoubleK(Lut, Colorant, K, &Lab);
675
for (j = 0; j < 3; j++) {
677
ColorantD.n[0] = Colorant ->n[0];
678
ColorantD.n[1] = Colorant ->n[1];
679
ColorantD.n[2] = Colorant ->n[2];
681
IncDelta(&ColorantD.n[j]);
683
EvalLUTdoubleK(Lut, &ColorantD, K, &LabD);
685
DeltaColorant = (Colorant->n[j] - ColorantD.n[j]);
687
for (i = 0; i < 3; i++) {
689
double DeltaTristim = (Lab.n[i] - LabD.n[i]);
691
Jacobian->v[i].n[j] = (DeltaTristim / DeltaColorant);
698
644
void ToEncoded(WORD Encoded[3], LPVEC3 Float)
854
LCMSAPI double LCMSEXPORT cmsEvalLUTreverse2(LPLUT Lut, WORD Target[], WORD Result[], LPWORD Hint)
857
double error, LastError;
859
VEC3 Goal, TestPoint, x;
860
MAT3 Jacobian, JacobianInverse;
867
// This is our Lab goal
868
FromEncoded(&Goal, Target);
870
// Special case for CMYK->Lab
872
if (Lut ->InputChan == 4)
878
// Take the hint as starting point if specified
882
// Begin at any point, we choose 1/3 of neutral CMY gray
884
x.n[0] = x.n[1] = x.n[2] = 0.3;
888
FromEncoded(&x, Hint);
896
for (i = 0; i < INVERSION_MAX_ITERATIONS; i++) {
899
EvalLUTdoubleK(Lut, &x, FixedK, &fx);
902
error = VEC3distance(&fx, &Goal);
904
// If not convergent, return last safe value
905
if (error >= LastError)
908
// Keep latest values
911
ToEncoded(LastResult, &x);
912
LastResult[3] = FixedK;
916
ComputeJacobian(Lut, &Jacobian, &x, FixedK);
919
MAT3eval(&TestPoint, &Jacobian, &x);
922
TestPoint.n[0] += (Goal.n[0] - fx.n[0]);
923
TestPoint.n[1] += (Goal.n[1] - fx.n[1]);
924
TestPoint.n[2] += (Goal.n[2] - fx.n[2]);
926
VEC3saturate(&TestPoint);
929
if (MAT3inverse(&Jacobian, &JacobianInverse) < 0) {
936
// Obtain x from current point
937
MAT3eval(&x, &JacobianInverse, &TestPoint);
943
Result[0] = LastResult[0];
944
Result[1] = LastResult[1];
945
Result[2] = LastResult[2];
946
Result[3] = LastResult[3];