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
//
17
// This library is free software; you can redistribute it and/or
18
// modify it under the terms of the GNU Lesser General Public
19
// License as published by the Free Software Foundation; either
20
// version 2 of the License, or (at your option) any later version.
21
//
22
// This library is distributed in the hope that it will be useful,
23
// but WITHOUT ANY WARRANTY; without even the implied warranty of
24
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25
// Lesser General Public License for more details.
26
//
27
// You should have received a copy of the GNU Lesser General Public
28
// License along with this library; if not, write to the Free Software
29
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30
 
31
#include "lcmsprf.h"
32
 
33
 
34
double cdecl _cmsxSaturate65535To255(double d);
35
double cdecl _cmsxSaturate255To65535(double d);
36
 
37
 
38
void   cdecl _cmsxClampXYZ100(LPcmsCIEXYZ xyz);
39
 
40
 
41
BOOL cdecl cmsxEmbedCharTarget(LPPROFILERCOMMONDATA hdr);
42
BOOL cdecl cmsxEmbedMatrixShaper(LPPROFILERCOMMONDATA hdr);
43
BOOL cdecl cmsxEmbedTextualInfo(LPPROFILERCOMMONDATA hdr);
44
 
45
// ----------------------------------------------------------------- Implementation
46
 
47
 
48
// Convert from 0.0..65535.0 to 0.0..255.0
49
 
50
double _cmsxSaturate65535To255(double d)
51
{  
52
    double v;
53
 
54
    v = d / 257.0;
55
 
56
        if (v < 0)     return 0;
57
    if (v > 255.0) return 255.0;
58
 
59
    return v;
60
}
61
 
62
 
63
double _cmsxSaturate255To65535(double d)
64
{  
65
    double v;
66
 
67
    v = d * 257.0;
68
 
69
        if (v < 0)     return 0;
70
    if (v > 65535.0) return 65535.0;
71
 
72
    return v;
73
}
74
 
75
 
76
 
77
// Cut off absurd values
78
 
79
void _cmsxClampXYZ100(LPcmsCIEXYZ xyz)
80
{
81
 
82
        if (xyz->X > 199.996)          
83
                xyz->X = 199.996;
84
 
85
        if (xyz->Y > 199.996)          
86
                xyz->Y = 199.996;
87
 
88
        if (xyz->Z > 199.996)          
89
                xyz->Z = 199.996;
90
 
91
                 if (xyz->Y < 0)
92
                xyz->Y = 0;
93
 
94
        if (xyz->X < 0)
95
                xyz->X = 0;
96
 
97
        if (xyz->Z < 0)
98
                xyz->Z = 0;
99
 
100
}
101
 
102
static
103
int xfilelength(int fd)
104
{
105
#ifdef _MSC_VER
106
                return _filelength(fd);
107
#else
108
        struct stat sb;
109
        if (fstat(fd, &sb) < 0)
110
                return(-1);
111
        return(sb.st_size);
112
#endif
113
 
114
 
115
}
116
 
117
 
118
BOOL cmsxEmbedCharTarget(LPPROFILERCOMMONDATA hdr)
119
{
120
                LCMSHANDLE it8 = cmsxIT8Alloc();
121
                LPBYTE mem;
122
                size_t size, readed;
123
                FILE* f;
124
                BOOL lFreeOnExit = FALSE;
125
 
126
 
127
                if (!hdr->m.Patches) {
128
 
129
                        if (!hdr ->ReferenceSheet[0] && !hdr->MeasurementSheet[0]) return FALSE;
130
 
131
                        if (cmsxPCollBuildMeasurement(&hdr ->m,
132
                                    hdr->ReferenceSheet,
133
                                    hdr->MeasurementSheet,
134
                                    PATCH_HAS_RGB|PATCH_HAS_XYZ) == FALSE) return FALSE;
135
                        lFreeOnExit = TRUE;
136
 
137
                }
138
 
139
                cmsxIT8SetSheetType(it8,"LCMSEMBED");
140
                cmsxIT8SetProperty(it8, "ORIGINATOR",   (const char *) "Little cms");
141
                cmsxIT8SetProperty(it8, "DESCRIPTOR",   (const char *) hdr -> Description);
142
                cmsxIT8SetProperty(it8, "MANUFACTURER", (const char *) hdr ->Manufacturer);
143
 
144
                cmsxPCollSaveToSheet(&hdr->m, it8);
145
                cmsxIT8SaveToFile(it8, "TMP00.IT8");
146
                cmsxIT8Free(it8);
147
 
148
                f = fopen("TMP00.IT8", "rb");
149
                size = xfilelength(fileno(f));
150
                mem = (char*) malloc(size + 1);
151
                readed = fread(mem, 1, size, f);
152
                fclose(f);
153
 
154
                mem[readed] = 0;
155
                unlink("TMP00.IT8");
156
 
157
                cmsAddTag(hdr->hProfile, icSigCharTargetTag, mem);
158
                free(mem);
159
 
160
                if (lFreeOnExit) {
161
 
162
                        cmsxPCollFreeMeasurements(&hdr->m);
163
                }
164
 
165
                return TRUE;
166
}
167
 
