Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2454 | craig | 1 | // |
2 | // Little cms - profiler construction set |
||
3 | // Copyright (C) 1998-2001 Marti Maria |
||
4 | // |
||
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. |
||
8 | // |
||
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. |
||
15 | // |
||
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. |
||
20 | // |
||
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. |
||
25 | // |
||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||
29 | // |
||
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. |
||
34 | // |
||
35 | // Version 1.09a |
||
36 | |||
37 | |||
38 | #include "lcmsprf.h" |
||
39 | |||
40 | |||
41 | static |
||
42 | void ClampRGB(LPVEC3 RGB) |
||
43 | { |
||
44 | int i; |
||
45 | |||
46 | for (i=0; i < 3; i++) { |
||
47 | |||
48 | if (RGB->n[i] > 1.0) |
||
49 | RGB->n[i] = 1.0; |
||
50 | if (RGB->n[i] < 0) |
||
51 | RGB->n[i] = 0; |
||
52 | } |
||
53 | } |
||
54 | |||
55 | |||
56 | static |
||
57 | int RegressionSamplerA2B(register WORD In[], register WORD Out[], register LPVOID Cargo) |
||
58 | { |
||
59 | cmsCIEXYZ xyz; |
||
60 | cmsCIELab Lab; |
||
61 | VEC3 RGB, RGBlinear, vxyz; |
||
62 | LPMONITORPROFILERDATA sys = (LPMONITORPROFILERDATA) Cargo; |
||
63 | |||
64 | |||
65 | RGB.n[0] = _cmsxSaturate65535To255(In[0]); |
||
66 | RGB.n[1] = _cmsxSaturate65535To255(In[1]); |
||
67 | RGB.n[2] = _cmsxSaturate65535To255(In[2]); |
||
68 | |||
69 | cmsxApplyLinearizationTable(RGB.n, sys->PreLab, RGBlinear.n); |
||
70 | cmsxApplyLinearizationTable(RGBlinear.n, sys->Prelinearization, RGBlinear.n); |
||
71 | |||
72 | RGBlinear.n[0] /= 255.; |
||
73 | RGBlinear.n[1] /= 255.; |
||
74 | RGBlinear.n[2] /= 255.; |
||
75 | |||
76 | MAT3eval(&vxyz, &sys->PrimariesMatrix, &RGBlinear); |
||
77 | |||
78 | xyz.X = vxyz.n[0]; |
||
79 | xyz.Y = vxyz.n[1]; |
||
80 | xyz.Z = vxyz.n[2]; |
||
81 | |||
82 | cmsxChromaticAdaptationAndNormalization(&sys ->hdr, &xyz, FALSE); |
||
83 | |||
84 | |||
85 | // To PCS encoding |
||
86 | |||
87 | cmsXYZ2Lab(NULL, &Lab, &xyz); |
||
88 | cmsFloat2LabEncoded(Out, &Lab); |
||
89 | |||
90 | |||
91 | return TRUE; // And done witch success |
||
92 | } |
||
93 | |||
94 | |||
95 | |||
96 | |||
97 | static |
||
98 | int RegressionSamplerB2A(register WORD In[], register WORD Out[], register LPVOID Cargo) |
||
99 | { |
||
100 | cmsCIELab Lab; |
||
101 | cmsCIEXYZ xyz; |
||
102 | VEC3 vxyz, RGB; |
||
103 | // cmsJCh JCh; |
||
104 | WORD Lin[3], Llab[3]; |
||
105 | LPMONITORPROFILERDATA sys = (LPMONITORPROFILERDATA) Cargo; |
||
106 | double L; |
||
107 | |||
108 | |||
109 | // Pass L back to 0..0xff00 domain |
||
110 | |||
111 | L = (double) (In[0] * 65280.0) / 65535.0; |
||
112 | In[0] = (WORD) floor(L + .5); |
||
113 | |||
114 | |||
115 | // To float values |
||
116 | cmsLabEncoded2Float(&Lab, In); |
||
117 | cmsLab2XYZ(NULL, &xyz, &Lab); |
||
118 | |||
119 | |||
120 | cmsxChromaticAdaptationAndNormalization(&sys ->hdr, &xyz, TRUE); |
||
121 | vxyz.n[0] = xyz.X; |
||
122 | vxyz.n[1] = xyz.Y; |
||
123 | vxyz.n[2] = xyz.Z; |
||
124 | |||
125 | MAT3eval(&RGB, &sys-> PrimariesMatrixRev, &vxyz); |
||
126 | |||
127 | // Clamp RGB |
||
128 | ClampRGB(&RGB); |
||
129 | |||
130 | // Encode output |
||
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); |
||
134 | |||
135 | cmsxApplyLinearizationGamma(Lin, sys ->ReverseTables, Llab); |
||
136 | cmsxApplyLinearizationGamma(Llab, sys ->PreLabRev, Out); |
||
137 | |||
138 | |||
139 | return TRUE; // And done witch success |
||
140 | } |
||
141 | |||
142 | |||
143 | BOOL cmsxMonitorProfilerInit(LPMONITORPROFILERDATA sys) |
||
144 | { |
||
145 | |||
146 | |||
147 | if (sys == NULL) return FALSE; |
||
148 | ZeroMemory(sys, sizeof(MONITORPROFILERDATA)); |
||
149 | |||
150 | sys->hdr.DeviceClass = icSigDisplayClass; |
||
151 | sys->hdr.ColorSpace = icSigRgbData; |
||
152 | sys->hdr.PCSType = PT_Lab; |
||
153 | sys->hdr.Medium = MEDIUM_TRANSMISSIVE; |
||
154 | |||
155 | |||
156 | // Default values for generation |
||
157 | |||
158 | sys -> hdr.lUseCIECAM97s = FALSE; |
||
159 | sys -> hdr.CLUTPoints = 16; |
||
160 | |||
161 | // Default viewing conditions |
||
162 | |||
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 |
||
167 | |||
168 | |||
169 | // Viewing conditions of PCS |
||
170 | cmsxInitPCSViewingConditions(&sys ->hdr); |
||
171 | |||
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)"); |
||
176 | |||
177 | sys -> hdr.ProfileVerbosityLevel = 0; |
||
178 | |||
179 | return TRUE; |
||
180 | } |
||
181 | |||
182 | |||
183 | static |
||
184 | void CreatePrimaryMatrices(LPMONITORPROFILERDATA sys) |
||
185 | { |
||
186 | cmsCIExyY White; |
||
187 | MAT3 tmp; |
||
188 | |||
189 | |||
190 | cmsXYZ2xyY(&White, &sys->hdr.WhitePoint); |
||
191 | cmsBuildRGB2XYZtransferMatrix(&sys -> PrimariesMatrix, &White, &sys->hdr.Primaries); |
||
192 | |||
193 | CopyMemory(&tmp, &sys -> PrimariesMatrix, sizeof(MAT3)); |
||
194 | MAT3inverse(&tmp, &sys->PrimariesMatrixRev); |
||
195 | |||
196 | } |
||
197 | |||
198 | |||
199 | static |
||
200 | BOOL CreateLUTS(LPMONITORPROFILERDATA sys, LPLUT* A2B, LPLUT* B2A) |
||
201 | { |
||
202 | LPLUT AToB0 = cmsAllocLUT(); |
||
203 | LPLUT BToA0 = cmsAllocLUT(); |
||
204 | LPGAMMATABLE LabG; |
||
205 | cmsCIExyY xyY; |
||
206 | |||
207 | |||
208 | cmsAlloc3DGrid(AToB0, sys->hdr.CLUTPoints, 3, 3); |
||
209 | cmsAlloc3DGrid(BToA0, sys->hdr.CLUTPoints, 3, 3); |
||
210 | |||
211 | // cmsAllocLinearTable(AToB0, sys -> Prelinearization, 1); |
||
212 | |||
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]); |
||
216 | |||
217 | // Prelinearization |
||
218 | |||
219 | LabG = cmsBuildGamma(4096, 3.0); |
||
220 | |||
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); |
||
224 | |||
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); |
||
228 | |||
229 | |||
230 | cmsFreeGamma(LabG); |
||
231 | |||
232 | |||
233 | cmsAllocLinearTable(AToB0, sys->PreLabRev, 1); |
||
234 | cmsAllocLinearTable(BToA0, sys->PreLab, 2); |
||
235 | |||
236 | |||
237 | // Set CIECAM97s parameters |
||
238 | |||
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.; |
||
242 | |||
243 | |||
244 | // Normalize White point for CIECAM97s model |
||
245 | cmsXYZ2xyY(&xyY, &sys -> hdr.device.whitePoint); |
||
246 | xyY.Y = 100.; |
||
247 | cmsxyY2XYZ(&sys -> hdr.device.whitePoint, &xyY); |
||
248 | |||
249 | |||
250 | sys->hdr.hDevice = cmsCIECAM97sInit(&sys->hdr.device); |
||
251 | sys->hdr.hPCS = cmsCIECAM97sInit(&sys->hdr.PCS); |
||
252 | |||
253 | |||
254 | cmsSample3DGrid(AToB0, RegressionSamplerA2B, sys, 0); |
||
255 | cmsSample3DGrid(BToA0, RegressionSamplerB2A, sys, 0); |
||
256 | |||
257 | cmsCIECAM97sDone(sys->hdr.hDevice); |
||
258 | cmsCIECAM97sDone(sys->hdr.hPCS); |
||
259 | |||
260 | cmsAddTag(sys->hdr.hProfile, icSigAToB0Tag, AToB0); |
||
261 | cmsAddTag(sys->hdr.hProfile, icSigBToA0Tag, BToA0); |
||
262 | |||
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)); |
||
265 | |||
266 | *A2B = AToB0; |
||
267 | *B2A = BToA0; |
||
268 | |||
269 | cmsFreeGammaTriple(sys->ReverseTables); |
||
270 | cmsFreeGammaTriple(sys->PreLab); |
||
271 | cmsFreeGammaTriple(sys->PreLabRev); |
||
272 | return TRUE; |
||
273 | } |
||
274 | |||
275 | |||
276 | |||
277 | BOOL cmsxMonitorProfilerDo(LPMONITORPROFILERDATA sys) |
||
278 | { |
||
279 | |||
280 | cmsCIExyY White; |
||
281 | LPLUT AToB0, BToA0; |
||
282 | |||
283 | AToB0 = BToA0 = NULL; |
||
284 | |||
285 | if (!*sys -> hdr.OutputProfileFile) |
||
286 | return FALSE; |
||
287 | |||
288 | |||
289 | if (sys->hdr.ReferenceSheet[0] || sys->hdr.MeasurementSheet[0]) { |
||
290 | |||
291 | if (sys->hdr.printf) { |
||
292 | |||
293 | sys->hdr.printf("Loading sheets..."); |
||
294 | |||
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); |
||
299 | } |
||
300 | |||
301 | |||
302 | if (!cmsxComputeMatrixShaper(sys -> hdr.ReferenceSheet, |
||
303 | sys -> hdr.MeasurementSheet, |
||
304 | MEDIUM_TRANSMISSIVE, |
||
305 | sys -> Prelinearization, |
||
306 | &sys -> hdr.WhitePoint, |
||
307 | &sys -> hdr.BlackPoint, |
||
308 | &sys -> hdr.Primaries)) return FALSE; |
||
309 | |||
310 | if (sys->hdr.printf) { |
||
311 | |||
312 | char Buffer[1024]; |
||
313 | _cmsIdentifyWhitePoint(Buffer, &sys ->hdr.WhitePoint); |
||
314 | sys->hdr.printf("%s", Buffer); |
||
315 | |||
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); |
||
320 | } |
||
321 | |||
322 | } |
||
323 | |||
324 | |||
325 | CreatePrimaryMatrices(sys); |
||
326 | |||
327 | |||
328 | cmsXYZ2xyY(&White, &sys->hdr.WhitePoint); |
||
329 | |||
330 | sys->hdr.hProfile = cmsCreateRGBProfile(&White, |
||
331 | &sys-> hdr.Primaries, |
||
332 | sys -> Prelinearization); |
||
333 | |||
334 | cmsSetDeviceClass(sys->hdr.hProfile, sys->hdr.DeviceClass); |
||
335 | |||
336 | if (sys -> hdr.lUseCIECAM97s) |
||
337 | sys->hdr.PCSType = PT_Lab; |
||
338 | else |
||
339 | sys->hdr.PCSType = PT_XYZ; |
||
340 | |||
341 | cmsSetPCS(sys->hdr.hProfile, _cmsICCcolorSpace(sys->hdr.PCSType)); |
||
342 | |||
343 | if (sys -> hdr.lUseCIECAM97s) |
||
344 | CreateLUTS(sys, &AToB0, &BToA0); |
||
345 | |||
346 | |||
347 | cmsxEmbedTextualInfo(&sys ->hdr); |
||
348 | |||
349 | cmsAddTag(sys->hdr.hProfile, icSigMediaWhitePointTag, &sys->hdr.WhitePoint); |
||
350 | cmsAddTag(sys->hdr.hProfile, icSigMediaBlackPointTag, &sys->hdr.BlackPoint); |
||
351 | |||
352 | |||
353 | if (sys->hdr.ProfileVerbosityLevel >= 2) { |
||
354 | |||
355 | cmsxEmbedCharTarget(&sys ->hdr); |
||
356 | } |
||
357 | |||
358 | |||
359 | _cmsSaveProfile(sys->hdr.hProfile, sys->hdr.OutputProfileFile); |
||
360 | cmsCloseProfile(sys->hdr.hProfile); |
||
361 | sys->hdr.hProfile = NULL; |
||
362 | |||
363 | |||
364 | if (AToB0) cmsFreeLUT(AToB0); |
||
365 | if (BToA0) cmsFreeLUT(BToA0); |
||
366 | |||
367 | if (sys ->Prelinearization[0]) |
||
368 | cmsFreeGammaTriple(sys -> Prelinearization); |
||
369 | |||
370 | return TRUE; |
||
371 | } |