diff options
Diffstat (limited to 'src/libs/lprof/cmsmntr.cpp')
-rw-r--r-- | src/libs/lprof/cmsmntr.cpp | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/src/libs/lprof/cmsmntr.cpp b/src/libs/lprof/cmsmntr.cpp new file mode 100644 index 00000000..ed14ed50 --- /dev/null +++ b/src/libs/lprof/cmsmntr.cpp @@ -0,0 +1,371 @@ +/* */ +/* Little cms - profiler construction set */ +/* Copyright (C) 1998-2001 Marti Maria <[email protected]> */ +/* */ +/* THIS SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY */ +/* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. */ +/* */ +/* IN NO EVENT SHALL MARTI MARIA BE LIABLE FOR ANY SPECIAL, INCIDENTAL, */ +/* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, */ +/* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, */ +/* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF */ +/* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE */ +/* OF THIS SOFTWARE. */ +/* */ +/* This file is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +/* */ +/* As a special exception to the GNU General Public License, if you */ +/* distribute this file as part of a program that contains a */ +/* configuration script generated by Autoconf, you may include it under */ +/* the same distribution terms that you use for the rest of that program. */ +/* */ +/* Version 1.09a */ + + +#include "lcmsprf.h" + + +static +void ClampRGB(LPVEC3 RGB) +{ + int i; + + for (i=0; i < 3; i++) { + + if (RGB->n[i] > 1.0) + RGB->n[i] = 1.0; + if (RGB->n[i] < 0) + RGB->n[i] = 0; + } +} + + +static +int RegressionSamplerA2B(WORD In[], WORD Out[], LPVOID Cargo) +{ + cmsCIEXYZ xyz; + cmsCIELab Lab; + VEC3 RGB, RGBlinear, vxyz; + LPMONITORPROFILERDATA sys = (LPMONITORPROFILERDATA) Cargo; + + + RGB.n[0] = _cmsxSaturate65535To255(In[0]); + RGB.n[1] = _cmsxSaturate65535To255(In[1]); + RGB.n[2] = _cmsxSaturate65535To255(In[2]); + + cmsxApplyLinearizationTable(RGB.n, sys->PreLab, RGBlinear.n); + cmsxApplyLinearizationTable(RGBlinear.n, sys->Prelinearization, RGBlinear.n); + + RGBlinear.n[0] /= 255.; + RGBlinear.n[1] /= 255.; + RGBlinear.n[2] /= 255.; + + MAT3eval(&vxyz, &sys->PrimariesMatrix, &RGBlinear); + + xyz.X = vxyz.n[0]; + xyz.Y = vxyz.n[1]; + xyz.Z = vxyz.n[2]; + + cmsxChromaticAdaptationAndNormalization(&sys ->hdr, &xyz, false); + + + /* To PCS encoding */ + + cmsXYZ2Lab(NULL, &Lab, &xyz); + cmsFloat2LabEncoded(Out, &Lab); + + + return true; /* And done witch success */ +} + + + + +static +int RegressionSamplerB2A(WORD In[], WORD Out[], LPVOID Cargo) +{ + cmsCIELab Lab; + cmsCIEXYZ xyz; + VEC3 vxyz, RGB; + /* cmsJCh JCh; */ + WORD Lin[3], Llab[3]; + LPMONITORPROFILERDATA sys = (LPMONITORPROFILERDATA) Cargo; + double L; + + + /* Pass L back to 0..0xff00 domain */ + + L = (double) (In[0] * 65280.0) / 65535.0; + In[0] = (WORD) floor(L + .5); + + + /* To float values */ + cmsLabEncoded2Float(&Lab, In); + cmsLab2XYZ(NULL, &xyz, &Lab); + + + cmsxChromaticAdaptationAndNormalization(&sys ->hdr, &xyz, true); + vxyz.n[0] = xyz.X; + vxyz.n[1] = xyz.Y; + vxyz.n[2] = xyz.Z; + + MAT3eval(&RGB, &sys-> PrimariesMatrixRev, &vxyz); + + /* Clamp RGB */ + ClampRGB(&RGB); + + /* Encode output */ + Lin[0] = (WORD) ((double) RGB.n[0] * 65535. + .5); + Lin[1] = (WORD) ((double) RGB.n[1] * 65535. + .5); + Lin[2] = (WORD) ((double) RGB.n[2] * 65535. + .5); + + cmsxApplyLinearizationGamma(Lin, sys ->ReverseTables, Llab); + cmsxApplyLinearizationGamma(Llab, sys ->PreLabRev, Out); + + + return true; /* And done witch success */ +} + + +BOOL cmsxMonitorProfilerInit(LPMONITORPROFILERDATA sys) +{ + + + if (sys == NULL) return false; + ZeroMemory(sys, sizeof(MONITORPROFILERDATA)); + + sys->hdr.DeviceClass = icSigDisplayClass; + sys->hdr.ColorSpace = icSigRgbData; + sys->hdr.PCSType = PT_Lab; + sys->hdr.Medium = MEDIUM_TRANSMISSIVE; + + + /* Default values for generation */ + + sys -> hdr.lUseCIECAM97s = false; + sys -> hdr.CLUTPoints = 16; + + /* Default viewing conditions */ + + sys -> hdr.device.Yb = 20; + sys -> hdr.device.La = 20; + sys -> hdr.device.surround = AVG_SURROUND; + sys -> hdr.device.D_value = 1; /* Complete adaptation */ + + + /* Viewing conditions of PCS */ + cmsxInitPCSViewingConditions(&sys ->hdr); + + strcpy(sys -> hdr.Description, "unknown monitor"); + strcpy(sys -> hdr.Manufacturer, "little cms profiler construction set"); + strcpy(sys -> hdr.Copyright, "No copyright, use freely"); + strcpy(sys -> hdr.Model, "(unknown)"); + + sys -> hdr.ProfileVerbosityLevel = 0; + + return true; +} + + +static +void CreatePrimaryMatrices(LPMONITORPROFILERDATA sys) +{ + cmsCIExyY White; + MAT3 tmp; + + + cmsXYZ2xyY(&White, &sys->hdr.WhitePoint); + cmsBuildRGB2XYZtransferMatrix(&sys -> PrimariesMatrix, &White, &sys->hdr.Primaries); + + CopyMemory(&tmp, &sys -> PrimariesMatrix, sizeof(MAT3)); + MAT3inverse(&tmp, &sys->PrimariesMatrixRev); + +} + + +static +BOOL CreateLUTS(LPMONITORPROFILERDATA sys, LPLUT* A2B, LPLUT* B2A) +{ + LPLUT AToB0 = cmsAllocLUT(); + LPLUT BToA0 = cmsAllocLUT(); + LPGAMMATABLE LabG; + cmsCIExyY xyY; + + + cmsAlloc3DGrid(AToB0, sys->hdr.CLUTPoints, 3, 3); + cmsAlloc3DGrid(BToA0, sys->hdr.CLUTPoints, 3, 3); + + /* cmsAllocLinearTable(AToB0, sys -> Prelinearization, 1); */ + + sys->ReverseTables[0] = cmsReverseGamma(4096, sys ->Prelinearization[0]); + sys->ReverseTables[1] = cmsReverseGamma(4096, sys ->Prelinearization[1]); + sys->ReverseTables[2] = cmsReverseGamma(4096, sys ->Prelinearization[2]); + + /* Prelinearization */ + + LabG = cmsBuildGamma(4096, 3.0); + + sys -> PreLab[0] = cmsJoinGammaEx(LabG, sys ->Prelinearization[0], 4096); + sys -> PreLab[1] = cmsJoinGammaEx(LabG, sys ->Prelinearization[1], 4096); + sys -> PreLab[2] = cmsJoinGammaEx(LabG, sys ->Prelinearization[2], 4096); + + sys -> PreLabRev[0] = cmsJoinGammaEx(sys ->Prelinearization[0], LabG, 4096); + sys -> PreLabRev[1] = cmsJoinGammaEx(sys ->Prelinearization[1], LabG, 4096); + sys -> PreLabRev[2] = cmsJoinGammaEx(sys ->Prelinearization[2], LabG, 4096); + + + cmsFreeGamma(LabG); + + + cmsAllocLinearTable(AToB0, sys->PreLabRev, 1); + cmsAllocLinearTable(BToA0, sys->PreLab, 2); + + + /* Set CIECAM97s parameters */ + + sys -> hdr.device.whitePoint.X = sys -> hdr.WhitePoint.X * 100.; + sys -> hdr.device.whitePoint.Y = sys -> hdr.WhitePoint.Y * 100.; + sys -> hdr.device.whitePoint.Z = sys -> hdr.WhitePoint.Z * 100.; + + + /* Normalize White point for CIECAM97s model */ + cmsXYZ2xyY(&xyY, &sys -> hdr.device.whitePoint); + xyY.Y = 100.; + cmsxyY2XYZ(&sys -> hdr.device.whitePoint, &xyY); + + + sys->hdr.hDevice = cmsCIECAM97sInit(&sys->hdr.device); + sys->hdr.hPCS = cmsCIECAM97sInit(&sys->hdr.PCS); + + + cmsSample3DGrid(AToB0, RegressionSamplerA2B, sys, 0); + cmsSample3DGrid(BToA0, RegressionSamplerB2A, sys, 0); + + cmsCIECAM97sDone(sys->hdr.hDevice); + cmsCIECAM97sDone(sys->hdr.hPCS); + + cmsAddTag(sys->hdr.hProfile, icSigAToB0Tag, AToB0); + cmsAddTag(sys->hdr.hProfile, icSigBToA0Tag, BToA0); + + /* This is the 0xff00 trick to map white at lattice point */ + BToA0 ->Matrix.v[0].n[0] = DOUBLE_TO_FIXED((65535.0 / 65280.0)); + + *A2B = AToB0; + *B2A = BToA0; + + cmsFreeGammaTriple(sys->ReverseTables); + cmsFreeGammaTriple(sys->PreLab); + cmsFreeGammaTriple(sys->PreLabRev); + return true; +} + + + +BOOL cmsxMonitorProfilerDo(LPMONITORPROFILERDATA sys) +{ + + cmsCIExyY White; + LPLUT AToB0, BToA0; + + AToB0 = BToA0 = NULL; + + if (!*sys -> hdr.OutputProfileFile) + return false; + + + if (sys->hdr.ReferenceSheet[0] || sys->hdr.MeasurementSheet[0]) { + + if (sys->hdr.printf) { + + sys->hdr.printf("Loading sheets..."); + + if (sys->hdr.ReferenceSheet[0]) + sys->hdr.printf("Reference sheet: %s", sys->hdr.ReferenceSheet); + if (sys->hdr.MeasurementSheet[0]) + sys->hdr.printf("Measurement sheet: %s", sys->hdr.MeasurementSheet); + } + + + if (!cmsxComputeMatrixShaper(sys -> hdr.ReferenceSheet, + sys -> hdr.MeasurementSheet, + MEDIUM_TRANSMISSIVE, + sys -> Prelinearization, + &sys -> hdr.WhitePoint, + &sys -> hdr.BlackPoint, + &sys -> hdr.Primaries)) return false; + + if (sys->hdr.printf) { + + char Buffer[1024]; + _cmsIdentifyWhitePoint(Buffer, &sys ->hdr.WhitePoint); + sys->hdr.printf("%s", Buffer); + + sys->hdr.printf("Primaries: R:%1.2g, %1.2g G:%1.2g, %1.2g B:%1.2g, %1.2g", + sys->hdr.Primaries.Red.x,sys->hdr.Primaries.Red.y, + sys->hdr.Primaries.Green.x, sys->hdr.Primaries.Green.y, + sys->hdr.Primaries.Blue.x, sys->hdr.Primaries.Blue.y); + } + + } + + + CreatePrimaryMatrices(sys); + + + cmsXYZ2xyY(&White, &sys->hdr.WhitePoint); + + sys->hdr.hProfile = cmsCreateRGBProfile(&White, + &sys-> hdr.Primaries, + sys -> Prelinearization); + + cmsSetDeviceClass(sys->hdr.hProfile, sys->hdr.DeviceClass); + + if (sys -> hdr.lUseCIECAM97s) + sys->hdr.PCSType = PT_Lab; + else + sys->hdr.PCSType = PT_XYZ; + + cmsSetPCS(sys->hdr.hProfile, _cmsICCcolorSpace(sys->hdr.PCSType)); + + if (sys -> hdr.lUseCIECAM97s) + CreateLUTS(sys, &AToB0, &BToA0); + + + cmsxEmbedTextualInfo(&sys ->hdr); + + cmsAddTag(sys->hdr.hProfile, icSigMediaWhitePointTag, &sys->hdr.WhitePoint); + cmsAddTag(sys->hdr.hProfile, icSigMediaBlackPointTag, &sys->hdr.BlackPoint); + + + if (sys->hdr.ProfileVerbosityLevel >= 2) { + + cmsxEmbedCharTarget(&sys ->hdr); + } + + + _cmsSaveProfile(sys->hdr.hProfile, sys->hdr.OutputProfileFile); + cmsCloseProfile(sys->hdr.hProfile); + sys->hdr.hProfile = NULL; + + + if (AToB0) cmsFreeLUT(AToB0); + if (BToA0) cmsFreeLUT(BToA0); + + if (sys ->Prelinearization[0]) + cmsFreeGammaTriple(sys -> Prelinearization); + + return true; +} |