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
// Incremental Interpolator
38
 
39
#include "lcmsprf.h"
40
 
41
 
42
// Res points to a result in XYZ or Lab
43
 
44
BOOL cdecl cmsxRegressionInterpolatorRGB(LPMEASUREMENT m,
45
                                       int ColorSpace,
46
                                       int    RegressionTerms,
47
                                       BOOL   lUseLocalPatches,
48
                                       int    MinPatchesToCollect,
49
                                       double r, double g, double b,
50
                                       void* Res);
51
 
52
 
53
// -------------------------------------------------------------- Implementation
54
 
55
// #define DEBUG 1
56
 
57
// Estimate regression matrix
58
static
59
void EstimateRegression(LPMEASUREMENT m, double r, double g, double b,
60
                                        int ColorSpace,
61
                                        LPMATN* ptfm,                                        
62
                                        int nterms,
63
                                        BOOL lIncludeAllPatches,
64
                                        int MinPatchesToCollect)
65
{
66
    int nCollected;
67
    MLRSTATISTICS maxAns;
68
    int ToCollect;
69
    SETOFPATCHES collected = cmsxPCollBuildSet(m, FALSE);
70
    SETOFPATCHES allowed   = cmsxPCollBuildSet(m, TRUE);
71
    BOOL rc;
72
    BOOL lPatchesExhausted = FALSE;
73
 
74
 
75
    CopyMemory(allowed, m -> Allowed, m->nPatches*sizeof(BOOL));
76
 
77
    *ptfm = NULL;
78
 
79
    ToCollect = max(MinPatchesToCollect, (nterms + 1));
80
 
81
    do {
82
 
83
                if (lIncludeAllPatches) {
84
 
85
                        CopyMemory(collected, allowed, m->nPatches*sizeof(BOOL));
86
                        lPatchesExhausted = TRUE;
87
                        ToCollect = nCollected = m->nPatches;
88
                }
89
                else
90
                {
91
 
92
                nCollected =  cmsxPCollPatchesNearRGB(m, m -> Allowed,
93
                                                            r, g, b,
94
                                                            ToCollect, collected);
95
 
96
                if (nCollected < ToCollect) {           // No more patches available
97
                        lPatchesExhausted = TRUE;
98
                }
99
                else    {
100
                        ToCollect = nCollected + 1;     // Start from here in next iteration
101
                }
102
        }
103
 
104
        // We are going always 3 -> 3 for now....
105
        rc = cmsxRegressionCreateMatrix(m, collected, nterms, ColorSpace, ptfm, &maxAns);
106
 
107
 
108
        // Does fit?
109
        if ((rc == FALSE) || maxAns.R2adj < 0.95 ||  maxAns.R2adj > 1.0) {
110
 
111
                maxAns.R2adj = -100;  // No, repeat              
112
        }
113
 
114
 
115
    } while (!lPatchesExhausted && maxAns.R2adj < 0.95);
116
 
117
#ifdef DEBUG
118
        printf("R2adj: %g, F: %g\n", maxAns.R2adj, maxAns.F);
119
#endif
120
 
121
    free(collected);
122
    free(allowed);
123
}
124
 
125
 
126
 
127
BOOL cmsxRegressionInterpolatorRGB(LPMEASUREMENT m,
128
                                       int ColorSpace,                                      
129
                                       int    RegressionTerms,
130
                                       BOOL   lUseLocalPatches,
131
                                       int    MinPatchesToCollect,
132
                                       double r, double g, double b,
133
                                       void* Res)
134
{
135
    LPMATN   tfm = NULL;
136
 
137
 
138
        EstimateRegression(m, r, g, b, ColorSpace, &tfm, RegressionTerms,
139
                                                                        !lUseLocalPatches, MinPatchesToCollect);
140
 
141
        if (tfm == NULL) return FALSE;
142
 
143
    switch (ColorSpace) {
144
 
145
        case PT_Lab:
146
 
147
                if (!cmsxRegressionRGB2Lab(r, g, b, tfm, (LPcmsCIELab) Res)) return FALSE;
148
                break;
149
 
150
        case PT_XYZ:
151
                if (!cmsxRegressionRGB2XYZ(r, g, b, tfm, (LPcmsCIEXYZ) Res)) return FALSE;
152
                break;
153
 
154
        default:
155
                return FALSE;
156
        }
157
 
158
        MATNfree(tfm);
159
 
160
 
161
#ifdef DEBUG
162
    printf("INTERPOLATED RGB %g,%g,%g Lab %g, %g, %g \n", r , g,  b,
163
            Lab->L, Lab->a, Lab->b);
164
 
165
#endif
166
    return TRUE;
167
}
168
 
