--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c Mon Mar 23 10:40:54 2009 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c Tue Mar 24 09:14:02 2009 -0700
@@ -29,7 +29,7 @@
//
//
// Little cms
-// Copyright (C) 1998-2006 Marti Maria
+// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -144,6 +144,8 @@
/Table [ p p p [<...>]]
/RangeABC [ 0 1 0 1 0 1]
/DecodeABC[ <postlinearization> ]
+ /RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]
+ % -128/500 1+127/500 0 1 -127/200 1+128/200
/MatrixABC [ 1 1 1 1 0 0 0 0 -1]
/WhitePoint [D50]
/BlackPoint [BP]
@@ -347,7 +349,8 @@
static
LPMEMSTREAM CreateMemStream(LPBYTE Buffer, DWORD dwMax, int MaxCols)
{
- LPMEMSTREAM m = (LPMEMSTREAM) malloc(sizeof(MEMSTREAM));
+ LPMEMSTREAM m = (LPMEMSTREAM) _cmsMalloc(sizeof(MEMSTREAM));
+ if (m == NULL) return NULL;
ZeroMemory(m, sizeof(MEMSTREAM));
@@ -376,9 +379,9 @@
static
BYTE L2Byte(WORD w)
{
- int ww = w + 0x0080;
+ int ww = w + 0x0080;
- if (ww > 0xFFFF) return 0xFF;
+ if (ww > 0xFFFF) return 0xFF;
return (BYTE) ((WORD) (ww >> 8) & 0xFF);
}
@@ -387,7 +390,6 @@
static
void WriteRawByte(LPMEMSTREAM m, BYTE b)
{
-
if (m -> dwUsed + 1 > m -> dwMax) {
m -> HasError = 1;
}
@@ -422,7 +424,7 @@
}
-// Does write a formatted string
+// Does write a formatted string. Guaranteed to be 2048 bytes at most.
static
void Writef(LPMEMSTREAM m, const char *frm, ...)
{
@@ -432,7 +434,7 @@
va_start(args, frm);
- vsprintf((char*) Buffer, frm, args);
+ vsnprintf((char*) Buffer, 2048, frm, args);
for (pt = Buffer; *pt; pt++) {
@@ -562,7 +564,7 @@
Writef(m, "{255 mul 128 sub 200 div } bind\n");
Writef(m, "]\n");
Writef(m, "/MatrixABC [ 1 1 1 1 0 0 0 0 -1]\n");
- Writef(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n");
+ Writef(m, "/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]\n");
Writef(m, "/DecodeLMN [\n");
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");
Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind\n");
@@ -584,7 +586,11 @@
if (nEntries <= 0) return; // Empty table
// Suppress whole if identity
- if (cmsIsLinear(Table, nEntries)) return;
+ if (cmsIsLinear(Table, nEntries)) {
+ Writef(m, "{} ");
+ return;
+ }
+
// Check if is really an exponential. If so, emit "exp"
gamma = cmsEstimateGammaEx(Table, nEntries, 0.001);
@@ -646,7 +652,7 @@
// Compare gamma table
static
-BOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries)
+LCMSBOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries)
{
return memcmp(g1, g2, nEntries* sizeof(WORD)) == 0;
}
@@ -676,7 +682,7 @@
// Check whatever a profile has CLUT tables (only on input)
static
-BOOL IsLUTbased(cmsHPROFILE hProfile, int Intent)
+LCMSBOOL IsLUTbased(cmsHPROFILE hProfile, int Intent)
{
icTagSignature Tag;
@@ -718,10 +724,10 @@
if (sc -> FixWhite) {
- if (In[0] == 0xFFFF) { // Only in L* = 100
+ if (In[0] == 0xFFFF) { // Only in L* = 100, ab = [-8..8]
- if ((In[1] >= 0x8000 && In[1] <= 0x87FF) ||
- (In[2] >= 0x8000 && In[2] <= 0x87FF)) {
+ if ((In[1] >= 0x7800 && In[1] <= 0x8800) &&
+ (In[2] >= 0x7800 && In[2] <= 0x8800)) {
WORD* Black;
WORD* White;
@@ -829,8 +835,8 @@
sc.PreMaj = PreMaj;
sc.PostMaj= PostMaj;
- sc.PreMin = PreMin;
- sc.PostMin= PostMin;
+ sc.PreMin = PreMin;
+ sc.PostMin = PostMin;
sc.lIsInput = lIsInput;
sc.FixWhite = FixWhite;
sc.ColorSpace = ColorSpace;
@@ -1231,7 +1237,7 @@
if (!WriteNamedColorCSA(mem, hProfile, Intent)) {
- free((void*) mem);
+ _cmsFree((void*) mem);
return 0;
}
}
@@ -1246,7 +1252,7 @@
ColorSpace != icSigLabData) {
cmsSignalError(LCMS_ERRC_ABORTED, "Invalid output color space");
- free((void*) mem);
+ _cmsFree((void*) mem);
return 0;
}
@@ -1256,7 +1262,7 @@
// Yes, so handle as LUT-based
if (!WriteInputLUT(mem, hProfile, Intent)) {
- free((void*) mem);
+ _cmsFree((void*) mem);
return 0;
}
}
@@ -1266,7 +1272,7 @@
if (!WriteInputMatrixShaper(mem, hProfile)) {
- free((void*) mem); // Something went wrong
+ _cmsFree((void*) mem); // Something went wrong
return 0;
}
}
@@ -1277,7 +1283,7 @@
dwBytesUsed = mem ->dwUsed;
// Get rid of memory stream
- free((void*) mem);
+ _cmsFree((void*) mem);
// Finally, return used byte count
return dwBytesUsed;
@@ -1350,27 +1356,40 @@
static
-void EmitPQRStage(LPMEMSTREAM m, int DoBPC, int lIsAbsolute)
+void EmitPQRStage(LPMEMSTREAM m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute)
{
+ if (lIsAbsolute) {
+
+ // For absolute colorimetric intent, encode back to relative
+ // and generate a relative LUT
+
+ // Relative encoding is obtained across XYZpcs*(D50/WhitePoint)
+
+ cmsCIEXYZ White;
+
+ cmsTakeMediaWhitePoint(&White, hProfile);
+
+ Writef(m,"/MatrixPQR [1 0 0 0 1 0 0 0 1 ]\n");
+ Writef(m,"/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
+
+ Writef(m, "%% Absolute colorimetric -- encode to relative to maximize LUT usage\n"
+ "/TransformPQR [\n"
+ "{0.9642 mul %g div exch pop exch pop exch pop exch pop} bind\n"
+ "{1.0000 mul %g div exch pop exch pop exch pop exch pop} bind\n"
+ "{0.8249 mul %g div exch pop exch pop exch pop exch pop} bind\n]\n",
+ White.X, White.Y, White.Z);
+ return;
+ }
+
+
Writef(m,"%% Bradford Cone Space\n"
"/MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296 ] \n");
Writef(m, "/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
- if (lIsAbsolute) {
-
- // For absolute colorimetric intent, do nothing
-
- Writef(m, "%% Absolute colorimetric -- no transformation\n"
- "/TransformPQR [\n"
- "{exch pop exch pop exch pop exch pop} bind dup dup]\n");
- return;
- }
-
-
// No BPC
if (!DoBPC) {
@@ -1414,6 +1433,7 @@
static
void EmitXYZ2Lab(LPMEMSTREAM m)
{
+ Writef(m, "/RangeLMN [ -0.635 2.0 0 2 -0.635 2.0 ]\n");
Writef(m, "/EncodeLMN [\n");
Writef(m, "{ 0.964200 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
Writef(m, "{ 1.000000 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
@@ -1423,17 +1443,10 @@
Writef(m, "/EncodeABC [\n");
-
Writef(m, "{ 116 mul 16 sub 100 div } bind\n");
- Writef(m, "{ 500 mul 128 add 255 div } bind\n");
- Writef(m, "{ 200 mul 128 add 255 div } bind\n");
-
+ Writef(m, "{ 500 mul 128 add 256 div } bind\n");
+ Writef(m, "{ 200 mul 128 add 256 div } bind\n");
- /*
- Writef(m, "{ 116 mul 16 sub 256 mul 25700 div } bind\n");
- Writef(m, "{ 500 mul 128 add 256 mul 65535 div } bind\n");
- Writef(m, "{ 200 mul 128 add 256 mul 65535 div } bind\n");
- */
Writef(m, "]\n");
@@ -1458,20 +1471,27 @@
LPLUT DeviceLink;
cmsHPROFILE Profiles[3];
cmsCIEXYZ BlackPointAdaptedToD50;
- BOOL lFreeDeviceLink = FALSE;
- BOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
+ LCMSBOOL lFreeDeviceLink = FALSE;
+ LCMSBOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
+ LCMSBOOL lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP);
+ int RelativeEncodingIntent;
- // Trick our v4 profile as it were v2. This prevents the ajusting done
- // in perceptual & saturation. We only neew v4 encoding!
- hLab = cmsCreateLab4Profile(NULL);
- cmsSetProfileICCversion(hLab, 0);
+ hLab = cmsCreateLabProfile(NULL);
ColorSpace = cmsGetColorSpace(hProfile);
nChannels = _cmsChannelsOf(ColorSpace);
OutputFormat = CHANNELS_SH(nChannels) | BYTES_SH(2);
+ // For absolute colorimetric, the LUT is encoded as relative
+ // in order to preserve precission.
+
+ RelativeEncodingIntent = Intent;
+ if (RelativeEncodingIntent == INTENT_ABSOLUTE_COLORIMETRIC)
+ RelativeEncodingIntent = INTENT_RELATIVE_COLORIMETRIC;
+
+
// Is a devicelink profile?
if (cmsGetDeviceClass(hProfile) == icSigLinkClass) {
@@ -1479,13 +1499,14 @@
if (ColorSpace == icSigLabData) {
- // adjust input to Lab to out v4
+ // adjust input to Lab to our v4
Profiles[0] = hLab;
Profiles[1] = hProfile;
xform = cmsCreateMultiprofileTransform(Profiles, 2, TYPE_Lab_DBL,
- OutputFormat, Intent, cmsFLAGS_NOPRELINEARIZATION);
+ OutputFormat, RelativeEncodingIntent,
+ dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION);
}
else {
@@ -1499,7 +1520,7 @@
// This is a normal profile
xform = cmsCreateTransform(hLab, TYPE_Lab_DBL, hProfile,
- OutputFormat, Intent, cmsFLAGS_NOPRELINEARIZATION);
+ OutputFormat, RelativeEncodingIntent, dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION);
}
if (xform == NULL) {
@@ -1515,7 +1536,7 @@
if (!DeviceLink) {
- DeviceLink = _cmsPrecalculateDeviceLink(xform, 0);
+ DeviceLink = _cmsPrecalculateDeviceLink(xform, cmsFLAGS_NOPRELINEARIZATION);
lFreeDeviceLink = TRUE;
}
@@ -1527,7 +1548,7 @@
// Emit headers, etc.
EmitWhiteBlackD50(m, &BlackPointAdaptedToD50);
- EmitPQRStage(m, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC);
+ EmitPQRStage(m, hProfile, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC);
EmitXYZ2Lab(m);
if (DeviceLink ->wFlags & LUT_HASTL1) {
@@ -1544,10 +1565,13 @@
// zero. This would sacrifice a bit of highlights, but failure to do so would cause
// scum dot. Ouch.
+ if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
+ lFixWhite = FALSE;
+
Writef(m, "/RenderTable ");
WriteCLUT(m, DeviceLink, 8, "<", ">\n", "", "", FALSE,
- (Intent != INTENT_ABSOLUTE_COLORIMETRIC), ColorSpace);
+ lFixWhite, ColorSpace);
Writef(m, " %d {} bind ", nChannels);
@@ -1582,6 +1606,9 @@
int j;
Colorant[0] = 0;
+ if (nColorant > MAXCHANNELS)
+ nColorant = MAXCHANNELS;
+
for (j=0; j < nColorant; j++) {
sprintf(Buff, "%.3f", Out[j] / 65535.0);
@@ -1677,7 +1704,7 @@
if (!WriteNamedColorCRD(mem, hProfile, Intent, dwFlags)) {
- free((void*) mem);
+ _cmsFree((void*) mem);
return 0;
}
}
@@ -1687,7 +1714,7 @@
if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) {
- free((void*) mem);
+ _cmsFree((void*) mem);
return 0;
}
}
@@ -1702,7 +1729,7 @@
dwBytesUsed = mem ->dwUsed;
// Get rid of memory stream
- free((void*) mem);
+ _cmsFree((void*) mem);
// Finally, return used byte count
return dwBytesUsed;