168
 
169
static
170
BOOL ComputeColorantMatrix(LPcmsCIEXYZTRIPLE Colorants,
171
                                                   LPcmsCIExyY WhitePoint,
172
                                                   LPcmsCIExyYTRIPLE Primaries)
173
{
174
           MAT3 MColorants;
175
 
176
           if (!cmsBuildRGB2XYZtransferMatrix(&MColorants, WhitePoint, Primaries))
177
       {      
178
              return FALSE;
179
       }  
180
 
181
 
182
           cmsAdaptMatrixToD50(&MColorants, WhitePoint);
183
 
184
       Colorants->Red.X = MColorants.v[0].n[0];
185
       Colorants->Red.Y = MColorants.v[1].n[0];
186
       Colorants->Red.Z = MColorants.v[2].n[0];
187
 
188
       Colorants->Green.X = MColorants.v[0].n[1];
189
       Colorants->Green.Y = MColorants.v[1].n[1];
190
       Colorants->Green.Z = MColorants.v[2].n[1];
191
 
192
       Colorants->Blue.X = MColorants.v[0].n[2];
193
       Colorants->Blue.Y = MColorants.v[1].n[2];
194
       Colorants->Blue.Z = MColorants.v[2].n[2];
195
 
196
           return TRUE;
197
 
198
}
199
 
200
 
201
BOOL cmsxEmbedMatrixShaper(LPPROFILERCOMMONDATA hdr)
202
{
203
        cmsCIEXYZTRIPLE Colorant;
204
        cmsCIExyY MediaWhite;
205
 
206
                cmsXYZ2xyY(&MediaWhite, &hdr ->WhitePoint);
207
 
208
                if (ComputeColorantMatrix(&Colorant, &MediaWhite, &hdr ->Primaries)) {
209
 
210
                cmsAddTag(hdr ->hProfile, icSigRedColorantTag, &Colorant.Red);
211
                cmsAddTag(hdr ->hProfile, icSigGreenColorantTag, &Colorant.Green);
212
                cmsAddTag(hdr ->hProfile, icSigBlueColorantTag, &Colorant.Blue);
213
                }
214
 
215
                cmsAddTag(hdr ->hProfile, icSigRedTRCTag, hdr ->Gamma[0]);
216
                cmsAddTag(hdr ->hProfile, icSigGreenTRCTag, hdr ->Gamma[1]);
217
                cmsAddTag(hdr ->hProfile, icSigBlueTRCTag, hdr ->Gamma[2]);
218
 
219
                return TRUE;
220
}
221
 
222
 
223
BOOL cmsxEmbedTextualInfo(LPPROFILERCOMMONDATA hdr)
224
{
225
            if (*hdr ->Description)
226
           cmsAddTag(hdr ->hProfile, icSigProfileDescriptionTag, hdr ->Description);
227
 
228
        if (*hdr ->Copyright)
229
           cmsAddTag(hdr ->hProfile, icSigCopyrightTag,          hdr ->Copyright);
230
 
231
        if (*hdr ->Manufacturer)
232
           cmsAddTag(hdr ->hProfile, icSigDeviceMfgDescTag,      hdr ->Manufacturer);
233
 
234
        if (*hdr ->Model)
235
           cmsAddTag(hdr ->hProfile, icSigDeviceModelDescTag,    hdr ->Model);
236
 
237
                return TRUE;
238
}
239
 