169
 
170
// Check the results of a given regression matrix
171
 
172
static
173
void CheckOneRegressionMatrix(LPPROFILERCOMMONDATA hdr, LPMATN Matrix,
174
                                                                                double* Mean, double* Std, double* Max)
175
{
176
 
177
    cmsCIELab Lab;
178
    cmsCIEXYZ XYZ;
179
    double Hit, sum, sum2, n, dE;
180
    int i;
181
        cmsCIEXYZ D50;
182
 
183
 
184
        D50.X = cmsD50_XYZ() -> X* 100.;
185
        D50.Y = cmsD50_XYZ() -> Y* 100.;
186
        D50.Z = cmsD50_XYZ() -> Z* 100.;
187
 
188
    Hit = sum = sum2 = n = 0;
189
    for (i=0; i < hdr -> m.nPatches; i++) {
190
 
191
        if (hdr -> m.Allowed[i]) {
192
 
193
            LPPATCH p = hdr -> m.Patches + i;
194
 
195
            if (hdr -> PCSType == PT_Lab) {
196
 
197
                    WORD ProfileLabEncoded[3];
198
 
199
                    cmsxRegressionRGB2Lab(p -> Colorant.RGB[0],
200
                                        p -> Colorant.RGB[1],
201
                                        p -> Colorant.RGB[2],
202
                                        Matrix, &Lab);
203
 
204
                    cmsFloat2LabEncoded(ProfileLabEncoded, &Lab);
205
                    cmsLabEncoded2Float(&Lab, ProfileLabEncoded);
206
 
207
                    dE = cmsDeltaE(&Lab, &p ->Lab);
208
            }
209
            else {
210
                    cmsCIELab Lab2;
211
 
212
                    cmsxRegressionRGB2XYZ(p -> Colorant.RGB[0],
213
                                        p -> Colorant.RGB[1],
214
                                        p -> Colorant.RGB[2],
215
                                        Matrix, &XYZ);
216
                                        _cmsxClampXYZ100(&XYZ);
217
 
218
                    cmsXYZ2Lab(&D50, &Lab, &XYZ);
219
                    cmsXYZ2Lab(&D50, &Lab2, &p ->XYZ);
220
 
221
                    dE = cmsDeltaE(&Lab, &Lab2);
222
            }
223
 
224
 
225
            if (dE > Hit)
226
                Hit = dE;
227
 
228
            sum  += dE;
229
            sum2 += dE * dE;
230
            n = n + 1;
231
 
232
        }
233
    }
234
 
235
    *Mean = sum / n;
236
    *Std  = sqrt((n * sum2 - sum * sum) / (n*(n-1)));
237
    *Max  = Hit;
238
 
239
}
240
 
241
 
242
// Trial-and-error in order to get best number of terms.
243
 
244
int cmsxFindOptimumNumOfTerms(LPPROFILERCOMMONDATA hdr, int nMaxTerms, BOOL* lAllOk)
245
{
246
    int i, BestTerms;
247
    BOOL rc;
248
    LPMATN Matrix = NULL;
249
    MLRSTATISTICS Stat;
250
    double dEmean, dEStd, dEHit, Best;
251
    BOOL lOneFound;
252
 
253
 
254
    BestTerms = 4;
255
    Best = 1000.;
256
    lOneFound = FALSE;
257
 
258
    for (i=4; i <= nMaxTerms; i++) {            // 55
259
 
260
            rc = cmsxRegressionCreateMatrix(&hdr -> m, hdr -> m.Allowed,
261
                                       i, hdr -> PCSType, &Matrix, &Stat);
262
 
263
            if (rc && Stat.R2adj < 1 && Stat.R2adj > 0.6) {
264
 
265
                CheckOneRegressionMatrix(hdr, Matrix, &dEmean, &dEStd, &dEHit);
266
 
267
                if (dEStd < Best && dEHit < 50.) {
268
 
269
                        Best = dEStd;
270
                        BestTerms = i;
271
                        lOneFound = TRUE;
272
                }
273
 
274
            }
275
        MATNfree(Matrix);
276
        Matrix = NULL;
277
    }
278
 
279
    *lAllOk = lOneFound;
280
 
281
    return BestTerms;
282
}
283
 
284