2
/* Little cms - profiler construction set */
3
/* Copyright (C) 1998-2001 Marti Maria <marti@littlecms.com> */
5
/* THIS SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, */
6
/* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY */
7
/* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. */
9
/* IN NO EVENT SHALL MARTI MARIA BE LIABLE FOR ANY SPECIAL, INCIDENTAL, */
10
/* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
11
/* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, */
12
/* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF */
13
/* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE */
14
/* OF THIS SOFTWARE. */
16
/* This file is free software; you can redistribute it and/or modify it */
17
/* under the terms of the GNU General Public License as published by */
18
/* the Free Software Foundation; either version 2 of the License, or */
19
/* (at your option) any later version. */
21
/* This program is distributed in the hope that it will be useful, but */
22
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
23
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
24
/* General Public License for more details. */
26
/* You should have received a copy of the GNU General Public License */
27
/* along with this program; if not, write to the Free Software */
28
/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
30
/* As a special exception to the GNU General Public License, if you */
31
/* distribute this file as part of a program that contains a */
32
/* configuration script generated by Autoconf, you may include it under */
33
/* the same distribution terms that you use for the rest of that program. */
42
void ClampRGB(LPVEC3 RGB)
46
for (i=0; i < 3; i++) {
57
int RegressionSamplerA2B(register WORD In[], register WORD Out[], register LPVOID Cargo)
61
VEC3 RGB, RGBlinear, vxyz;
62
LPMONITORPROFILERDATA sys = (LPMONITORPROFILERDATA) Cargo;
65
RGB.n[0] = _cmsxSaturate65535To255(In[0]);
66
RGB.n[1] = _cmsxSaturate65535To255(In[1]);
67
RGB.n[2] = _cmsxSaturate65535To255(In[2]);
69
cmsxApplyLinearizationTable(RGB.n, sys->PreLab, RGBlinear.n);
70
cmsxApplyLinearizationTable(RGBlinear.n, sys->Prelinearization, RGBlinear.n);
72
RGBlinear.n[0] /= 255.;
73
RGBlinear.n[1] /= 255.;
74
RGBlinear.n[2] /= 255.;
76
MAT3eval(&vxyz, &sys->PrimariesMatrix, &RGBlinear);
82
cmsxChromaticAdaptationAndNormalization(&sys ->hdr, &xyz, false);
87
cmsXYZ2Lab(NULL, &Lab, &xyz);
88
cmsFloat2LabEncoded(Out, &Lab);
91
return true; /* And done witch success */
98
int RegressionSamplerB2A(register WORD In[], register WORD Out[], register LPVOID Cargo)
104
WORD Lin[3], Llab[3];
105
LPMONITORPROFILERDATA sys = (LPMONITORPROFILERDATA) Cargo;
109
/* Pass L back to 0..0xff00 domain */
111
L = (double) (In[0] * 65280.0) / 65535.0;
112
In[0] = (WORD) floor(L + .5);
115
/* To float values */
116
cmsLabEncoded2Float(&Lab, In);
117
cmsLab2XYZ(NULL, &xyz, &Lab);
120
cmsxChromaticAdaptationAndNormalization(&sys ->hdr, &xyz, true);
125
MAT3eval(&RGB, &sys-> PrimariesMatrixRev, &vxyz);
131
Lin[0] = (WORD) ((double) RGB.n[0] * 65535. + .5);
132
Lin[1] = (WORD) ((double) RGB.n[1] * 65535. + .5);
133
Lin[2] = (WORD) ((double) RGB.n[2] * 65535. + .5);
135
cmsxApplyLinearizationGamma(Lin, sys ->ReverseTables, Llab);
136
cmsxApplyLinearizationGamma(Llab, sys ->PreLabRev, Out);
139
return true; /* And done witch success */
143
BOOL cmsxMonitorProfilerInit(LPMONITORPROFILERDATA sys)
147
if (sys == NULL) return false;
148
ZeroMemory(sys, sizeof(MONITORPROFILERDATA));
150
sys->hdr.DeviceClass = icSigDisplayClass;
151
sys->hdr.ColorSpace = icSigRgbData;
152
sys->hdr.PCSType = PT_Lab;
153
sys->hdr.Medium = MEDIUM_TRANSMISSIVE;
156
/* Default values for generation */
158
sys -> hdr.lUseCIECAM97s = false;
159
sys -> hdr.CLUTPoints = 16;
161
/* Default viewing conditions */
163
sys -> hdr.device.Yb = 20;
164
sys -> hdr.device.La = 20;
165
sys -> hdr.device.surround = AVG_SURROUND;
166
sys -> hdr.device.D_value = 1; /* Complete adaptation */
169
/* Viewing conditions of PCS */
170
cmsxInitPCSViewingConditions(&sys ->hdr);
172
strcpy(sys -> hdr.Description, "unknown monitor");
173
strcpy(sys -> hdr.Manufacturer, "little cms profiler construction set");
174
strcpy(sys -> hdr.Copyright, "No copyright, use freely");
175
strcpy(sys -> hdr.Model, "(unknown)");
177
sys -> hdr.ProfileVerbosityLevel = 0;
184
void CreatePrimaryMatrices(LPMONITORPROFILERDATA sys)
190
cmsXYZ2xyY(&White, &sys->hdr.WhitePoint);
191
cmsBuildRGB2XYZtransferMatrix(&sys -> PrimariesMatrix, &White, &sys->hdr.Primaries);
193
CopyMemory(&tmp, &sys -> PrimariesMatrix, sizeof(MAT3));
194
MAT3inverse(&tmp, &sys->PrimariesMatrixRev);
200
BOOL CreateLUTS(LPMONITORPROFILERDATA sys, LPLUT* A2B, LPLUT* B2A)
202
LPLUT AToB0 = cmsAllocLUT();
203
LPLUT BToA0 = cmsAllocLUT();
208
cmsAlloc3DGrid(AToB0, sys->hdr.CLUTPoints, 3, 3);
209
cmsAlloc3DGrid(BToA0, sys->hdr.CLUTPoints, 3, 3);
211
/* cmsAllocLinearTable(AToB0, sys -> Prelinearization, 1); */
213
sys->ReverseTables[0] = cmsReverseGamma(4096, sys ->Prelinearization[0]);
214
sys->ReverseTables[1] = cmsReverseGamma(4096, sys ->Prelinearization[1]);
215
sys->ReverseTables[2] = cmsReverseGamma(4096, sys ->Prelinearization[2]);
217
/* Prelinearization */
219
LabG = cmsBuildGamma(4096, 3.0);
221
sys -> PreLab[0] = cmsJoinGammaEx(LabG, sys ->Prelinearization[0], 4096);
222
sys -> PreLab[1] = cmsJoinGammaEx(LabG, sys ->Prelinearization[1], 4096);
223
sys -> PreLab[2] = cmsJoinGammaEx(LabG, sys ->Prelinearization[2], 4096);
225
sys -> PreLabRev[0] = cmsJoinGammaEx(sys ->Prelinearization[0], LabG, 4096);
226
sys -> PreLabRev[1] = cmsJoinGammaEx(sys ->Prelinearization[1], LabG, 4096);
227
sys -> PreLabRev[2] = cmsJoinGammaEx(sys ->Prelinearization[2], LabG, 4096);
233
cmsAllocLinearTable(AToB0, sys->PreLabRev, 1);
234
cmsAllocLinearTable(BToA0, sys->PreLab, 2);
237
/* Set CIECAM97s parameters */
239
sys -> hdr.device.whitePoint.X = sys -> hdr.WhitePoint.X * 100.;
240
sys -> hdr.device.whitePoint.Y = sys -> hdr.WhitePoint.Y * 100.;
241
sys -> hdr.device.whitePoint.Z = sys -> hdr.WhitePoint.Z * 100.;
244
/* Normalize White point for CIECAM97s model */
245
cmsXYZ2xyY(&xyY, &sys -> hdr.device.whitePoint);
247
cmsxyY2XYZ(&sys -> hdr.device.whitePoint, &xyY);
250
sys->hdr.hDevice = cmsCIECAM97sInit(&sys->hdr.device);
251
sys->hdr.hPCS = cmsCIECAM97sInit(&sys->hdr.PCS);
254
cmsSample3DGrid(AToB0, RegressionSamplerA2B, sys, 0);
255
cmsSample3DGrid(BToA0, RegressionSamplerB2A, sys, 0);
257
cmsCIECAM97sDone(sys->hdr.hDevice);
258
cmsCIECAM97sDone(sys->hdr.hPCS);
260
cmsAddTag(sys->hdr.hProfile, icSigAToB0Tag, AToB0);
261
cmsAddTag(sys->hdr.hProfile, icSigBToA0Tag, BToA0);
263
/* This is the 0xff00 trick to map white at lattice point */
264
BToA0 ->Matrix.v[0].n[0] = DOUBLE_TO_FIXED((65535.0 / 65280.0));
269
cmsFreeGammaTriple(sys->ReverseTables);
270
cmsFreeGammaTriple(sys->PreLab);
271
cmsFreeGammaTriple(sys->PreLabRev);
277
BOOL cmsxMonitorProfilerDo(LPMONITORPROFILERDATA sys)
283
AToB0 = BToA0 = NULL;
285
if (!*sys -> hdr.OutputProfileFile)
289
if (sys->hdr.ReferenceSheet[0] || sys->hdr.MeasurementSheet[0]) {
291
if (sys->hdr.printf) {
293
sys->hdr.printf("Loading sheets...");
295
if (sys->hdr.ReferenceSheet[0])
296
sys->hdr.printf("Reference sheet: %s", sys->hdr.ReferenceSheet);
297
if (sys->hdr.MeasurementSheet[0])
298
sys->hdr.printf("Measurement sheet: %s", sys->hdr.MeasurementSheet);
302
if (!cmsxComputeMatrixShaper(sys -> hdr.ReferenceSheet,
303
sys -> hdr.MeasurementSheet,
305
sys -> Prelinearization,
306
&sys -> hdr.WhitePoint,
307
&sys -> hdr.BlackPoint,
308
&sys -> hdr.Primaries)) return false;
310
if (sys->hdr.printf) {
313
_cmsIdentifyWhitePoint(Buffer, &sys ->hdr.WhitePoint);
314
sys->hdr.printf("%s", Buffer);
316
sys->hdr.printf("Primaries: R:%1.2g, %1.2g G:%1.2g, %1.2g B:%1.2g, %1.2g",
317
sys->hdr.Primaries.Red.x,sys->hdr.Primaries.Red.y,
318
sys->hdr.Primaries.Green.x, sys->hdr.Primaries.Green.y,
319
sys->hdr.Primaries.Blue.x, sys->hdr.Primaries.Blue.y);
325
CreatePrimaryMatrices(sys);
328
cmsXYZ2xyY(&White, &sys->hdr.WhitePoint);
330
sys->hdr.hProfile = cmsCreateRGBProfile(&White,
331
&sys-> hdr.Primaries,
332
sys -> Prelinearization);
334
cmsSetDeviceClass(sys->hdr.hProfile, sys->hdr.DeviceClass);
336
if (sys -> hdr.lUseCIECAM97s)
337
sys->hdr.PCSType = PT_Lab;
339
sys->hdr.PCSType = PT_XYZ;
341
cmsSetPCS(sys->hdr.hProfile, _cmsICCcolorSpace(sys->hdr.PCSType));
343
if (sys -> hdr.lUseCIECAM97s)
344
CreateLUTS(sys, &AToB0, &BToA0);
347
cmsxEmbedTextualInfo(&sys ->hdr);
349
cmsAddTag(sys->hdr.hProfile, icSigMediaWhitePointTag, &sys->hdr.WhitePoint);
350
cmsAddTag(sys->hdr.hProfile, icSigMediaBlackPointTag, &sys->hdr.BlackPoint);
353
if (sys->hdr.ProfileVerbosityLevel >= 2) {
355
cmsxEmbedCharTarget(&sys ->hdr);
359
_cmsSaveProfile(sys->hdr.hProfile, sys->hdr.OutputProfileFile);
360
cmsCloseProfile(sys->hdr.hProfile);
361
sys->hdr.hProfile = NULL;
364
if (AToB0) cmsFreeLUT(AToB0);
365
if (BToA0) cmsFreeLUT(BToA0);
367
if (sys ->Prelinearization[0])
368
cmsFreeGammaTriple(sys -> Prelinearization);