Subversion Repositories Scribus

Rev

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
}