240
 
241
 
242
void cmsxChromaticAdaptationAndNormalization(LPPROFILERCOMMONDATA hdr, LPcmsCIEXYZ xyz, BOOL lReverse)
243
{
244
 
245
        if (hdr->lUseCIECAM97s) {
246
 
247
                cmsJCh JCh;
248
 
249
                // Let's CIECAM97s to do the adaptation to D50
250
 
251
               xyz->X *= 100.;
252
               xyz->Y *= 100.;
253
               xyz->Z *= 100.;
254
 
255
               _cmsxClampXYZ100(xyz);
256
 
257
                           if (lReverse) {
258
                                        cmsCIECAM97sForward(hdr->hPCS, xyz, &JCh);
259
                                        cmsCIECAM97sReverse(hdr->hDevice, &JCh, xyz);
260
                           }
261
                           else {
262
 
263
                                        cmsCIECAM97sForward(hdr->hDevice, xyz, &JCh);
264
                                        cmsCIECAM97sReverse(hdr->hPCS, &JCh, xyz);
265
                           }
266
 
267
               _cmsxClampXYZ100(xyz);
268
 
269
               xyz -> X /= 100.;
270
               xyz -> Y /= 100.;
271
               xyz -> Z /= 100.;
272
 
273
        }
274
        else {
275
 
276
              // Else, use Bradford
277
 
278
                        if (lReverse) {
279
                                 cmsAdaptToIlluminant(xyz, cmsD50_XYZ(), &hdr->WhitePoint,  xyz);            
280
                        }
281
                        else {
282
                          cmsAdaptToIlluminant(xyz, &hdr->WhitePoint, cmsD50_XYZ(), xyz);            
283
                        }
284
 
285
       }
286
 
287
}
288
 
289
 
290
void cmsxInitPCSViewingConditions(LPPROFILERCOMMONDATA hdr)
291
{
292
 
293
            hdr->PCS.whitePoint.X = cmsD50_XYZ()->X * 100.;
294
                hdr->PCS.whitePoint.Y = cmsD50_XYZ()->Y * 100.;
295
                hdr->PCS.whitePoint.Z = cmsD50_XYZ()->Z * 100.;
296
 
297
 
298
        hdr->PCS.Yb = 20;                     // 20% of surround
299
        hdr->PCS.La = 20;                     // Adapting field luminance
300
        hdr->PCS.surround = AVG_SURROUND;
301
        hdr->PCS.D_value  = 1.0;                         // Complete adaptation
302
 
303
}
304
 
305
 
306
// Build gamut hull by geometric means
307
void cmsxComputeGamutHull(LPPROFILERCOMMONDATA hdr)
308
{      
309
        int i;
310
        int x0, y0, z0;
311
        int Inside, Outside, Boundaries;
312
        char code;
313
 
314
 
315
        hdr -> hRGBHull = cmsxHullInit();
316
 
317
        // For all valid patches, mark RGB knots as 0
318
        for (i=0; i < hdr ->m.nPatches; i++) {
319
 
320
        if (hdr ->m.Allowed[i]) {
321
 
322
            LPPATCH p = hdr ->m.Patches + i;
323
 
324
 
325
                        x0 = (int) floor(p->Colorant.RGB[0]  + .5);
326
                        y0 = (int) floor(p->Colorant.RGB[1]  + .5);
327
                        z0 = (int) floor(p->Colorant.RGB[2]  + .5);
328
 
329
                        cmsxHullAddPoint(hdr->hRGBHull, x0, y0, z0);                   
330
                }
331
        }
332
 
333
        cmsxHullComputeHull(hdr ->hRGBHull);
334
 
335
// #ifdef DEBUG
336
        cmsxHullDumpVRML(hdr -> hRGBHull, "rgbhull.wrl");
337
// #endif
338
 
339
 
340
 
341
        // A check
342
 
343
        Inside = Outside = Boundaries = 0;
344
        // For all valid patches, mark RGB knots as 0
345
        for (i=0; i < hdr ->m.nPatches; i++) {
346
 
347
        if (hdr ->m.Allowed[i]) {
348
 
349
            LPPATCH p = hdr ->m.Patches + i;
350
 
351
                        x0 = (int) floor(p->Colorant.RGB[0]  + .5);
352
                        y0 = (int) floor(p->Colorant.RGB[1]  + .5);
353
                        z0 = (int) floor(p->Colorant.RGB[2]  + .5);
354
 
355
                        code = cmsxHullCheckpoint(hdr -> hRGBHull, x0, y0, z0);
356
 
357
                        switch (code) {
358
 
359
                        case 'i': Inside++; break;
360
                        case 'o': Outside++; break;
361
                        default:  Boundaries++;                                
362
                        }
363
 
364
                }
365
        }
366
 
367
        if (hdr ->printf)
368
                hdr ->printf("Gamut hull: %d inside, %d outside, %d on boundaries", Inside, Outside, Boundaries);
369
 
370
}
371
 
