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

« back to all changes in this revision

Viewing changes to digikam/libs/lprof/cmsmkmsh.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
 
 
40
 
 
41
BOOL cdecl cmsxComputeMatrixShaper(const char* ReferenceSheet,                              
 
42
                             const char* MeasurementSheet,  
 
43
                             int Medium,
 
44
                             LPGAMMATABLE TransferCurves[3],
 
45
                             LPcmsCIEXYZ WhitePoint,
 
46
                             LPcmsCIEXYZ BlackPoint,
 
47
                             LPcmsCIExyYTRIPLE Primaries);
 
48
 
 
49
 
 
50
 
 
51
/* ------------------------------------------------------------- Implementation  */
 
52
 
 
53
 
 
54
static
 
55
void Div100(LPcmsCIEXYZ xyz)
 
56
{
 
57
    xyz -> X /= 100; xyz -> Y /= 100; xyz -> Z /= 100;
 
58
}
 
59
 
 
60
 
 
61
 
 
62
/* Compute endpoints */
 
63
 
 
64
static
 
65
BOOL ComputeWhiteAndBlackPoints(LPMEASUREMENT Linearized,
 
66
                                LPGAMMATABLE TransferCurves[3], 
 
67
                                LPcmsCIEXYZ Black, LPcmsCIEXYZ White)
 
68
{
 
69
 
 
70
    double Zeroes[3], Ones[3], lmin[3], lmax[3];    
 
71
 
 
72
    SETOFPATCHES Neutrals = cmsxPCollBuildSet(Linearized, false);
 
73
    
 
74
    cmsxPCollPatchesNearNeutral(Linearized, Linearized->Allowed,
 
75
                                                    15, Neutrals); 
 
76
 
 
77
    Zeroes[0] = Zeroes[1] = Zeroes[2] = 0.0;
 
78
    Ones[0]   = Ones[1]   = Ones[2]   = 255.0;
 
79
 
 
80
 
 
81
    cmsxApplyLinearizationTable(Zeroes,  TransferCurves, lmin);
 
82
    cmsxApplyLinearizationTable(Ones,    TransferCurves, lmax);
 
83
 
 
84
    
 
85
    /* Global regression to find White & Black points */
 
86
    if (!cmsxRegressionInterpolatorRGB(Linearized, PT_XYZ,                                       
 
87
                                       4,
 
88
                                       true,
 
89
                                       12,
 
90
                                       lmin[0], lmin[1], lmin[2],
 
91
                                       Black)) return false;
 
92
 
 
93
    if (!cmsxRegressionInterpolatorRGB(Linearized, PT_XYZ,                                       
 
94
                                       4,
 
95
                                       true,
 
96
                                       12,
 
97
                                       lmax[0], lmax[1], lmax[2],
 
98
                                       White)) return false;
 
99
 
 
100
    _cmsxClampXYZ100(White);
 
101
    _cmsxClampXYZ100(Black);
 
102
    
 
103
    return true;
 
104
    
 
105
}
 
106
 
 
107
 
 
108
/* Study convergence of primary axis */
 
109
 
 
110
static
 
111
BOOL ComputePrimary(LPMEASUREMENT Linearized,
 
112
                    LPGAMMATABLE TransferCurves[3], 
 
113
                    int n,
 
114
                    LPcmsCIExyY Primary)
 
115
{
 
116
 
 
117
    double Ones[3], lmax[3];    
 
118
    cmsCIEXYZ PrimXYZ;
 
119
    SETOFPATCHES SetPrimary;
 
120
    int nR;
 
121
           
 
122
 
 
123
    /* At first, try to see if primaries are already in measurement */
 
124
 
 
125
    SetPrimary = cmsxPCollBuildSet(Linearized, false);
 
126
    nR = cmsxPCollPatchesNearPrimary(Linearized, Linearized->Allowed,
 
127
                                           n, 32, SetPrimary);
 
128
 
 
129
    Ones[0]  = Ones[1] = Ones[2] = 0;
 
130
    Ones[n]  = 255.0;
 
131
 
 
132
    cmsxApplyLinearizationTable(Ones,  TransferCurves, lmax);
 
133
    
 
134
    /* Do incremental regression to find primaries */
 
135
    if (!cmsxRegressionInterpolatorRGB(Linearized, PT_XYZ,                                       
 
136
                                       4,
 
137
                                       false, 
 
138
                                       12,
 
139
                                       lmax[0], lmax[1], lmax[2],                                   
 
140
                                       &PrimXYZ)) return false;
 
141
 
 
142
    _cmsxClampXYZ100(&PrimXYZ);
 
143
    cmsXYZ2xyY(Primary, &PrimXYZ);
 
144
    return true;
 
145
    
 
146
 
 
147
}
 
