diff options
Diffstat (limited to 'src/libs/lprof/cmsprf.cpp')
-rw-r--r-- | src/libs/lprof/cmsprf.cpp | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/src/libs/lprof/cmsprf.cpp b/src/libs/lprof/cmsprf.cpp new file mode 100644 index 00000000..527fc8e8 --- /dev/null +++ b/src/libs/lprof/cmsprf.cpp @@ -0,0 +1,439 @@ +/* */ +/* 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 library is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Lesser General Public */ +/* License as published by the Free Software Foundation; either */ +/* version 2 of the License, or (at your option) any later version. */ +/* */ +/* This library 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 */ +/* Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public */ +/* License along with this library; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "lcmsprf.h" + + +double cdecl _cmsxSaturate65535To255(double d); +double cdecl _cmsxSaturate255To65535(double d); + + +void cdecl _cmsxClampXYZ100(LPcmsCIEXYZ xyz); + + +BOOL cdecl cmsxEmbedCharTarget(LPPROFILERCOMMONDATA hdr); +BOOL cdecl cmsxEmbedMatrixShaper(LPPROFILERCOMMONDATA hdr); +BOOL cdecl cmsxEmbedTextualInfo(LPPROFILERCOMMONDATA hdr); + +/* ----------------------------------------------------------------- Implementation */ + + +/* Convert from 0.0..65535.0 to 0.0..255.0 */ + +double _cmsxSaturate65535To255(double d) +{ + double v; + + v = d / 257.0; + + if (v < 0) return 0; + if (v > 255.0) return 255.0; + + return v; +} + + +double _cmsxSaturate255To65535(double d) +{ + double v; + + v = d * 257.0; + + if (v < 0) return 0; + if (v > 65535.0) return 65535.0; + + return v; +} + + + +/* Cut off absurd values */ + +void _cmsxClampXYZ100(LPcmsCIEXYZ xyz) +{ + + if (xyz->X > 199.996) + xyz->X = 199.996; + + if (xyz->Y > 199.996) + xyz->Y = 199.996; + + if (xyz->Z > 199.996) + xyz->Z = 199.996; + + if (xyz->Y < 0) + xyz->Y = 0; + + if (xyz->X < 0) + xyz->X = 0; + + if (xyz->Z < 0) + xyz->Z = 0; + +} + +static +int xfilelength(int fd) +{ +#ifdef _MSC_VER + return _filelength(fd); +#else + struct stat sb; + if (fstat(fd, &sb) < 0) + return(-1); + return(sb.st_size); +#endif + + +} + + +BOOL cmsxEmbedCharTarget(LPPROFILERCOMMONDATA hdr) +{ + LCMSHANDLE it8 = cmsxIT8Alloc(); + LPBYTE mem; + size_t size, readed; + FILE* f; + BOOL lFreeOnExit = false; + + + if (!hdr->m.Patches) { + + if (!hdr ->ReferenceSheet[0] && !hdr->MeasurementSheet[0]) return false; + + if (cmsxPCollBuildMeasurement(&hdr ->m, + hdr->ReferenceSheet, + hdr->MeasurementSheet, + PATCH_HAS_RGB|PATCH_HAS_XYZ) == false) return false; + lFreeOnExit = true; + + } + + cmsxIT8SetSheetType(it8,"LCMSEMBED"); + cmsxIT8SetProperty(it8, "ORIGINATOR", (const char *) "Little cms"); + cmsxIT8SetProperty(it8, "DESCRIPTOR", (const char *) hdr -> Description); + cmsxIT8SetProperty(it8, "MANUFACTURER", (const char *) hdr ->Manufacturer); + + cmsxPCollSaveToSheet(&hdr->m, it8); + cmsxIT8SaveToFile(it8, "TMP00.IT8"); + cmsxIT8Free(it8); + + f = fopen("TMP00.IT8", "rb"); + size = xfilelength(fileno(f)); + mem = (unsigned char*) malloc(size + 1); // C->C++ : fixed cast + readed = fread(mem, 1, size, f); + fclose(f); + + mem[readed] = 0; + unlink("TMP00.IT8"); + + cmsAddTag(hdr->hProfile, icSigCharTargetTag, mem); + free(mem); + + if (lFreeOnExit) { + + cmsxPCollFreeMeasurements(&hdr->m); + } + + return true; +} + + +static +BOOL ComputeColorantMatrix(LPcmsCIEXYZTRIPLE Colorants, + LPcmsCIExyY WhitePoint, + LPcmsCIExyYTRIPLE Primaries) +{ + MAT3 MColorants; + + if (!cmsBuildRGB2XYZtransferMatrix(&MColorants, WhitePoint, Primaries)) + { + return false; + } + + + cmsAdaptMatrixToD50(&MColorants, WhitePoint); + + Colorants->Red.X = MColorants.v[0].n[0]; + Colorants->Red.Y = MColorants.v[1].n[0]; + Colorants->Red.Z = MColorants.v[2].n[0]; + + Colorants->Green.X = MColorants.v[0].n[1]; + Colorants->Green.Y = MColorants.v[1].n[1]; + Colorants->Green.Z = MColorants.v[2].n[1]; + + Colorants->Blue.X = MColorants.v[0].n[2]; + Colorants->Blue.Y = MColorants.v[1].n[2]; + Colorants->Blue.Z = MColorants.v[2].n[2]; + + return true; + +} + + +BOOL cmsxEmbedMatrixShaper(LPPROFILERCOMMONDATA hdr) +{ + cmsCIEXYZTRIPLE Colorant; + cmsCIExyY MediaWhite; + + cmsXYZ2xyY(&MediaWhite, &hdr ->WhitePoint); + + if (ComputeColorantMatrix(&Colorant, &MediaWhite, &hdr ->Primaries)) { + + cmsAddTag(hdr ->hProfile, icSigRedColorantTag, &Colorant.Red); + cmsAddTag(hdr ->hProfile, icSigGreenColorantTag, &Colorant.Green); + cmsAddTag(hdr ->hProfile, icSigBlueColorantTag, &Colorant.Blue); + } + + cmsAddTag(hdr ->hProfile, icSigRedTRCTag, hdr ->Gamma[0]); + cmsAddTag(hdr ->hProfile, icSigGreenTRCTag, hdr ->Gamma[1]); + cmsAddTag(hdr ->hProfile, icSigBlueTRCTag, hdr ->Gamma[2]); + + return true; +} + + +BOOL cmsxEmbedTextualInfo(LPPROFILERCOMMONDATA hdr) +{ + if (*hdr ->Description) + cmsAddTag(hdr ->hProfile, icSigProfileDescriptionTag, hdr ->Description); + + if (*hdr ->Copyright) + cmsAddTag(hdr ->hProfile, icSigCopyrightTag, hdr ->Copyright); + + if (*hdr ->Manufacturer) + cmsAddTag(hdr ->hProfile, icSigDeviceMfgDescTag, hdr ->Manufacturer); + + if (*hdr ->Model) + cmsAddTag(hdr ->hProfile, icSigDeviceModelDescTag, hdr ->Model); + + return true; +} + + + +void cmsxChromaticAdaptationAndNormalization(LPPROFILERCOMMONDATA hdr, LPcmsCIEXYZ xyz, BOOL lReverse) +{ + + if (hdr->lUseCIECAM97s) { + + cmsJCh JCh; + + /* Let's CIECAM97s to do the adaptation to D50 */ + + xyz->X *= 100.; + xyz->Y *= 100.; + xyz->Z *= 100.; + + _cmsxClampXYZ100(xyz); + + if (lReverse) { + cmsCIECAM97sForward(hdr->hPCS, xyz, &JCh); + cmsCIECAM97sReverse(hdr->hDevice, &JCh, xyz); + } + else { + + cmsCIECAM97sForward(hdr->hDevice, xyz, &JCh); + cmsCIECAM97sReverse(hdr->hPCS, &JCh, xyz); + } + + _cmsxClampXYZ100(xyz); + + xyz -> X /= 100.; + xyz -> Y /= 100.; + xyz -> Z /= 100.; + + } + else { + + /* Else, use Bradford */ + + if (lReverse) { + cmsAdaptToIlluminant(xyz, cmsD50_XYZ(), &hdr->WhitePoint, xyz); + } + else { + cmsAdaptToIlluminant(xyz, &hdr->WhitePoint, cmsD50_XYZ(), xyz); + } + + } + +} + + +void cmsxInitPCSViewingConditions(LPPROFILERCOMMONDATA hdr) +{ + + hdr->PCS.whitePoint.X = cmsD50_XYZ()->X * 100.; + hdr->PCS.whitePoint.Y = cmsD50_XYZ()->Y * 100.; + hdr->PCS.whitePoint.Z = cmsD50_XYZ()->Z * 100.; + + + hdr->PCS.Yb = 20; /* 20% of surround */ + hdr->PCS.La = 20; /* Adapting field luminance */ + hdr->PCS.surround = AVG_SURROUND; + hdr->PCS.D_value = 1.0; /* Complete adaptation */ + +} + + +/* Build gamut hull by geometric means */ +void cmsxComputeGamutHull(LPPROFILERCOMMONDATA hdr) +{ + int i; + int x0, y0, z0; + int Inside, Outside, Boundaries; + char code; + + + hdr -> hRGBHull = cmsxHullInit(); + + /* For all valid patches, mark RGB knots as 0 */ + for (i=0; i < hdr ->m.nPatches; i++) { + + if (hdr ->m.Allowed[i]) { + + LPPATCH p = hdr ->m.Patches + i; + + + x0 = (int) floor(p->Colorant.RGB[0] + .5); + y0 = (int) floor(p->Colorant.RGB[1] + .5); + z0 = (int) floor(p->Colorant.RGB[2] + .5); + + cmsxHullAddPoint(hdr->hRGBHull, x0, y0, z0); + } + } + + cmsxHullComputeHull(hdr ->hRGBHull); + +/* #ifdef DEBUG */ + cmsxHullDumpVRML(hdr -> hRGBHull, "rgbhull.wrl"); +/* #endif */ + + + + /* A check */ + + Inside = Outside = Boundaries = 0; + /* For all valid patches, mark RGB knots as 0 */ + for (i=0; i < hdr ->m.nPatches; i++) { + + if (hdr ->m.Allowed[i]) { + + LPPATCH p = hdr ->m.Patches + i; + + x0 = (int) floor(p->Colorant.RGB[0] + .5); + y0 = (int) floor(p->Colorant.RGB[1] + .5); + z0 = (int) floor(p->Colorant.RGB[2] + .5); + + code = cmsxHullCheckpoint(hdr -> hRGBHull, x0, y0, z0); + + switch (code) { + + case 'i': Inside++; break; + case 'o': Outside++; break; + default: Boundaries++; + } + + } + } + + if (hdr ->printf) + hdr ->printf("Gamut hull: %d inside, %d outside, %d on boundaries", Inside, Outside, Boundaries); + +} + +BOOL cmsxChoosePCS(LPPROFILERCOMMONDATA hdr) +{ + + double gamma_r, gamma_g, gamma_b; + cmsCIExyY SourceWhite; + + /* At first, compute aproximation on matrix-shaper */ + if (!cmsxComputeMatrixShaper(hdr ->ReferenceSheet, + hdr ->MeasurementSheet, + hdr -> Medium, + hdr ->Gamma, + &hdr ->WhitePoint, + &hdr ->BlackPoint, + &hdr ->Primaries)) return false; + + + + cmsXYZ2xyY(&SourceWhite, &hdr ->WhitePoint); + + gamma_r = cmsEstimateGamma(hdr ->Gamma[0]); + gamma_g = cmsEstimateGamma(hdr ->Gamma[1]); + gamma_b = cmsEstimateGamma(hdr ->Gamma[2]); + + + + if (gamma_r > 1.8 || gamma_g > 1.8 || gamma_b > 1.8 || + gamma_r == -1 || gamma_g == -1 || gamma_b == -1) { + + hdr ->PCSType = PT_Lab; + + if (hdr ->printf) + hdr ->printf("I have chosen Lab as PCS"); + + } + else { + + hdr ->PCSType = PT_XYZ; + + if (hdr ->printf) + hdr ->printf("I have chosen XYZ as PCS"); + } + + + + if (hdr ->printf) { + + char Buffer[256] = "Infered "; + + _cmsIdentifyWhitePoint(Buffer, &hdr ->WhitePoint); + hdr ->printf("%s", Buffer); + hdr ->printf("Primaries (x-y): [Red: %2.2f, %2.2f] [Green: %2.2f, %2.2f] [Blue: %2.2f, %2.2f]", + hdr ->Primaries.Red.x, hdr ->Primaries.Red.y, + hdr ->Primaries.Green.x, hdr ->Primaries.Green.y, + hdr ->Primaries.Blue.x, hdr ->Primaries.Blue.y); + + if ((gamma_r != -1) && (gamma_g != -1) && (gamma_b != -1)) { + + hdr ->printf("Estimated gamma: [Red: %2.2f] [Green: %2.2f] [Blue: %2.2f]", + gamma_r, gamma_g, gamma_b); + } + + + } + + + + return true; +} |