void cmsLab2XYZEncoded(WORD Lab[3], WORD XYZ[3]) { double L, a, b; double X, Y, Z, x, y, z; L = ((double) Lab[0] * 100.0) / 65280.0; if (L==0.0) { XYZ[0] = 0; XYZ[1] = 0; XYZ[2] = 0; return; } a = ((double) Lab[1] / 256.0) - 128.0; b = ((double) Lab[2] / 256.0) - 128.0; y = (L + 16.) / 116.0; x = y + 0.002 * a; z = y - 0.005 * b; X = f_1(x) * D50X; Y = f_1(y) * D50Y; Z = f_1(z) * D50Z; // Convert to 1.15 fixed format PCS XYZ[0] = _cmsClampWord((int) floor(X * 32768.0 + 0.5)); XYZ[1] = _cmsClampWord((int) floor(Y * 32768.0 + 0.5)); XYZ[2] = _cmsClampWord((int) floor(Z * 32768.0 + 0.5)); }
static void AllSmeltedBehaviour(LPMATSHAPER MatShaper, WORD In[], WORD Out[]) { WORD tmp[3]; WVEC3 InVect, OutVect; if (MatShaper -> dwFlags & MATSHAPER_HASINPSHAPER) { InVect.n[VX] = cmsLinearInterpFixed(In[0], MatShaper -> L2[0], &MatShaper -> p2_16); InVect.n[VY] = cmsLinearInterpFixed(In[1], MatShaper -> L2[1], &MatShaper -> p2_16); InVect.n[VZ] = cmsLinearInterpFixed(In[2], MatShaper -> L2[2], &MatShaper -> p2_16); } else { InVect.n[VX] = ToFixedDomain(In[0]); InVect.n[VY] = ToFixedDomain(In[1]); InVect.n[VZ] = ToFixedDomain(In[2]); } if (MatShaper -> dwFlags & MATSHAPER_HASMATRIX) { MAT3evalW(&OutVect, &MatShaper -> Matrix, &InVect); } else { OutVect.n[VX] = InVect.n[VX]; OutVect.n[VY] = InVect.n[VY]; OutVect.n[VZ] = InVect.n[VZ]; } tmp[0] = _cmsClampWord(FromFixedDomain(OutVect.n[VX])); tmp[1] = _cmsClampWord(FromFixedDomain(OutVect.n[VY])); tmp[2] = _cmsClampWord(FromFixedDomain(OutVect.n[VZ])); if (MatShaper -> dwFlags & MATSHAPER_HASSHAPER) { Out[0] = cmsLinearInterpLUT16(tmp[0], MatShaper -> L[0], &MatShaper -> p16); Out[1] = cmsLinearInterpLUT16(tmp[1], MatShaper -> L[1], &MatShaper -> p16); Out[2] = cmsLinearInterpLUT16(tmp[2], MatShaper -> L[2], &MatShaper -> p16); } else { Out[0] = tmp[0]; Out[1] = tmp[1]; Out[2] = tmp[2]; } }
static void OutputBehaviour(LPMATSHAPER MatShaper, WORD In[], WORD Out[]) { WVEC3 InVect, OutVect; int i; // We need to convert from XYZ to RGB, here we must // shift << 1 to pass between 1.15 to 15.16 formats InVect.n[VX] = (Fixed32) In[0] << 1; InVect.n[VY] = (Fixed32) In[1] << 1; InVect.n[VZ] = (Fixed32) In[2] << 1; if (MatShaper -> dwFlags & MATSHAPER_HASMATRIX) { MAT3evalW(&OutVect, &MatShaper -> Matrix, &InVect); } else { OutVect = InVect; } if (MatShaper -> dwFlags & MATSHAPER_HASSHAPER) { for (i=0; i < 3; i++) { Out[i] = cmsLinearInterpLUT16( _cmsClampWord(FromFixedDomain(OutVect.n[i])), MatShaper -> L[i], &MatShaper ->p16); } } else { // Result from fixed domain to RGB Out[0] = _cmsClampWord(FromFixedDomain(OutVect.n[VX])); Out[1] = _cmsClampWord(FromFixedDomain(OutVect.n[VY])); Out[2] = _cmsClampWord(FromFixedDomain(OutVect.n[VZ])); } }
void LCMSEXPORT cmsEvalLUT(LPLUT Lut, WORD In[], WORD Out[]) { register unsigned int i; WORD StageABC[MAXCHANNELS], StageLMN[MAXCHANNELS]; // Try to speedup things on plain devicelinks if (Lut ->wFlags == LUT_HAS3DGRID) { Lut ->CLut16params.Interp3D(In, Out, Lut -> T, &Lut -> CLut16params); return; } // Nope, evaluate whole LUT for (i=0; i < Lut -> InputChan; i++) StageABC[i] = In[i]; if (Lut ->wFlags & LUT_V4_OUTPUT_EMULATE_V2) { // Clamp Lab to avoid overflow if (StageABC[0] > 0xFF00) StageABC[0] = 0xFF00; StageABC[0] = (WORD) FROM_V2_TO_V4(StageABC[0]); StageABC[1] = (WORD) FROM_V2_TO_V4(StageABC[1]); StageABC[2] = (WORD) FROM_V2_TO_V4(StageABC[2]); } if (Lut ->wFlags & LUT_V2_OUTPUT_EMULATE_V4) { StageABC[0] = (WORD) FROM_V4_TO_V2(StageABC[0]); StageABC[1] = (WORD) FROM_V4_TO_V2(StageABC[1]); StageABC[2] = (WORD) FROM_V4_TO_V2(StageABC[2]); } // Matrix handling. if (Lut -> wFlags & LUT_HASMATRIX) { WVEC3 InVect, OutVect; // In LUT8 here comes the special gray axis fixup if (Lut ->FixGrayAxes) { StageABC[1] = _cmsClampWord(StageABC[1] - 128); StageABC[2] = _cmsClampWord(StageABC[2] - 128); } // Matrix InVect.n[VX] = ToFixedDomain(StageABC[0]); InVect.n[VY] = ToFixedDomain(StageABC[1]); InVect.n[VZ] = ToFixedDomain(StageABC[2]); MAT3evalW(&OutVect, &Lut -> Matrix, &InVect); // PCS in 1Fixed15 format, adjusting StageABC[0] = _cmsClampWord(FromFixedDomain(OutVect.n[VX])); StageABC[1] = _cmsClampWord(FromFixedDomain(OutVect.n[VY])); StageABC[2] = _cmsClampWord(FromFixedDomain(OutVect.n[VZ])); } // First linearization if (Lut -> wFlags & LUT_HASTL1) { for (i=0; i < Lut -> InputChan; i++) StageABC[i] = cmsLinearInterpLUT16(StageABC[i], Lut -> L1[i], &Lut -> In16params); } // Mat3, Ofs3, L3 processing if (Lut ->wFlags & LUT_HASMATRIX3) { WVEC3 InVect, OutVect; InVect.n[VX] = ToFixedDomain(StageABC[0]); InVect.n[VY] = ToFixedDomain(StageABC[1]); InVect.n[VZ] = ToFixedDomain(StageABC[2]); MAT3evalW(&OutVect, &Lut -> Mat3, &InVect); OutVect.n[VX] += Lut ->Ofs3.n[VX]; OutVect.n[VY] += Lut ->Ofs3.n[VY]; OutVect.n[VZ] += Lut ->Ofs3.n[VZ]; StageABC[0] = _cmsClampWord(FromFixedDomain(OutVect.n[VX])); StageABC[1] = _cmsClampWord(FromFixedDomain(OutVect.n[VY])); StageABC[2] = _cmsClampWord(FromFixedDomain(OutVect.n[VZ])); } if (Lut ->wFlags & LUT_HASTL3) { for (i=0; i < Lut -> InputChan; i++) StageABC[i] = cmsLinearInterpLUT16(StageABC[i], Lut -> L3[i], &Lut -> L3params); } if (Lut -> wFlags & LUT_HAS3DGRID) { Lut ->CLut16params.Interp3D(StageABC, StageLMN, Lut -> T, &Lut -> CLut16params); } else { for (i=0; i < Lut -> InputChan; i++) StageLMN[i] = StageABC[i]; } // Mat4, Ofs4, L4 processing if (Lut ->wFlags & LUT_HASTL4) { for (i=0; i < Lut -> OutputChan; i++) StageLMN[i] = cmsLinearInterpLUT16(StageLMN[i], Lut -> L4[i], &Lut -> L4params); } if (Lut ->wFlags & LUT_HASMATRIX4) { WVEC3 InVect, OutVect; InVect.n[VX] = ToFixedDomain(StageLMN[0]); InVect.n[VY] = ToFixedDomain(StageLMN[1]); InVect.n[VZ] = ToFixedDomain(StageLMN[2]); MAT3evalW(&OutVect, &Lut -> Mat4, &InVect); OutVect.n[VX] += Lut ->Ofs4.n[VX]; OutVect.n[VY] += Lut ->Ofs4.n[VY]; OutVect.n[VZ] += Lut ->Ofs4.n[VZ]; StageLMN[0] = _cmsClampWord(FromFixedDomain(OutVect.n[VX])); StageLMN[1] = _cmsClampWord(FromFixedDomain(OutVect.n[VY])); StageLMN[2] = _cmsClampWord(FromFixedDomain(OutVect.n[VZ])); } // Last linearitzation if (Lut -> wFlags & LUT_HASTL2) { for (i=0; i < Lut -> OutputChan; i++) Out[i] = cmsLinearInterpLUT16(StageLMN[i], Lut -> L2[i], &Lut -> Out16params); } else { for (i=0; i < Lut -> OutputChan; i++) Out[i] = StageLMN[i]; } if (Lut ->wFlags & LUT_V4_INPUT_EMULATE_V2) { Out[0] = (WORD) FROM_V4_TO_V2(Out[0]); Out[1] = (WORD) FROM_V4_TO_V2(Out[1]); Out[2] = (WORD) FROM_V4_TO_V2(Out[2]); } if (Lut ->wFlags & LUT_V2_INPUT_EMULATE_V4) { Out[0] = (WORD) FROM_V2_TO_V4(Out[0]); Out[1] = (WORD) FROM_V2_TO_V4(Out[1]); Out[2] = (WORD) FROM_V2_TO_V4(Out[2]); } }