148
 
 
149
 
 
150
 
 
151
/* Does compute a matrix-shaper based on patches.  */
 
152
 
 
153
static
 
154
double Clip(double d)
 
155
{
 
156
    return d > 0 ? d: 0;
 
157
}
 
158
 
 
159
 
 
160
BOOL cmsxComputeMatrixShaper(const char* ReferenceSheet,                                
 
161
                             const char* MeasurementSheet, 
 
162
                             int Medium,
 
163
                             LPGAMMATABLE TransferCurves[3],
 
164
                             LPcmsCIEXYZ WhitePoint,
 
165
                             LPcmsCIEXYZ BlackPoint,
 
166
                             LPcmsCIExyYTRIPLE Primaries)
 
167
{
 
168
 
 
169
    MEASUREMENT Linearized;     
 
170
    cmsCIEXYZ Black, White;
 
171
    cmsCIExyYTRIPLE  PrimarySet;
 
172
    LPPATCH PatchWhite, PatchBlack;
 
173
    LPPATCH PatchRed, PatchGreen, PatchBlue;
 
174
    double Distance;
 
175
 
 
176
    /* Load sheets */
 
177
 
 
178
    if (!cmsxPCollBuildMeasurement(&Linearized, 
 
179
                             ReferenceSheet,
 
180
                             MeasurementSheet,
 
181
                             PATCH_HAS_XYZ|PATCH_HAS_RGB)) return false;
 
182
 
 
183
 
 
184
 
 
185
    /* Any patch to deal of? */
 
186
    if (cmsxPCollCountSet(&Linearized, Linearized.Allowed) <= 0) return false;
 
187
 
 
188
 
 
189
    /* Try to see if proper primaries, white and black already present */
 
190
    PatchWhite = cmsxPCollFindWhite(&Linearized, Linearized.Allowed, &Distance);
 
191
    if (Distance != 0)
 
192
        PatchWhite = NULL;  
 
193
 
 
194
    PatchBlack = cmsxPCollFindBlack(&Linearized, Linearized.Allowed, &Distance);
 
195
    if (Distance != 0)
 
196
        PatchBlack = NULL;  
 
197
 
 
198
    PatchRed = cmsxPCollFindPrimary(&Linearized, Linearized.Allowed, 0, &Distance);
 
199
    if (Distance != 0)
 
200
        PatchRed = NULL;    
 
201
 
 
202
    PatchGreen = cmsxPCollFindPrimary(&Linearized, Linearized.Allowed, 1, &Distance);
 
203
    if (Distance != 0)
 
204
        PatchGreen = NULL;  
 
205
 
 
206
    PatchBlue = cmsxPCollFindPrimary(&Linearized, Linearized.Allowed, 2, &Distance);
 
207
    if (Distance != 0)
 
208
        PatchBlue= NULL;    
 
209
 
 
210
    /* If we got primaries, then we can also get prelinearization */
 
211
    /* by  Levenberg-Marquardt. This applies on monitor profiles */
 
212
 
 
213
    if (PatchWhite && PatchRed && PatchGreen && PatchBlue) {
 
214
 
 
215
        /* Build matrix with primaries */
 
216
 
 
217
        MAT3 Mat, MatInv;
 
218
        LPSAMPLEDCURVE Xr,Yr, Xg, Yg, Xb, Yb;
 
219
        int i, nRes, cnt;
 
220
        
 
221
        VEC3init(&Mat.v[0], PatchRed->XYZ.X, PatchGreen->XYZ.X, PatchBlue->XYZ.X);
 
222
        VEC3init(&Mat.v[1], PatchRed->XYZ.Y, PatchGreen->XYZ.Y, PatchBlue->XYZ.Y);
 
223
        VEC3init(&Mat.v[2], PatchRed->XYZ.Z, PatchGreen->XYZ.Z, PatchBlue->XYZ.Z);
 
224
 
 
225
        /* Invert matrix */
 
226
        MAT3inverse(&Mat, &MatInv);
 
227
 
 
228
        nRes = cmsxPCollCountSet(&Linearized, Linearized.Allowed);
 
229
 
 
230
        Xr = cmsAllocSampledCurve(nRes);
 
231
        Yr = cmsAllocSampledCurve(nRes);
 
232
        Xg = cmsAllocSampledCurve(nRes);
 
233
        Yg = cmsAllocSampledCurve(nRes);
 
234
        Xb = cmsAllocSampledCurve(nRes);
 
235
        Yb = cmsAllocSampledCurve(nRes);
 
236
                
 
237
        /* Convert XYZ of all patches to RGB */
 
238
        cnt = 0;
 
239
        for (i=0; i < Linearized.nPatches; i++) {
 
240
 
 
241
            if (Linearized.Allowed[i]) {
 
242
 
 
243
                VEC3 RGBprime, XYZ;
 
244
                LPPATCH p;
 
245
                
 
246
                p = Linearized.Patches + i;
 
247
                XYZ.n[0] = p -> XYZ.X;
 
248
                XYZ.n[1] = p -> XYZ.Y;
 
249
                XYZ.n[2] = p -> XYZ.Z;
 
250
 
 
251
                MAT3eval(&RGBprime, &MatInv, &XYZ);
 
252
 
 
253
                Xr ->Values[cnt] = p ->Colorant.RGB[0];
 
254
                Yr ->Values[cnt] = Clip(RGBprime.n[0]);
 
255
 
 
256
                Xg ->Values[cnt] = p ->Colorant.RGB[1];
 
257
                Yg ->Values[cnt] = Clip(RGBprime.n[1]);
 
258
 
 
259
                Xb ->Values[cnt] = p ->Colorant.RGB[2];
 
260
                Yb ->Values[cnt] = Clip(RGBprime.n[2]); 
 
261
 
 
262
                cnt++;
 
263
 
 
264
            }
 
265
        }
 
266
 
 
267
        TransferCurves[0] = cmsxEstimateGamma(Xr, Yr, 1024);
 
268
        TransferCurves[1] = cmsxEstimateGamma(Xg, Yg, 1024);
 
269
        TransferCurves[2] = cmsxEstimateGamma(Xb, Yb, 1024);
 
270
 
 
271
        if (WhitePoint) {
 
272
        
 
273
            WhitePoint->X = PatchWhite->XYZ.X;
 
274
            WhitePoint->Y= PatchWhite ->XYZ.Y;
 
275
            WhitePoint->Z= PatchWhite ->XYZ.Z;
 
276
        }
 
277
 
 
278
        if (BlackPoint && PatchBlack) {
 
279
 
 
280
            BlackPoint->X = PatchBlack ->XYZ.X;
 
281
            BlackPoint->Y = PatchBlack ->XYZ.Y;
 
282
            BlackPoint->Z = PatchBlack ->XYZ.Z;
 
283
        }
 
284
 
 
285
        if (Primaries) {
 
286
 
 
287
            cmsXYZ2xyY(&Primaries->Red,   &PatchRed ->XYZ);
 
288
            cmsXYZ2xyY(&Primaries->Green, &PatchGreen ->XYZ);
 
289
            cmsXYZ2xyY(&Primaries->Blue,  &PatchBlue ->XYZ);
 
290
 
 
291
        }
 
292
 
 
293
 
 
294
        cmsFreeSampledCurve(Xr);
 
295
        cmsFreeSampledCurve(Yr);
 
296
        cmsFreeSampledCurve(Xg);
 
297
        cmsFreeSampledCurve(Yg);
 
298
        cmsFreeSampledCurve(Xb);
 
299
        cmsFreeSampledCurve(Yb);
 
300
 
 
301
        cmsxPCollFreeMeasurements(&Linearized); 
 
302
 
 
303
        return true;
 
304
    }
 
305
 
 
306
 
 
307
 
 
308
 
 
309
    /* Compute prelinearization */
 
310
    cmsxComputeLinearizationTables(&Linearized, PT_XYZ, TransferCurves, 1024, Medium);   
 
311
      
 
312
    /* Linearize measurements */
 
313
    cmsxPCollLinearizePatches(&Linearized, Linearized.Allowed, TransferCurves);
 
314
       
 
315
 
 
316
    /* Endpoints */
 
317
    ComputeWhiteAndBlackPoints(&Linearized, TransferCurves, &Black, &White);
 
318
        
 
319
    /* Primaries */
 
320
    ComputePrimary(&Linearized, TransferCurves, 0, &PrimarySet.Red);
 
321
    ComputePrimary(&Linearized, TransferCurves, 1, &PrimarySet.Green);
 
322
    ComputePrimary(&Linearized, TransferCurves, 2, &PrimarySet.Blue);
 
323
 
 
324
    
 
325
    if (BlackPoint) {
 
326
        *BlackPoint = Black;            
 
327
        Div100(BlackPoint);
 
328
    }
 
329
 
 
330
    if (WhitePoint) {
 
331
        *WhitePoint = White;
 
332
        Div100(WhitePoint);     
 
333
    }
 
334
 
 
335
 
 
336
    if (Primaries) {
 
337
        *Primaries = PrimarySet;    
 
338
    }
 
339
    
 
340
    cmsxPCollFreeMeasurements(&Linearized); 
 
341
    
 
342
    return true;
 
343
}
 
344
 
 
345
 
 
346