summaryrefslogtreecommitdiffstats
path: root/src/libs/lprof/cmsoutl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/lprof/cmsoutl.cpp')
-rw-r--r--src/libs/lprof/cmsoutl.cpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/src/libs/lprof/cmsoutl.cpp b/src/libs/lprof/cmsoutl.cpp
new file mode 100644
index 00000000..248aaa04
--- /dev/null
+++ b/src/libs/lprof/cmsoutl.cpp
@@ -0,0 +1,284 @@
+/* */
+/* Little cms - profiler construction set */
+/* Copyright (C) 1998-2001 Marti Maria <marti@littlecms.com> */
+/* */
+/* 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 */
+/* */
+/* Incremental Interpolator */
+
+#include "lcmsprf.h"
+
+
+/* Res points to a result in XYZ or Lab */
+
+BOOL cdecl cmsxRegressionInterpolatorRGB(LPMEASUREMENT m,
+ int ColorSpace,
+ int RegressionTerms,
+ BOOL lUseLocalPatches,
+ int MinPatchesToCollect,
+ double r, double g, double b,
+ void* Res);
+
+
+/* -------------------------------------------------------------- Implementation */
+
+/* #define DEBUG 1 */
+
+/* Estimate regression matrix */
+static
+void EstimateRegression(LPMEASUREMENT m, double r, double g, double b,
+ int ColorSpace,
+ LPMATN* ptfm,
+ int nterms,
+ BOOL lIncludeAllPatches,
+ int MinPatchesToCollect)
+{
+ int nCollected;
+ MLRSTATISTICS maxAns;
+ int ToCollect;
+ SETOFPATCHES collected = cmsxPCollBuildSet(m, false);
+ SETOFPATCHES allowed = cmsxPCollBuildSet(m, true);
+ BOOL rc;
+ BOOL lPatchesExhausted = false;
+
+
+ CopyMemory(allowed, m -> Allowed, m->nPatches*sizeof(BOOL));
+
+ *ptfm = NULL;
+
+ ToCollect = max(MinPatchesToCollect, (nterms + 1));
+
+ do {
+
+ if (lIncludeAllPatches) {
+
+ CopyMemory(collected, allowed, m->nPatches*sizeof(BOOL));
+ lPatchesExhausted = true;
+ ToCollect = nCollected = m->nPatches;
+ }
+ else
+ {
+
+ nCollected = cmsxPCollPatchesNearRGB(m, m -> Allowed,
+ r, g, b,
+ ToCollect, collected);
+
+ if (nCollected < ToCollect) { /* No more patches available */
+ lPatchesExhausted = true;
+ }
+ else {
+ ToCollect = nCollected + 1; /* Start from here in next iteration */
+ }
+ }
+
+ /* We are going always 3 -> 3 for now.... */
+ rc = cmsxRegressionCreateMatrix(m, collected, nterms, ColorSpace, ptfm, &maxAns);
+
+
+ /* Does fit? */
+ if ((rc == false) || maxAns.R2adj < 0.95 || maxAns.R2adj > 1.0) {
+
+ maxAns.R2adj = -100; /* No, repeat */
+ }
+
+
+ } while (!lPatchesExhausted && maxAns.R2adj < 0.95);
+
+#ifdef DEBUG
+ printf("R2adj: %g, F: %g\n", maxAns.R2adj, maxAns.F);
+#endif
+
+ free(collected);
+ free(allowed);
+}
+
+
+
+BOOL cmsxRegressionInterpolatorRGB(LPMEASUREMENT m,
+ int ColorSpace,
+ int RegressionTerms,
+ BOOL lUseLocalPatches,
+ int MinPatchesToCollect,
+ double r, double g, double b,
+ void* Res)
+{
+ LPMATN tfm = NULL;
+
+
+ EstimateRegression(m, r, g, b, ColorSpace, &tfm, RegressionTerms,
+ !lUseLocalPatches, MinPatchesToCollect);
+
+ if (tfm == NULL) return false;
+
+ switch (ColorSpace) {
+
+ case PT_Lab:
+
+ if (!cmsxRegressionRGB2Lab(r, g, b, tfm, (LPcmsCIELab) Res)) return false;
+ break;
+
+ case PT_XYZ:
+ if (!cmsxRegressionRGB2XYZ(r, g, b, tfm, (LPcmsCIEXYZ) Res)) return false;
+ break;
+
+ default:
+ return false;
+ }
+
+ MATNfree(tfm);
+
+
+#ifdef DEBUG
+ printf("INTERPOLATED RGB %g,%g,%g Lab %g, %g, %g \n", r , g, b,
+ Lab->L, Lab->a, Lab->b);
+
+#endif
+ return true;
+}
+
+
+/* Check the results of a given regression matrix */
+
+static
+void CheckOneRegressionMatrix(LPPROFILERCOMMONDATA hdr, LPMATN Matrix,
+ double* Mean, double* Std, double* Max)
+{
+
+ cmsCIELab Lab;
+ cmsCIEXYZ XYZ;
+ double Hit, sum, sum2, n, dE;
+ int i;
+ cmsCIEXYZ D50;
+
+
+ D50.X = cmsD50_XYZ() -> X* 100.;
+ D50.Y = cmsD50_XYZ() -> Y* 100.;
+ D50.Z = cmsD50_XYZ() -> Z* 100.;
+
+ Hit = sum = sum2 = n = 0;
+ for (i=0; i < hdr -> m.nPatches; i++) {
+
+ if (hdr -> m.Allowed[i]) {
+
+ LPPATCH p = hdr -> m.Patches + i;
+
+ if (hdr -> PCSType == PT_Lab) {
+
+ WORD ProfileLabEncoded[3];
+
+ cmsxRegressionRGB2Lab(p -> Colorant.RGB[0],
+ p -> Colorant.RGB[1],
+ p -> Colorant.RGB[2],
+ Matrix, &Lab);
+
+ cmsFloat2LabEncoded(ProfileLabEncoded, &Lab);
+ cmsLabEncoded2Float(&Lab, ProfileLabEncoded);
+
+ dE = cmsDeltaE(&Lab, &p ->Lab);
+ }
+ else {
+ cmsCIELab Lab2;
+
+ cmsxRegressionRGB2XYZ(p -> Colorant.RGB[0],
+ p -> Colorant.RGB[1],
+ p -> Colorant.RGB[2],
+ Matrix, &XYZ);
+ _cmsxClampXYZ100(&XYZ);
+
+ cmsXYZ2Lab(&D50, &Lab, &XYZ);
+ cmsXYZ2Lab(&D50, &Lab2, &p ->XYZ);
+
+ dE = cmsDeltaE(&Lab, &Lab2);
+ }
+
+
+ if (dE > Hit)
+ Hit = dE;
+
+ sum += dE;
+ sum2 += dE * dE;
+ n = n + 1;
+
+ }
+ }
+
+ *Mean = sum / n;
+ *Std = sqrt((n * sum2 - sum * sum) / (n*(n-1)));
+ *Max = Hit;
+
+}
+
+
+/* Trial-and-error in order to get best number of terms. */
+
+int cmsxFindOptimumNumOfTerms(LPPROFILERCOMMONDATA hdr, int nMaxTerms, BOOL* lAllOk)
+{
+ int i, BestTerms;
+ BOOL rc;
+ LPMATN Matrix = NULL;
+ MLRSTATISTICS Stat;
+ double dEmean, dEStd, dEHit, Best;
+ BOOL lOneFound;
+
+
+ BestTerms = 4;
+ Best = 1000.;
+ lOneFound = false;
+
+ for (i=4; i <= nMaxTerms; i++) { /* 55 */
+
+ rc = cmsxRegressionCreateMatrix(&hdr -> m, hdr -> m.Allowed,
+ i, hdr -> PCSType, &Matrix, &Stat);
+
+ if (rc && Stat.R2adj < 1 && Stat.R2adj > 0.6) {
+
+ CheckOneRegressionMatrix(hdr, Matrix, &dEmean, &dEStd, &dEHit);
+
+ if (dEStd < Best && dEHit < 50.) {
+
+ Best = dEStd;
+ BestTerms = i;
+ lOneFound = true;
+ }
+
+ }
+ MATNfree(Matrix);
+ Matrix = NULL;
+ }
+
+ *lAllOk = lOneFound;
+
+ return BestTerms;
+}
+
+