~ubuntu-branches/ubuntu/intrepid/digikam/intrepid

« back to all changes in this revision

Viewing changes to digikam/libs/lprof/cmsscn.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell
  • Date: 2008-07-17 20:25:39 UTC
  • mfrom: (1.3.2 upstream) (37 hardy)
  • mto: This revision was merged to the branch mainline in revision 39.
  • Revision ID: james.westby@ubuntu.com-20080717202539-1bw3w3nrsso7yj4z
* New upstream release
  - digiKam 0.9.4 Release Plan (KDE3) ~ 13 July 08 (Closes: #490144)
* DEB_CONFIGURE_EXTRA_FLAGS := --without-included-sqlite3
* Debhelper compatibility level V7
* Install pixmaps in debian/*.install
* Add debian/digikam.lintian-overrides

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* */
 
2
/*  Little cms - profiler construction set */
 
3
/*  Copyright (C) 1998-2001 Marti Maria <marti@littlecms.com> */
 
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., 51 Franklin Street, Fifth Floor, 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.08a */
 
36
 
 
37
 
 
38
#include "lcmsprf.h"
 
39
#include <stdio.h>
 
40
 
 
41
/* The scanner profiler */
 
42
 
 
43
 
 
44
BOOL   cdecl cmsxScannerProfilerInit(LPSCANNERPROFILERDATA sys);                                        
 
45
BOOL   cdecl cmsxScannerProfilerDo(LPSCANNERPROFILERDATA sys);
 
46
 
 
47
/* ------------------------------------------------------------ Implementation */
 
48
 
 
49
 
 
50
 
 
51
/* Does create regression matrix */
 
52
 
 
53
static
 
54
void ComputeGlobalRegression(LPSCANNERPROFILERDATA sys)
 
55
{
 
56
        BOOL lAllOk;
 
57
        int nTerms;
 
58
        MLRSTATISTICS Stat;
 
59
 
 
60
                nTerms = cmsxFindOptimumNumOfTerms(&sys ->hdr, 55, &lAllOk);
 
61
 
 
62
  
 
63
        if (!lAllOk) {
 
64
                        if (sys -> hdr.printf) 
 
65
                                        sys -> hdr.printf("*** WARNING: Inconsistence found, profile may be wrong. Check the target!");     
 
66
                        nTerms = 4;
 
67
                }
 
68
 
 
69
                /* Create high terms matrix used by interpolation */
 
70
        cmsxRegressionCreateMatrix(&sys -> hdr.m, 
 
71
                                       sys -> hdr.m.Allowed, 
 
72
                                       nTerms,
 
73
                                       sys -> hdr.PCSType,
 
74
                                       &sys -> HiTerms,
 
75
                                       &Stat);
 
76
        
 
77
        if (sys -> hdr.printf) 
 
78
            sys -> hdr.printf("Global regression: %d terms, R2Adj = %g", nTerms, Stat.R2adj);
 
79
 
 
80
                /* Create low terms matrix used by extrapolation */
 
81
                cmsxRegressionCreateMatrix(&sys -> hdr.m, 
 
82
                                       sys -> hdr.m.Allowed, 
 
83
                                       (nTerms > 10 ? 10 : nTerms),
 
84
                                       sys -> hdr.PCSType,
 
85
                                       &sys -> LoTerms,
 
86
                                       &Stat);          
 
87
                if (sys -> hdr.printf) 
 
88
            sys -> hdr.printf("Extrapolation: R2Adj = %g", Stat.R2adj);
 
89
 
 
90
}
 
91
 
 
92
 
 
93
/* Fill struct with default values */
 
94
        
 
95
BOOL cmsxScannerProfilerInit(LPSCANNERPROFILERDATA sys)
 
96
{                                
 
97
        
 
98
 
 
99
        if (sys == NULL) return false;
 
100
        ZeroMemory(sys, sizeof(SCANNERPROFILERDATA));
 
101
 
 
102
        sys->hdr.DeviceClass = icSigInputClass;
 
103
        sys->hdr.ColorSpace  = icSigRgbData;
 
104
        sys->hdr.PCSType     = PT_Lab;
 
105
                sys->hdr.Medium      = MEDIUM_REFLECTIVE_D50;
 
106
                
 
107
        /* Default values for generation */
 
108
 
 
109
        sys -> hdr.lUseCIECAM97s = false;
 
110
        sys -> hdr.CLUTPoints = 16;
 
111
       
 
112
           
 
113
        /* Default viewing conditions for scanner */
 
114
 
 
115
        sys -> hdr.device.Yb = 20;
 
116
        sys -> hdr.device.La = 20;
 
117
        sys -> hdr.device.surround = AVG_SURROUND;
 
118
        sys -> hdr.device.D_value  = 1.0;                       /* Complete adaptation */
 
119
 
 
120
 
 
121
        /* Viewing conditions of PCS */
 
122
                cmsxInitPCSViewingConditions(&sys -> hdr);
 
123
 
 
124
 
 
125
        sys -> HiTerms = NULL;
 
126
                sys -> LoTerms = NULL;
 
127
 
 
128
        strcpy(sys -> hdr.Description,  "no description");
 
129
        strcpy(sys -> hdr.Manufacturer, "little cms profiler construction set");
 
130
        strcpy(sys -> hdr.Copyright,   "No copyright, use freely");
 
131
        strcpy(sys -> hdr.Model,       "(unknown)");
 
132
 
 
133
                sys ->lLocalConvergenceExtrapolation = false;
 
134
                sys ->hdr.ProfileVerbosityLevel = 0;
 
135
        
 
136
 
 
137
    return true;
 
138
}
 
139
 
 
140
/* Auxiliar: take RGB and update gauge */
 
141
static
 
142
void GetRGB(LPPROFILERCOMMONDATA hdr, register WORD In[], double* r, double* g, double* b)
 
143
{   
 
144
    static int Count = 0, n_old = 0;
 
145
    double R, G, B;
 
146
    int n;
 
147
    
 
148
        
 
149
        R = _cmsxSaturate65535To255(In[0]);       /* Convert from the sheet notation */
 
150
        G = _cmsxSaturate65535To255(In[1]);       /* 0..255.0, to our notation */
 
151
        B = _cmsxSaturate65535To255(In[2]);       /* of 0..0xffff, 0xffff/255 = 257 */
 
152
 
 
153
        if (R == 0 && G == 0 && B == 0)  {
 
154
                Count = 0; n_old = -1;
 
155
        }
 
156
 
 
157
        n = (int) (double) (100. * Count)  / (hdr->CLUTPoints * hdr->CLUTPoints * hdr->CLUTPoints);
 
158
        Count++;
 
159
 
 
160
        if (n > n_old) {
 
161
            if (hdr->Gauger) hdr->Gauger("", 0, 100, (int) n);
 
162
        }
 
163
 
 
164
        n_old = n;
 
165
        *r = R; *g = G; *b = B;
 
166
 
 
167
}
 
168
 
 
169
 
 
170
 
 
171
 
 
172
 
 
173
/* The sampler for Lab */
 
174
static
 
175
int RegressionSamplerLab(register WORD In[], register WORD Out[], register LPVOID Cargo)
 
176
{
 
177
    cmsCIEXYZ xyz;  
 
178
    cmsCIELab Lab;
 
179
    double r, g, b;     
 
180
    LPSCANNERPROFILERDATA sys = (LPSCANNERPROFILERDATA) Cargo;
 
181
        char code;
 
182
 
 
183
        
 
184
        GetRGB(&sys->hdr, In, &r, &g, &b);
 
185
 
 
186
 
 
187
                code = cmsxHullCheckpoint(sys->hdr.hRGBHull, 
 
188
                                                              (int) floor(r + .5),
 
189
                                                                  (int) floor(g + .5),
 
190
                                                                  (int) floor(b + .5));
 
191
 
 
192
 
 
193
                if (code == 'i') { /* Inside gamut */
 
194
 
 
195
                        if (!cmsxRegressionRGB2Lab(r, g, b, sys -> HiTerms, &Lab)) return false;
 
196
                }
 
197
                else  
 
198
                if (!sys -> lLocalConvergenceExtrapolation && code == 'o') {  /* outside gamut */
 
199
 
 
200
                        if (!cmsxRegressionRGB2Lab(r, g, b, sys -> LoTerms, &Lab)) return false;
 
201
                }                               
 
202
                else {  /* At gamut hull boundaries */
 
203
 
 
204
                        if (!cmsxRegressionInterpolatorRGB(&sys -> hdr.m,
 
205
                                                                                                PT_Lab,                                        
 
206
                                                                                                10,
 
207
                                                                                                true,
 
208
                                                                                                30,
 
209
                                                                                                r, g, b,
 
210
                                                                                                &Lab)) return false;
 
211
                }
 
212
                
 
213
                       
 
214
        /* Regression CAN deliver wrong values. Clamp these. */
 
215
        cmsClampLab(&Lab, 127.9961, -128, 127.9961, -128);
 
216
 
 
217
        /* Normalize */
 
218
        cmsLab2XYZ(cmsD50_XYZ(), &xyz, &Lab);
 
219
        cmsxChromaticAdaptationAndNormalization(&sys->hdr, &xyz, false);       
 
220
        cmsXYZ2Lab(cmsD50_XYZ(), &Lab, &xyz);
 
221
 
 
222
        /* Clamping again, adaptation could move slightly values */
 
223
        cmsClampLab(&Lab, 127.9961, -128, 127.9961, -128);
 
224
 
 
225
        /* To PCS encoding */
 
226
        cmsFloat2LabEncoded(Out, &Lab);
 
227
 
 
228
                                
 
229
    return true; /* And done with success */
 
230
}
 
231
 
 
232
 
 
233
 
 
234
 
 
235
 
 
236
/* The sampler for XYZ */
 
237
static
 
238
int RegressionSamplerXYZ(register WORD In[], register WORD Out[], register LPVOID Cargo)
 
239
{
 
240
    cmsCIEXYZ xyz;
 
241
    double r, g, b;
 
242
    LPSCANNERPROFILERDATA sys = (LPSCANNERPROFILERDATA) Cargo;
 
243
        char code;
 
244
 
 
245
      GetRGB(&sys -> hdr, In, &r, &g, &b);
 
246
 
 
247
            code = cmsxHullCheckpoint(sys ->hdr.hRGBHull,
 
248
                                                                  (int) floor(r + .5),
 
249
                                                                  (int) floor(g + .5),
 
250
                                                                  (int) floor(b + .5));
 
251
 
 
252
                if (code == 'i') { /* Inside gamut */
 
253
 
 
254
                        if (!cmsxRegressionRGB2XYZ(r, g, b, sys -> HiTerms, &xyz)) return false;
 
255
                }
 
256
                else  
 
257
                if (!sys -> lLocalConvergenceExtrapolation && code == 'o') {  /* outside gamut */
 
258
 
 
259
                        if (!cmsxRegressionRGB2XYZ(r, g, b, sys -> LoTerms, &xyz)) return false;
 
260
                }
 
261
                                
 
262
                else {  /* At gamut hull boundaries */
 
263
 
 
264
                        if (!cmsxRegressionInterpolatorRGB(&sys -> hdr.m,
 
265
                                                                                                PT_XYZ,                                        
 
266
                                                                                                10,
 
267
                                                                                                true,
 
268
                                                                                                30,
 
269
                                                                                                r, g, b,
 
270
                                                                                                &xyz)) return false;
 
271
                }
 
272
                                                        
 
273
        
 
274
      xyz.X /= 100.;
 
275
      xyz.Y /= 100.;
 
276
      xyz.Z /= 100.;
 
277
 
 
278
      cmsxChromaticAdaptationAndNormalization(&sys->hdr, &xyz, false);       
 
279
     
 
280
      /* To PCS encoding. It also claps bad values */
 
281
      cmsFloat2XYZEncoded(Out, &xyz);
 
282
        
 
283
    return true; /* And done witch success */
 
284
}
 
285
 
 
286
 
 
287
 
 
288
/* The main scanner profiler */
 
289
BOOL cmsxScannerProfilerDo(LPSCANNERPROFILERDATA sys)
 
290
{
 
291
 
 
292
        LPLUT AToB0;
 
293
        DWORD dwNeedSamples;
 
294
 
 
295
                   
 
296
        if (!*sys -> hdr.OutputProfileFile)
 
297
                return false;
 
298
 
 
299
    
 
300
        if (!cmsxChoosePCS(&sys->hdr))
 
301
                return false;               
 
302
 
 
303
        dwNeedSamples = PATCH_HAS_RGB;
 
304
        if (sys ->hdr.PCSType == PT_Lab)
 
305
                dwNeedSamples |= PATCH_HAS_Lab;
 
306
        else
 
307
                dwNeedSamples |= PATCH_HAS_XYZ;
 
308
 
 
309
            
 
310
        if (sys->hdr.printf) {
 
311
            
 
312
            sys->hdr.printf("Loading sheets...");
 
313
 
 
314
            if (sys->hdr.ReferenceSheet[0])
 
315
                sys->hdr.printf("Reference sheet: %s", sys->hdr.ReferenceSheet);
 
316
            if (sys->hdr.MeasurementSheet[0])
 
317
                sys->hdr.printf("Measurement sheet: %s", sys->hdr.MeasurementSheet);
 
318
        }
 
319
 
 
320
 
 
321
        if (!cmsxPCollBuildMeasurement(&sys->hdr.m, 
 
322
                                    sys->hdr.ReferenceSheet, 
 
323
                                    sys->hdr.MeasurementSheet,
 
324
                                    dwNeedSamples)) return false;
 
325
 
 
326
                        
 
327
                
 
328
        sys->hdr.hProfile = cmsCreateRGBProfile(NULL, NULL, NULL);
 
329
     
 
330
 
 
331
        cmsSetDeviceClass(sys->hdr.hProfile, sys->hdr.DeviceClass);
 
332
        cmsSetColorSpace(sys->hdr.hProfile,  sys->hdr.ColorSpace);
 
333
        cmsSetPCS(sys->hdr. hProfile,  _cmsICCcolorSpace(sys->hdr.PCSType));
 
334
    
 
335
        /* Save char target tag */
 
336
                if (sys->hdr.ProfileVerbosityLevel >= 2) {
 
337
                        
 
338
                        cmsxEmbedCharTarget(&sys ->hdr);
 
339
                }
 
340
 
 
341
        AToB0 = cmsAllocLUT();
 
342
 
 
343
        cmsAlloc3DGrid(AToB0, sys->hdr.CLUTPoints, 3, 3);
 
344
 
 
345
        cmsxComputeLinearizationTables(&sys-> hdr.m, 
 
346
                                        sys -> hdr.PCSType, 
 
347
                                        sys -> Prelinearization, 
 
348
                                                                                1024,
 
349
                                                                                MEDIUM_REFLECTIVE_D50);
 
350
                                                
 
351
        /* Refresh RGB of all patches. This converts all regression into */
 
352
        /* near linear RGB->Lab or XYZ */
 
353
            
 
354
        cmsxPCollLinearizePatches(&sys->hdr.m, sys -> hdr.m.Allowed, sys -> Prelinearization);   
 
355
 
 
356
                cmsxComputeGamutHull(&sys->hdr);
 
357
        ComputeGlobalRegression(sys);
 
358
 
 
359
        cmsAllocLinearTable(AToB0, sys -> Prelinearization, 1);                              
 
360
 
 
361
        /* Set CIECAM97s parameters */
 
362
 
 
363
        sys -> hdr.device.whitePoint.X = sys -> hdr.WhitePoint.X * 100.;
 
364
        sys -> hdr.device.whitePoint.Y = sys -> hdr.WhitePoint.Y * 100.;
 
365
        sys -> hdr.device.whitePoint.Z = sys -> hdr.WhitePoint.Z * 100.;
 
366
           
 
367
                           
 
368
        sys->hdr.hDevice = cmsCIECAM97sInit(&sys->hdr.device);
 
369
        sys->hdr.hPCS    = cmsCIECAM97sInit(&sys->hdr.PCS);
 
370
 
 
371
        
 
372
        if (sys -> hdr.PCSType == PT_Lab)
 
373
                cmsSample3DGrid(AToB0, RegressionSamplerLab, sys, 0);
 
374
        else
 
375
                cmsSample3DGrid(AToB0, RegressionSamplerXYZ, sys, 0);
 
376
 
 
377
        cmsCIECAM97sDone(sys->hdr.hDevice);
 
378
        cmsCIECAM97sDone(sys->hdr.hPCS);
 
379
 
 
380
        cmsAddTag(sys->hdr.hProfile, icSigAToB0Tag, AToB0);
 
381
 
 
382
 
 
383
            cmsxEmbedTextualInfo(&sys -> hdr);
 
384
       
 
385
                cmsAddTag(sys->hdr.hProfile, icSigMediaWhitePointTag, &sys->hdr.WhitePoint);
 
386
        cmsAddTag(sys->hdr.hProfile, icSigMediaBlackPointTag, &sys->hdr.BlackPoint);
 
387
 
 
388
 
 
389
                /* Save primaries & gamma curves */
 
390
                if (sys->hdr.ProfileVerbosityLevel >= 1) {
 
391
 
 
392
                        cmsxEmbedMatrixShaper(&sys ->hdr);
 
393
                }
 
394
 
 
395
        _cmsSaveProfile(sys->hdr.hProfile, sys->hdr.OutputProfileFile);
 
396
 
 
397
        cmsCloseProfile(sys->hdr.hProfile);
 
398
        sys->hdr.hProfile = NULL;
 
399
 
 
400
        cmsxPCollFreeMeasurements(&sys->hdr.m);    
 
401
               
 
402
        cmsFreeLUT(AToB0);
 
403
       
 
404
        if (sys -> HiTerms)
 
405
                MATNfree(sys -> HiTerms);
 
406
        sys -> HiTerms = NULL;
 
407
 
 
408
 
 
409
                if (sys -> LoTerms)
 
410
                MATNfree(sys -> LoTerms);
 
411
        sys -> LoTerms = NULL;
 
412
 
 
413
                
 
414
 
 
415
        if (sys ->Prelinearization[0])
 
416
            cmsFreeGammaTriple(sys -> Prelinearization);   
 
417
                
 
418
                if (sys ->hdr.Gamma)
 
419
                        cmsFreeGammaTriple(sys->hdr.Gamma);
 
420
                
 
421
    return true;
 
422
}