372
BOOL cmsxChoosePCS(LPPROFILERCOMMONDATA hdr)
373
{
374
 
375
        double gamma_r, gamma_g, gamma_b;        
376
        cmsCIExyY SourceWhite;
377
 
378
        // At first, compute aproximation on matrix-shaper
379
        if (!cmsxComputeMatrixShaper(hdr ->ReferenceSheet,                                
380
                                     hdr ->MeasurementSheet,
381
                                                                         hdr -> Medium,
382
                                     hdr ->Gamma,
383
                                     &hdr ->WhitePoint,
384
                                     &hdr ->BlackPoint,
385
                                     &hdr ->Primaries)) return FALSE;
386
 
387
 
388
 
389
                cmsXYZ2xyY(&SourceWhite,   &hdr ->WhitePoint); 
390
 
391
        gamma_r = cmsEstimateGamma(hdr ->Gamma[0]);
392
        gamma_g = cmsEstimateGamma(hdr ->Gamma[1]);
393
        gamma_b = cmsEstimateGamma(hdr ->Gamma[2]);
394
 
395
 
396
 
397
        if (gamma_r > 1.8 || gamma_g > 1.8 || gamma_b > 1.8 ||
398
             gamma_r == -1 || gamma_g == -1 || gamma_b == -1) {
399
 
400
                hdr ->PCSType = PT_Lab;
401
 
402
                if (hdr ->printf)
403
                       hdr ->printf("I have choosen Lab as PCS");                        
404
 
405
        }
406
        else {
407
 
408
                hdr ->PCSType = PT_XYZ;
409
 
410
                if (hdr ->printf)
411
                       hdr ->printf("I have choosen XYZ as PCS");                        
412
     }
413
 
414
 
415
 
416
     if (hdr ->printf) {
417
 
418
                   char Buffer[256] = "Infered ";
419
 
420
                   _cmsIdentifyWhitePoint(Buffer, &hdr ->WhitePoint);
421
                   hdr ->printf("%s", Buffer);                        
422
                   hdr ->printf("Primaries (x-y): [Red: %2.2f, %2.2f] [Green: %2.2f, %2.2f] [Blue: %2.2f, %2.2f]",
423
                                      hdr ->Primaries.Red.x, hdr ->Primaries.Red.y,
424
                                      hdr ->Primaries.Green.x, hdr ->Primaries.Green.y,
425
                                      hdr ->Primaries.Blue.x, hdr ->Primaries.Blue.y);
426
 
427
                   if ((gamma_r != -1) && (gamma_g != -1) && (gamma_b != -1)) {
428
 
429
                   hdr ->printf("Estimated gamma: [Red: %2.2f] [Green: %2.2f] [Blue: %2.2f]",
430
                                                            gamma_r, gamma_g, gamma_b);
431
                   }
432
 
433
 
434
         }
435
 
436
 
437
 
438
        return TRUE;
439
}