~ubuntu-branches/ubuntu/karmic/lcms/karmic

« back to all changes in this revision

Viewing changes to src/cmsps2.c

  • Committer: Bazaar Package Importer
  • Author(s): Oleksandr Moskalenko
  • Date: 2008-07-24 14:29:36 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080724142936-9fgs00bge01jgdl5
Tags: 1.17.dfsg-1
Removed Adobe sRGB profiles from the testdbed and python/testbed
directories (Closes: #491995).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
//
2
2
//  Little cms
3
 
//  Copyright (C) 1998-2006 Marti Maria
 
3
//  Copyright (C) 1998-2007 Marti Maria
4
4
//
5
5
// Permission is hereby granted, free of charge, to any person obtaining 
6
6
// a copy of this software and associated documentation files (the "Software"), 
115
115
            /Table [ p p p [<...>]]
116
116
            /RangeABC [ 0 1 0 1 0 1]
117
117
            /DecodeABC[ <postlinearization> ]
 
118
            /RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ] 
 
119
               % -128/500 1+127/500 0 1  -127/200 1+128/200 
118
120
            /MatrixABC [ 1 1 1 1 0 0 0 0 -1]
119
121
            /WhitePoint [D50]
120
122
            /BlackPoint [BP]
318
320
static
319
321
LPMEMSTREAM CreateMemStream(LPBYTE Buffer, DWORD dwMax, int MaxCols)
320
322
{
321
 
    LPMEMSTREAM m = (LPMEMSTREAM) malloc(sizeof(MEMSTREAM));
 
323
    LPMEMSTREAM m = (LPMEMSTREAM) _cmsMalloc(sizeof(MEMSTREAM));
 
324
    if (m == NULL) return NULL;
322
325
 
323
326
    ZeroMemory(m, sizeof(MEMSTREAM));
324
327
 
357
360
// Write a raw, uncooked byte. Check for space
358
361
static
359
362
void WriteRawByte(LPMEMSTREAM m, BYTE b)
360
 
{
361
 
    
 
363
{    
362
364
    if (m -> dwUsed + 1 > m -> dwMax) {
363
365
        m -> HasError = 1;      
364
366
    }
393
395
 
394
396
}
395
397
 
396
 
// Does write a formatted string
 
398
// Does write a formatted string. Guaranteed to be 2048 bytes at most.
397
399
static
398
400
void Writef(LPMEMSTREAM m, const char *frm, ...)
399
401
{
403
405
 
404
406
        va_start(args, frm);
405
407
 
406
 
        vsprintf((char*) Buffer, frm, args);
 
408
        vsnprintf((char*) Buffer, 2048, frm, args);
407
409
 
408
410
        for (pt = Buffer; *pt; pt++)  {
409
411
 
533
535
    Writef(m, "{255 mul 128 sub 200 div } bind\n");
534
536
    Writef(m, "]\n");
535
537
    Writef(m, "/MatrixABC [ 1 1 1 1 0 0 0 0 -1]\n");
536
 
        Writef(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n");
 
538
        Writef(m, "/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]\n"); 
537
539
    Writef(m, "/DecodeLMN [\n");
538
540
    Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind\n");
539
541
    Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind\n");
617
619
// Compare gamma table
618
620
 
619
621
static
620
 
BOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries)
 
622
LCMSBOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries)
621
623
{    
622
624
    return memcmp(g1, g2, nEntries* sizeof(WORD)) == 0;
623
625
}
647
649
// Check whatever a profile has CLUT tables (only on input)
648
650
 
649
651
static
650
 
BOOL IsLUTbased(cmsHPROFILE hProfile, int Intent)
 
652
LCMSBOOL IsLUTbased(cmsHPROFILE hProfile, int Intent)
651
653
{
652
654
    icTagSignature Tag;
653
655
 
689
691
 
690
692
    if (sc -> FixWhite) {
691
693
 
692
 
        if (In[0] == 0xFFFF) {  // Only in L* = 100
 
694
        if (In[0] == 0xFFFF) {  // Only in L* = 100, ab = [-8..8]
693
695
 
694
 
            if ((In[1] >= 0x8000 && In[1] <= 0x87FF) ||
695
 
                (In[2] >= 0x8000 && In[2] <= 0x87FF)) {
 
696
            if ((In[1] >= 0x7800 && In[1] <= 0x8800) &&
 
697
                (In[2] >= 0x7800 && In[2] <= 0x8800)) {
696
698
 
697
699
                WORD* Black;
698
700
                WORD* White;
800
802
    sc.PreMaj = PreMaj;
801
803
    sc.PostMaj= PostMaj;
802
804
 
803
 
    sc.PreMin = PreMin;
804
 
    sc.PostMin= PostMin;
 
805
    sc.PreMin   = PreMin;
 
806
    sc.PostMin  = PostMin;
805
807
    sc.lIsInput = lIsInput;
806
808
    sc.FixWhite = FixWhite;
807
809
    sc.ColorSpace = ColorSpace;
1202
1204
 
1203
1205
        if (!WriteNamedColorCSA(mem, hProfile, Intent)) {
1204
1206
 
1205
 
                    free((void*) mem);
 
1207
                    _cmsFree((void*) mem);
1206
1208
                    return 0;
1207
1209
        }
1208
1210
    }
1217
1219
        ColorSpace != icSigLabData) {
1218
1220
 
1219
1221
            cmsSignalError(LCMS_ERRC_ABORTED, "Invalid output color space");
1220
 
            free((void*) mem);
 
1222
            _cmsFree((void*) mem);
1221
1223
            return 0;
1222
1224
    }
1223
1225
    
1227
1229
        // Yes, so handle as LUT-based
1228
1230
        if (!WriteInputLUT(mem, hProfile, Intent)) {
1229
1231
 
1230
 
                    free((void*) mem);
 
1232
                    _cmsFree((void*) mem);
1231
1233
                    return 0;
1232
1234
        }
1233
1235
    }
1237
1239
 
1238
1240
        if (!WriteInputMatrixShaper(mem, hProfile)) {
1239
1241
 
1240
 
                    free((void*) mem);  // Something went wrong
 
1242
                    _cmsFree((void*) mem);  // Something went wrong
1241
1243
                    return 0;
1242
1244
        }
1243
1245
    }
1248
1250
    dwBytesUsed = mem ->dwUsed;
1249
1251
 
1250
1252
    // Get rid of memory stream
1251
 
    free((void*) mem);
 
1253
    _cmsFree((void*) mem);
1252
1254
 
1253
1255
    // Finally, return used byte count
1254
1256
    return dwBytesUsed;
1321
1323
 
1322
1324
 
1323
1325
static
1324
 
void EmitPQRStage(LPMEMSTREAM m, int DoBPC, int lIsAbsolute)
 
1326
void EmitPQRStage(LPMEMSTREAM m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute)
1325
1327
{
1326
1328
 
1327
 
    
 
1329
   
 
1330
        if (lIsAbsolute) {
 
1331
 
 
1332
            // For absolute colorimetric intent, encode back to relative 
 
1333
                        // and generate a relative LUT
 
1334
 
 
1335
                        // Relative encoding is obtained across XYZpcs*(D50/WhitePoint)
 
1336
 
 
1337
                        cmsCIEXYZ White;
 
1338
 
 
1339
                        cmsTakeMediaWhitePoint(&White, hProfile);
 
1340
 
 
1341
                        Writef(m,"/MatrixPQR [1 0 0 0 1 0 0 0 1 ]\n");
 
1342
            Writef(m,"/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
 
1343
 
 
1344
            Writef(m, "%% Absolute colorimetric -- encode to relative to maximize LUT usage\n"
 
1345
                      "/TransformPQR [\n"
 
1346
                      "{0.9642 mul %g div exch pop exch pop exch pop exch pop} bind\n"
 
1347
                      "{1.0000 mul %g div exch pop exch pop exch pop exch pop} bind\n"
 
1348
                      "{0.8249 mul %g div exch pop exch pop exch pop exch pop} bind\n]\n", 
 
1349
                                          White.X, White.Y, White.Z);
 
1350
            return;
 
1351
        }
 
1352
 
 
1353
 
1328
1354
        Writef(m,"%% Bradford Cone Space\n"
1329
1355
                 "/MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296 ] \n");
1330
1356
 
1331
1357
        Writef(m, "/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
1332
1358
 
1333
 
        
1334
 
        if (lIsAbsolute) {
1335
 
 
1336
 
            // For absolute colorimetric intent, do nothing
1337
 
        
1338
 
            Writef(m, "%% Absolute colorimetric -- no transformation\n"
1339
 
                      "/TransformPQR [\n"
1340
 
                      "{exch pop exch pop exch pop exch pop} bind dup dup]\n"); 
1341
 
            return;
1342
 
        }
1343
 
        
1344
1359
 
1345
1360
        // No BPC
1346
1361
 
1385
1400
static
1386
1401
void EmitXYZ2Lab(LPMEMSTREAM m)
1387
1402
{
 
1403
    Writef(m, "/RangeLMN [ -0.635 2.0 0 2 -0.635 2.0 ]\n"); 
1388
1404
    Writef(m, "/EncodeLMN [\n");
1389
1405
    Writef(m, "{ 0.964200  div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
1390
1406
    Writef(m, "{ 1.000000  div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
1393
1409
    Writef(m, "/MatrixABC [ 0 1 0 1 -1 1 0 0 -1 ]\n");
1394
1410
    Writef(m, "/EncodeABC [\n");
1395
1411
    
1396
 
    
1397
 
    
 
1412
        
1398
1413
    Writef(m, "{ 116 mul  16 sub 100 div  } bind\n");
1399
 
    Writef(m, "{ 500 mul 128 add 255 div  } bind\n");
1400
 
    Writef(m, "{ 200 mul 128 add 255 div  } bind\n");
1401
 
    
1402
 
    
1403
 
    /*
1404
 
    Writef(m, "{ 116 mul  16 sub 256 mul 25700 div  } bind\n");
1405
 
    Writef(m, "{ 500 mul 128 add 256 mul 65535 div  } bind\n");
1406
 
    Writef(m, "{ 200 mul 128 add 256 mul 65535 div  } bind\n");
1407
 
    */
 
1414
    Writef(m, "{ 500 mul 128 add 256 div  } bind\n");
 
1415
    Writef(m, "{ 200 mul 128 add 256 div  } bind\n");
 
1416
    
1408
1417
    
1409
1418
    Writef(m, "]\n");
1410
1419
    
1429
1438
    LPLUT DeviceLink;
1430
1439
    cmsHPROFILE Profiles[3];
1431
1440
    cmsCIEXYZ BlackPointAdaptedToD50;
1432
 
    BOOL lFreeDeviceLink = FALSE;
1433
 
    BOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
1434
 
        
1435
 
    
1436
 
    // Trick our v4 profile as it were v2. This prevents the ajusting done
1437
 
    // in perceptual & saturation. We only neew v4 encoding!
 
1441
    LCMSBOOL lFreeDeviceLink = FALSE;
 
1442
    LCMSBOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
 
1443
    LCMSBOOL lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP);
 
1444
        int RelativeEncodingIntent;
 
1445
    
 
1446
    
1438
1447
 
1439
 
    hLab         = cmsCreateLab4Profile(NULL);
1440
 
    cmsSetProfileICCversion(hLab, 0);
 
1448
    hLab = cmsCreateLabProfile(NULL);
1441
1449
 
1442
1450
    ColorSpace  =  cmsGetColorSpace(hProfile);
1443
1451
    nChannels   = _cmsChannelsOf(ColorSpace);
1444
1452
    OutputFormat = CHANNELS_SH(nChannels) | BYTES_SH(2);
1445
1453
    
 
1454
        // For absolute colorimetric, the LUT is encoded as relative 
 
1455
        // in order to preserve precission.
 
1456
 
 
1457
    RelativeEncodingIntent = Intent;
 
1458
        if (RelativeEncodingIntent == INTENT_ABSOLUTE_COLORIMETRIC)
 
1459
                RelativeEncodingIntent = INTENT_RELATIVE_COLORIMETRIC;
 
1460
 
 
1461
 
1446
1462
    // Is a devicelink profile?
1447
1463
    if (cmsGetDeviceClass(hProfile) == icSigLinkClass) {
1448
1464
 
1450
1466
 
1451
1467
        if (ColorSpace == icSigLabData) {
1452
1468
 
1453
 
              // adjust input to Lab to out v4
 
1469
              // adjust input to Lab to our v4
1454
1470
 
1455
1471
            Profiles[0] = hLab;
1456
1472
            Profiles[1] = hProfile;
1457
1473
 
1458
1474
            xform = cmsCreateMultiprofileTransform(Profiles, 2, TYPE_Lab_DBL, 
1459
 
                                                        OutputFormat, Intent, cmsFLAGS_NOPRELINEARIZATION);
 
1475
                                                        OutputFormat, RelativeEncodingIntent, 
 
1476
                                                                                                                dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION);
1460
1477
            
1461
1478
        }
1462
1479
        else {
1467
1484
 
1468
1485
    }
1469
1486
    else {
1470
 
 
 
1487
                
1471
1488
        // This is a normal profile
1472
1489
        xform = cmsCreateTransform(hLab, TYPE_Lab_DBL, hProfile, 
1473
 
                            OutputFormat, Intent, cmsFLAGS_NOPRELINEARIZATION);
 
1490
                            OutputFormat, RelativeEncodingIntent, dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION);
1474
1491
    }
1475
1492
 
1476
1493
    if (xform == NULL) {
1486
1503
    
1487
1504
    if (!DeviceLink) {
1488
1505
 
1489
 
        DeviceLink = _cmsPrecalculateDeviceLink(xform, 0);
 
1506
        DeviceLink = _cmsPrecalculateDeviceLink(xform, cmsFLAGS_NOPRELINEARIZATION);
1490
1507
        lFreeDeviceLink = TRUE;
1491
1508
    }
1492
1509
 
1498
1515
 
1499
1516
    // Emit headers, etc.
1500
1517
    EmitWhiteBlackD50(m, &BlackPointAdaptedToD50);
1501
 
    EmitPQRStage(m, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC);
 
1518
    EmitPQRStage(m, hProfile, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC);
1502
1519
    EmitXYZ2Lab(m);
1503
1520
        
1504
1521
    if (DeviceLink ->wFlags & LUT_HASTL1) {
1515
1532
    // zero. This would sacrifice a bit of highlights, but failure to do so would cause
1516
1533
    // scum dot. Ouch.
1517
1534
    
 
1535
    if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
 
1536
            lFixWhite = FALSE;
 
1537
 
1518
1538
    Writef(m, "/RenderTable ");
1519
1539
    
1520
1540
    WriteCLUT(m, DeviceLink, 8, "<", ">\n", "", "", FALSE, 
1521
 
                (Intent != INTENT_ABSOLUTE_COLORIMETRIC), ColorSpace);
 
1541
                lFixWhite, ColorSpace);
1522
1542
    
1523
1543
    Writef(m, " %d {} bind ", nChannels);
1524
1544
 
1553
1573
    int j;
1554
1574
 
1555
1575
    Colorant[0] = 0;
 
1576
    if (nColorant > MAXCHANNELS)
 
1577
        nColorant = MAXCHANNELS;
 
1578
 
1556
1579
    for (j=0; j < nColorant; j++) {
1557
1580
 
1558
1581
                sprintf(Buff, "%.3f", Out[j] / 65535.0);
1648
1671
 
1649
1672
        if (!WriteNamedColorCRD(mem, hProfile, Intent, dwFlags)) {
1650
1673
 
1651
 
                    free((void*) mem);
 
1674
                    _cmsFree((void*) mem);
1652
1675
                    return 0;
1653
1676
        }
1654
1677
    }
1658
1681
 
1659
1682
 
1660
1683
    if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) {
1661
 
        free((void*) mem);
 
1684
        _cmsFree((void*) mem);
1662
1685
        return 0;
1663
1686
    }
1664
1687
    }
1673
1696
    dwBytesUsed = mem ->dwUsed;
1674
1697
 
1675
1698
    // Get rid of memory stream
1676
 
    free((void*) mem);
 
1699
    _cmsFree((void*) mem);
1677
1700
 
1678
1701
    // Finally, return used byte count
1679
1702
    return dwBytesUsed;