diff -r 78d56f33c3a7 -r 0f6a4442b29e jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c Tue Sep 07 16:54:39 2010 +0400 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c Thu Sep 09 16:20:55 2010 +0400 @@ -27,9 +27,10 @@ // However, the following notice accompanied the original version of this // file: // +//--------------------------------------------------------------------------------- // -// Little cms -// Copyright (C) 1998-2007 Marti Maria +// Little Color Management System +// Copyright (c) 1998-2008 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -48,22 +49,14 @@ // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -// Postscript level 2 operators - +// +//--------------------------------------------------------------------------------- +// - -#include "lcms.h" -#include -#include +#include "lcms2_internal.h" // PostScript ColorRenderingDictionary and ColorSpaceArray -LCMSAPI DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile, int Intent, LPVOID Buffer, DWORD dwBufferLen); -LCMSAPI DWORD LCMSEXPORT cmsGetPostScriptCRD(cmsHPROFILE hProfile, int Intent, LPVOID Buffer, DWORD dwBufferLen); -LCMSAPI DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile, int Intent, DWORD dwFlags, LPVOID Buffer, DWORD dwBufferLen); -// -------------------------------------------------------------------- Implementation #define MAXPSCOLS 60 // Columns on tables @@ -83,9 +76,9 @@ Color Space Arrays (CSA) ================================================================================== - In order to obtain precission, code chooses between three ways to implement + In order to obtain precision, code chooses between three ways to implement the device -> XYZ transform. These cases identifies monochrome profiles (often - implemented as a set of curves), matrix-shaper and LUT-based. + implemented as a set of curves), matrix-shaper and Pipeline-based. Monochrome ----------- @@ -101,7 +94,7 @@ << /DecodeA { transfer function } bind /MatrixA [D50] - /RangeLMN [ 0.0 D50X 0.0 D50Y 0.0 D50Z ] + /RangeLMN [ 0.0 cmsD50X 0.0 cmsD50Y 0.0 cmsD50Z ] /WhitePoint [D50] /BlackPoint [BP] /RenderingIntent (intent) @@ -115,7 +108,7 @@ ------------------- This is implemented both with /CIEBasedABC or /CIEBasedDEF on dependig - of profile implementation. Since here is no interpolation tables, I do + of profile implementation. Since here there are no interpolation tables, I do the conversion directly to XYZ @@ -124,7 +117,7 @@ << /DecodeABC [ {transfer1} {transfer2} {transfer3} ] /MatrixABC [Matrix] - /RangeLMN [ 0.0 D50X 0.0 D50Y 0.0 D50Z ] + /RangeLMN [ 0.0 cmsD50X 0.0 cmsD50Y 0.0 cmsD50Z ] /DecodeLMN [ { / 2} dup dup ] /WhitePoint [D50] /BlackPoint [BP] @@ -299,153 +292,66 @@ */ -static icTagSignature Device2PCSTab[] = {icSigAToB0Tag, // Perceptual - icSigAToB1Tag, // Relative colorimetric - icSigAToB2Tag, // Saturation - icSigAToB1Tag }; // Absolute colorimetric - // (Relative/WhitePoint) - -// --------------------------------------------------------------- Memory Stream -// // This struct holds the memory block currently being write -// +typedef struct { + _cmsStageCLutData* Pipeline; + cmsIOHANDLER* m; + + int FirstComponent; + int SecondComponent; -typedef struct { - LPBYTE Block; - LPBYTE Ptr; - DWORD dwMax; - DWORD dwUsed; - int MaxCols; - int Col; - int HasError; + const char* PreMaj; + const char* PostMaj; + const char* PreMin; + const char* PostMin; - } MEMSTREAM, FAR* LPMEMSTREAM; + int FixWhite; // Force mapping of pure white + + cmsColorSpaceSignature ColorSpace; // ColorSpace of profile -typedef struct { - LPLUT Lut; - LPMEMSTREAM m; - - int FirstComponent; - int SecondComponent; - - int bps; - const char* PreMaj; - const char* PostMaj; - const char* PreMin; - const char* PostMin; - - int lIsInput; // Handle L* encoding - int FixWhite; // Force mapping of pure white - - icColorSpaceSignature ColorSpace; // ColorSpace of profile - - - } SAMPLERCARGO, FAR* LPSAMPLERCARGO; +} cmsPsSamplerCargo; - -// Creates a ready to use memory stream -static -LPMEMSTREAM CreateMemStream(LPBYTE Buffer, DWORD dwMax, int MaxCols) -{ - LPMEMSTREAM m = (LPMEMSTREAM) _cmsMalloc(sizeof(MEMSTREAM)); - if (m == NULL) return NULL; - - ZeroMemory(m, sizeof(MEMSTREAM)); - - m -> Block = m -> Ptr = Buffer; - m -> dwMax = dwMax; - m -> dwUsed = 0; - m -> MaxCols = MaxCols; - m -> Col = 0; - m -> HasError = 0; - - return m; -} - +static int _cmsPSActualColumn = 0; // Convert to byte static -BYTE Word2Byte(WORD w) +cmsUInt8Number Word2Byte(cmsUInt16Number w) { - return (BYTE) floor((double) w / 257.0 + 0.5); + return (cmsUInt8Number) floor((cmsFloat64Number) w / 257.0 + 0.5); } // Convert to byte (using ICC2 notation) - -static -BYTE L2Byte(WORD w) -{ - int ww = w + 0x0080; - - if (ww > 0xFFFF) return 0xFF; - - return (BYTE) ((WORD) (ww >> 8) & 0xFF); -} - -// Write a raw, uncooked byte. Check for space +/* static -void WriteRawByte(LPMEMSTREAM m, BYTE b) +cmsUInt8Number L2Byte(cmsUInt16Number w) { - if (m -> dwUsed + 1 > m -> dwMax) { - m -> HasError = 1; - } + int ww = w + 0x0080; - if (!m ->HasError && m ->Block) { - *m ->Ptr++ = b; - } + if (ww > 0xFFFF) return 0xFF; - m -> dwUsed++; + return (cmsUInt8Number) ((cmsUInt16Number) (ww >> 8) & 0xFF); } +*/ // Write a cooked byte + static -void WriteByte(LPMEMSTREAM m, BYTE b) +void WriteByte(cmsIOHANDLER* m, cmsUInt8Number b) { - static const BYTE Hex[] = "0123456789ABCDEF"; - BYTE c; - - c = Hex[(b >> 4) & 0x0f]; - WriteRawByte(m, c); - - c = Hex[b & 0x0f]; - WriteRawByte(m, c); - - m -> Col += 2; - - if (m -> Col > m -> MaxCols) { - - WriteRawByte(m, '\n'); - m -> Col = 0; - } - -} + _cmsIOPrintf(m, "%02x", b); + _cmsPSActualColumn += 2; -// Does write a formatted string. Guaranteed to be 2048 bytes at most. -static -void Writef(LPMEMSTREAM m, const char *frm, ...) -{ - va_list args; - LPBYTE pt; - BYTE Buffer[2048]; - - va_start(args, frm); + if (_cmsPSActualColumn > MAXPSCOLS) { - vsnprintf((char*) Buffer, 2048, frm, args); - - for (pt = Buffer; *pt; pt++) { - - WriteRawByte(m, *pt); - } - - va_end(args); + _cmsIOPrintf(m, "\n"); + _cmsPSActualColumn = 0; + } } - - // ----------------------------------------------------------------- PostScript generation @@ -466,21 +372,31 @@ } static -void EmitHeader(LPMEMSTREAM m, const char* Title, cmsHPROFILE hProfile) +void EmitHeader(cmsIOHANDLER* m, const char* Title, cmsHPROFILE hProfile) { - time_t timer; + cmsMLU *Description, *Copyright; + char DescASCII[256], CopyrightASCII[256]; time(&timer); - Writef(m, "%%!PS-Adobe-3.0\n"); - Writef(m, "%%\n"); - Writef(m, "%% %s\n", Title); - Writef(m, "%% Source: %s\n", RemoveCR(cmsTakeProductName(hProfile))); - Writef(m, "%% Description: %s\n", RemoveCR(cmsTakeProductDesc(hProfile))); - Writef(m, "%% Created: %s", ctime(&timer)); // ctime appends a \n!!! - Writef(m, "%%\n"); - Writef(m, "%%%%BeginResource\n"); + Description = (cmsMLU*) cmsReadTag(hProfile, cmsSigProfileDescriptionTag); + Copyright = (cmsMLU*) cmsReadTag(hProfile, cmsSigCopyrightTag); + + DescASCII[0] = DescASCII[255] = 0; + CopyrightASCII[0] = CopyrightASCII[255] = 0; + + if (Description != NULL) cmsMLUgetASCII(Description, cmsNoLanguage, cmsNoCountry, DescASCII, 255); + if (Copyright != NULL) cmsMLUgetASCII(Copyright, cmsNoLanguage, cmsNoCountry, CopyrightASCII, 255); + + _cmsIOPrintf(m, "%%!PS-Adobe-3.0\n"); + _cmsIOPrintf(m, "%%\n"); + _cmsIOPrintf(m, "%% %s\n", Title); + _cmsIOPrintf(m, "%% Source: %s\n", RemoveCR(DescASCII)); + _cmsIOPrintf(m, "%% %s\n", RemoveCR(CopyrightASCII)); + _cmsIOPrintf(m, "%% Created: %s", ctime(&timer)); // ctime appends a \n!!! + _cmsIOPrintf(m, "%%\n"); + _cmsIOPrintf(m, "%%%%BeginResource\n"); } @@ -489,31 +405,31 @@ // Black point adapted to D50. static -void EmitWhiteBlackD50(LPMEMSTREAM m, LPcmsCIEXYZ BlackPoint) +void EmitWhiteBlackD50(cmsIOHANDLER* m, cmsCIEXYZ* BlackPoint) { - Writef(m, "/BlackPoint [%f %f %f]\n", BlackPoint -> X, + _cmsIOPrintf(m, "/BlackPoint [%f %f %f]\n", BlackPoint -> X, BlackPoint -> Y, BlackPoint -> Z); - Writef(m, "/WhitePoint [%f %f %f]\n", cmsD50_XYZ()->X, + _cmsIOPrintf(m, "/WhitePoint [%f %f %f]\n", cmsD50_XYZ()->X, cmsD50_XYZ()->Y, cmsD50_XYZ()->Z); } static -void EmitRangeCheck(LPMEMSTREAM m) +void EmitRangeCheck(cmsIOHANDLER* m) { - Writef(m, "dup 0.0 lt { pop 0.0 } if " - "dup 1.0 gt { pop 1.0 } if "); + _cmsIOPrintf(m, "dup 0.0 lt { pop 0.0 } if " + "dup 1.0 gt { pop 1.0 } if "); } // Does write the intent static -void EmitIntent(LPMEMSTREAM m, int RenderingIntent) +void EmitIntent(cmsIOHANDLER* m, int RenderingIntent) { const char *intent; @@ -527,7 +443,7 @@ default: intent = "Undefined"; break; } - Writef(m, "/RenderingIntent (%s)\n", intent ); + _cmsIOPrintf(m, "/RenderingIntent (%s)\n", intent ); } // @@ -539,9 +455,9 @@ /* static -void EmitL2Y(LPMEMSTREAM m) +void EmitL2Y(cmsIOHANDLER* m) { - Writef(m, + _cmsIOPrintf(m, "{ " "100 mul 16 add 116 div " // (L * 100 + 16) / 116 "dup 6 29 div ge " // >= 6 / 29 ? @@ -555,21 +471,21 @@ // Lab -> XYZ, see the discussion above static -void EmitLab2XYZ(LPMEMSTREAM m) +void EmitLab2XYZ(cmsIOHANDLER* m) { - Writef(m, "/RangeABC [ 0 1 0 1 0 1]\n"); - Writef(m, "/DecodeABC [\n"); - Writef(m, "{100 mul 16 add 116 div } bind\n"); - Writef(m, "{255 mul 128 sub 500 div } bind\n"); - 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.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"); - Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.824900 mul} bind\n"); - Writef(m, "]\n"); + _cmsIOPrintf(m, "/RangeABC [ 0 1 0 1 0 1]\n"); + _cmsIOPrintf(m, "/DecodeABC [\n"); + _cmsIOPrintf(m, "{100 mul 16 add 116 div } bind\n"); + _cmsIOPrintf(m, "{255 mul 128 sub 500 div } bind\n"); + _cmsIOPrintf(m, "{255 mul 128 sub 200 div } bind\n"); + _cmsIOPrintf(m, "]\n"); + _cmsIOPrintf(m, "/MatrixABC [ 1 1 1 1 0 0 0 0 -1]\n"); + _cmsIOPrintf(m, "/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]\n"); + _cmsIOPrintf(m, "/DecodeLMN [\n"); + _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind\n"); + _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind\n"); + _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.824900 mul} bind\n"); + _cmsIOPrintf(m, "]\n"); } @@ -577,29 +493,25 @@ // Outputs a table of words. It does use 16 bits static -void Emit1Gamma(LPMEMSTREAM m, LPWORD Table, int nEntries) +void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table) { - int i; - double gamma; + cmsUInt32Number i; + cmsFloat64Number gamma; - if (nEntries <= 0) return; // Empty table + if (Table ->nEntries <= 0) return; // Empty table // Suppress whole if identity - if (cmsIsLinear(Table, nEntries)) { - Writef(m, "{} "); - return; - } - + if (cmsIsToneCurveLinear(Table)) return; // Check if is really an exponential. If so, emit "exp" - gamma = cmsEstimateGammaEx(Table, nEntries, 0.001); + gamma = cmsEstimateGamma(Table, 0.001); if (gamma > 0) { - Writef(m, "{ %g exp } bind ", gamma); + _cmsIOPrintf(m, "{ %g exp } bind ", gamma); return; } - Writef(m, "{ "); + _cmsIOPrintf(m, "{ "); // Bounds check EmitRangeCheck(m); @@ -609,94 +521,74 @@ // PostScript code Stack // =============== ======================== // v - Writef(m, " ["); + _cmsIOPrintf(m, " ["); - // TODO: Check for endianess!!! - - for (i=0; i < nEntries; i++) { - Writef(m, "%d ", Table[i]); + for (i=0; i < Table->nEntries; i++) { + _cmsIOPrintf(m, "%d ", Table->Table16[i]); } - Writef(m, "] "); // v tab + _cmsIOPrintf(m, "] "); // v tab - Writef(m, "dup "); // v tab tab - Writef(m, "length 1 sub "); // v tab dom - Writef(m, "3 -1 roll "); // tab dom v - Writef(m, "mul "); // tab val2 - Writef(m, "dup "); // tab val2 val2 - Writef(m, "dup "); // tab val2 val2 val2 - Writef(m, "floor cvi "); // tab val2 val2 cell0 - Writef(m, "exch "); // tab val2 cell0 val2 - Writef(m, "ceiling cvi "); // tab val2 cell0 cell1 - Writef(m, "3 index "); // tab val2 cell0 cell1 tab - Writef(m, "exch "); // tab val2 cell0 tab cell1 - Writef(m, "get "); // tab val2 cell0 y1 - Writef(m, "4 -1 roll "); // val2 cell0 y1 tab - Writef(m, "3 -1 roll "); // val2 y1 tab cell0 - Writef(m, "get "); // val2 y1 y0 - Writef(m, "dup "); // val2 y1 y0 y0 - Writef(m, "3 1 roll "); // val2 y0 y1 y0 - Writef(m, "sub "); // val2 y0 (y1-y0) - Writef(m, "3 -1 roll "); // y0 (y1-y0) val2 - Writef(m, "dup "); // y0 (y1-y0) val2 val2 - Writef(m, "floor cvi "); // y0 (y1-y0) val2 floor(val2) - Writef(m, "sub "); // y0 (y1-y0) rest - Writef(m, "mul "); // y0 t1 - Writef(m, "add "); // y - Writef(m, "65535 div "); // result + _cmsIOPrintf(m, "dup "); // v tab tab + _cmsIOPrintf(m, "length 1 sub "); // v tab dom + _cmsIOPrintf(m, "3 -1 roll "); // tab dom v + _cmsIOPrintf(m, "mul "); // tab val2 + _cmsIOPrintf(m, "dup "); // tab val2 val2 + _cmsIOPrintf(m, "dup "); // tab val2 val2 val2 + _cmsIOPrintf(m, "floor cvi "); // tab val2 val2 cell0 + _cmsIOPrintf(m, "exch "); // tab val2 cell0 val2 + _cmsIOPrintf(m, "ceiling cvi "); // tab val2 cell0 cell1 + _cmsIOPrintf(m, "3 index "); // tab val2 cell0 cell1 tab + _cmsIOPrintf(m, "exch "); // tab val2 cell0 tab cell1 + _cmsIOPrintf(m, "get "); // tab val2 cell0 y1 + _cmsIOPrintf(m, "4 -1 roll "); // val2 cell0 y1 tab + _cmsIOPrintf(m, "3 -1 roll "); // val2 y1 tab cell0 + _cmsIOPrintf(m, "get "); // val2 y1 y0 + _cmsIOPrintf(m, "dup "); // val2 y1 y0 y0 + _cmsIOPrintf(m, "3 1 roll "); // val2 y0 y1 y0 + _cmsIOPrintf(m, "sub "); // val2 y0 (y1-y0) + _cmsIOPrintf(m, "3 -1 roll "); // y0 (y1-y0) val2 + _cmsIOPrintf(m, "dup "); // y0 (y1-y0) val2 val2 + _cmsIOPrintf(m, "floor cvi "); // y0 (y1-y0) val2 floor(val2) + _cmsIOPrintf(m, "sub "); // y0 (y1-y0) rest + _cmsIOPrintf(m, "mul "); // y0 t1 + _cmsIOPrintf(m, "add "); // y + _cmsIOPrintf(m, "65535 div "); // result - Writef(m, " } bind "); + _cmsIOPrintf(m, " } bind "); } // Compare gamma table static -LCMSBOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries) +cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, int nEntries) { - return memcmp(g1, g2, nEntries* sizeof(WORD)) == 0; + return memcmp(g1, g2, nEntries* sizeof(cmsUInt16Number)) == 0; } // Does write a set of gamma curves static -void EmitNGamma(LPMEMSTREAM m, int n, LPWORD g[], int nEntries) +void EmitNGamma(cmsIOHANDLER* m, int n, cmsToneCurve* g[]) { int i; for( i=0; i < n; i++ ) { - if (i > 0 && GammaTableEquals(g[i-1], g[i], nEntries)) { + if (i > 0 && GammaTableEquals(g[i-1]->Table16, g[i]->Table16, g[i]->nEntries)) { - Writef(m, "dup "); + _cmsIOPrintf(m, "dup "); } else { - Emit1Gamma(m, g[i], nEntries); + Emit1Gamma(m, g[i]); } } } -// Check whatever a profile has CLUT tables (only on input) - -static -LCMSBOOL IsLUTbased(cmsHPROFILE hProfile, int Intent) -{ - icTagSignature Tag; - - // Check if adequate tag is present - Tag = Device2PCSTab[Intent]; - - if (cmsIsTag(hProfile, Tag)) return 1; - - // If not present, revert to default (perceptual) - Tag = icSigAToB0Tag; - - // If no tag present, try matrix-shaper - return cmsIsTag(hProfile, Tag); -} @@ -707,19 +599,19 @@ // that is, the callback will be called for each knot with // // In[] The grid location coordinates, normalized to 0..ffff -// Out[] The LUT values, normalized to 0..ffff +// Out[] The Pipeline values, normalized to 0..ffff // // Returning a value other than 0 does terminate the sampling process // -// Each row contains LUT values for all but first component. So, I +// Each row contains Pipeline values for all but first component. So, I // detect row changing by keeping a copy of last value of first // component. -1 is used to mark begining of whole block. static -int OutputValueSampler(register WORD In[], register WORD Out[], register LPVOID Cargo) +int OutputValueSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) { - LPSAMPLERCARGO sc = (LPSAMPLERCARGO) Cargo; - unsigned int i; + cmsPsSamplerCargo* sc = (cmsPsSamplerCargo*) Cargo; + cmsUInt32Number i; if (sc -> FixWhite) { @@ -729,14 +621,14 @@ if ((In[1] >= 0x7800 && In[1] <= 0x8800) && (In[2] >= 0x7800 && In[2] <= 0x8800)) { - WORD* Black; - WORD* White; - int nOutputs; + cmsUInt16Number* Black; + cmsUInt16Number* White; + cmsUInt32Number nOutputs; if (!_cmsEndPointsBySpace(sc ->ColorSpace, &White, &Black, &nOutputs)) return 0; - for (i=0; i < (unsigned int) nOutputs; i++) + for (i=0; i < nOutputs; i++) Out[i] = White[i]; } @@ -751,15 +643,15 @@ if (sc ->FirstComponent != -1) { - Writef(sc ->m, sc ->PostMin); + _cmsIOPrintf(sc ->m, sc ->PostMin); sc ->SecondComponent = -1; - Writef(sc ->m, sc ->PostMaj); + _cmsIOPrintf(sc ->m, sc ->PostMaj); } // Begin block - sc->m->Col = 0; + _cmsPSActualColumn = 0; - Writef(sc ->m, sc ->PreMaj); + _cmsIOPrintf(sc ->m, sc ->PreMaj); sc ->FirstComponent = In[0]; } @@ -768,96 +660,66 @@ if (sc ->SecondComponent != -1) { - Writef(sc ->m, sc ->PostMin); + _cmsIOPrintf(sc ->m, sc ->PostMin); } - Writef(sc ->m, sc ->PreMin); + _cmsIOPrintf(sc ->m, sc ->PreMin); sc ->SecondComponent = In[1]; } - - - // Dump table. Could be Word or byte based on - // depending on bps member (16 bps mode is not currently - // being used at all, but is here for future ampliations) - - for (i=0; i < sc -> Lut ->OutputChan; i++) { + // Dump table. - WORD wWordOut = Out[i]; - - if (sc ->bps == 8) { + for (i=0; i < sc -> Pipeline ->Params->nOutputs; i++) { - // Value as byte - BYTE wByteOut; - - // If is input, convert from Lab2 to Lab4 (just divide by 256) + cmsUInt16Number wWordOut = Out[i]; + cmsUInt8Number wByteOut; // Value as byte - if (sc ->lIsInput) { - - - wByteOut = L2Byte(wWordOut); - } - else - wByteOut = Word2Byte(wWordOut); + // We always deal with Lab4 - WriteByte(sc -> m, wByteOut); - } - else { + wByteOut = Word2Byte(wWordOut); + WriteByte(sc -> m, wByteOut); + } - // Value as word - WriteByte(sc -> m, (BYTE) (wWordOut & 0xFF)); - WriteByte(sc -> m, (BYTE) ((wWordOut >> 8) & 0xFF)); - } - } - - return 1; + return 1; } -// Writes a LUT on memstream. Could be 8 or 16 bits based +// Writes a Pipeline on memstream. Could be 8 or 16 bits based static -void WriteCLUT(LPMEMSTREAM m, LPLUT Lut, int bps, const char* PreMaj, - const char* PostMaj, - const char* PreMin, - const char* PostMin, - int lIsInput, - int FixWhite, - icColorSpaceSignature ColorSpace) +void WriteCLUT(cmsIOHANDLER* m, cmsStage* mpe, const char* PreMaj, + const char* PostMaj, + const char* PreMin, + const char* PostMin, + int FixWhite, + cmsColorSpaceSignature ColorSpace) { - unsigned int i; - SAMPLERCARGO sc; + cmsUInt32Number i; + cmsPsSamplerCargo sc; sc.FirstComponent = -1; sc.SecondComponent = -1; - sc.Lut = Lut; + sc.Pipeline = (_cmsStageCLutData *) mpe ->Data; sc.m = m; - sc.bps = bps; sc.PreMaj = PreMaj; sc.PostMaj= PostMaj; sc.PreMin = PreMin; sc.PostMin = PostMin; - sc.lIsInput = lIsInput; sc.FixWhite = FixWhite; sc.ColorSpace = ColorSpace; - Writef(m, "["); + _cmsIOPrintf(m, "["); - for (i=0; i < Lut ->InputChan; i++) - Writef(m, " %d ", Lut ->cLutPoints); - - Writef(m, " [\n"); - - + for (i=0; i < sc.Pipeline->Params->nInputs; i++) + _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]); - cmsSample3DGrid(Lut, OutputValueSampler, (LPVOID) &sc, SAMPLER_INSPECT); + _cmsIOPrintf(m, " [\n"); + cmsStageSampleCLut16bit(mpe, OutputValueSampler, (void*) &sc, SAMPLER_INSPECT); - Writef(m, PostMin); - Writef(m, PostMaj); - Writef(m, "] "); - - + _cmsIOPrintf(m, PostMin); + _cmsIOPrintf(m, PostMaj); + _cmsIOPrintf(m, "] "); } @@ -865,89 +727,92 @@ // Dumps CIEBasedA Color Space Array static -int EmitCIEBasedA(LPMEMSTREAM m, LPWORD Tab, int nEntries, LPcmsCIEXYZ BlackPoint) +int EmitCIEBasedA(cmsIOHANDLER* m, cmsToneCurve* Curve, cmsCIEXYZ* BlackPoint) { - Writef(m, "[ /CIEBasedA\n"); - Writef(m, " <<\n"); + _cmsIOPrintf(m, "[ /CIEBasedA\n"); + _cmsIOPrintf(m, " <<\n"); - Writef(m, "/DecodeA "); + _cmsIOPrintf(m, "/DecodeA "); - Emit1Gamma(m,Tab, nEntries); + Emit1Gamma(m, Curve); - Writef(m, " \n"); + _cmsIOPrintf(m, " \n"); - Writef(m, "/MatrixA [ 0.9642 1.0000 0.8249 ]\n"); - Writef(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n"); + _cmsIOPrintf(m, "/MatrixA [ 0.9642 1.0000 0.8249 ]\n"); + _cmsIOPrintf(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n"); - EmitWhiteBlackD50(m, BlackPoint); - EmitIntent(m, INTENT_PERCEPTUAL); + EmitWhiteBlackD50(m, BlackPoint); + EmitIntent(m, INTENT_PERCEPTUAL); - Writef(m, ">>\n"); - Writef(m, "]\n"); + _cmsIOPrintf(m, ">>\n"); + _cmsIOPrintf(m, "]\n"); - return 1; + return 1; } // Dumps CIEBasedABC Color Space Array static -int EmitCIEBasedABC(LPMEMSTREAM m, LPWORD L[], int nEntries, LPWMAT3 Matrix, LPcmsCIEXYZ BlackPoint) +int EmitCIEBasedABC(cmsIOHANDLER* m, cmsFloat64Number* Matrix, cmsToneCurve** CurveSet, cmsCIEXYZ* BlackPoint) { int i; - Writef(m, "[ /CIEBasedABC\n"); - Writef(m, "<<\n"); - Writef(m, "/DecodeABC [ "); + _cmsIOPrintf(m, "[ /CIEBasedABC\n"); + _cmsIOPrintf(m, "<<\n"); + _cmsIOPrintf(m, "/DecodeABC [ "); - EmitNGamma(m, 3, L, nEntries); + EmitNGamma(m, 3, CurveSet); - Writef(m, "]\n"); + _cmsIOPrintf(m, "]\n"); - Writef(m, "/MatrixABC [ " ); + _cmsIOPrintf(m, "/MatrixABC [ " ); - for( i=0; i < 3; i++ ) { + for( i=0; i < 3; i++ ) { - Writef(m, "%.6f %.6f %.6f ", - FIXED_TO_DOUBLE(Matrix->v[0].n[i]), - FIXED_TO_DOUBLE(Matrix->v[1].n[i]), - FIXED_TO_DOUBLE(Matrix->v[2].n[i])); - } + _cmsIOPrintf(m, "%.6f %.6f %.6f ", Matrix[0 + 3*i], + Matrix[1 + 3*i], + Matrix[2 + 3*i]); + } - Writef(m, "]\n"); + _cmsIOPrintf(m, "]\n"); - Writef(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n"); + _cmsIOPrintf(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n"); - EmitWhiteBlackD50(m, BlackPoint); - EmitIntent(m, INTENT_PERCEPTUAL); + EmitWhiteBlackD50(m, BlackPoint); + EmitIntent(m, INTENT_PERCEPTUAL); - Writef(m, ">>\n"); - Writef(m, "]\n"); + _cmsIOPrintf(m, ">>\n"); + _cmsIOPrintf(m, "]\n"); - return 1; + return 1; } static -int EmitCIEBasedDEF(LPMEMSTREAM m, LPLUT Lut, int Intent, LPcmsCIEXYZ BlackPoint) +int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXYZ* BlackPoint) { const char* PreMaj; const char* PostMaj; const char* PreMin, *PostMin; + cmsStage* mpe; - switch (Lut ->InputChan) { + mpe = Pipeline ->Elements; + + + switch (cmsStageInputChannels(mpe)) { case 3: - Writef(m, "[ /CIEBasedDEF\n"); + _cmsIOPrintf(m, "[ /CIEBasedDEF\n"); PreMaj ="<"; PostMaj= ">\n"; PreMin = PostMin = ""; break; case 4: - Writef(m, "[ /CIEBasedDEFG\n"); + _cmsIOPrintf(m, "[ /CIEBasedDEFG\n"); PreMaj = "["; PostMaj = "]\n"; PreMin = "<"; @@ -958,30 +823,32 @@ } - Writef(m, "<<\n"); + _cmsIOPrintf(m, "<<\n"); - if (Lut ->wFlags & LUT_HASTL1) { + if (cmsStageType(mpe) == cmsSigCurveSetElemType) { - Writef(m, "/DecodeDEF [ "); - EmitNGamma(m, Lut ->InputChan, Lut ->L1, Lut ->CLut16params.nSamples); - Writef(m, "]\n"); + _cmsIOPrintf(m, "/DecodeDEF [ "); + EmitNGamma(m, cmsStageOutputChannels(mpe), _cmsStageGetPtrToCurveSet(mpe)); + _cmsIOPrintf(m, "]\n"); + + mpe = mpe ->Next; } - if (Lut ->wFlags & LUT_HAS3DGRID) { + if (cmsStageType(mpe) == cmsSigCLutElemType) { - Writef(m, "/Table "); - WriteCLUT(m, Lut, 8, PreMaj, PostMaj, PreMin, PostMin, TRUE, FALSE, (icColorSpaceSignature) 0); - Writef(m, "]\n"); + _cmsIOPrintf(m, "/Table "); + WriteCLUT(m, mpe, PreMaj, PostMaj, PreMin, PostMin, FALSE, (cmsColorSpaceSignature) 0); + _cmsIOPrintf(m, "]\n"); } EmitLab2XYZ(m); EmitWhiteBlackD50(m, BlackPoint); EmitIntent(m, Intent); - Writef(m, " >>\n"); - Writef(m, "]\n"); + _cmsIOPrintf(m, " >>\n"); + _cmsIOPrintf(m, "]\n"); return 1; @@ -990,21 +857,21 @@ // Generates a curve from a gray profile static -LPGAMMATABLE ExtractGray2Y(cmsHPROFILE hProfile, int Intent) +cmsToneCurve* ExtractGray2Y(cmsContext ContextID, cmsHPROFILE hProfile, int Intent) { - LPGAMMATABLE Out = cmsAllocGamma(256); - cmsHPROFILE hXYZ = cmsCreateXYZProfile(); - cmsHTRANSFORM xform = cmsCreateTransform(hProfile, TYPE_GRAY_8, hXYZ, TYPE_XYZ_DBL, Intent, cmsFLAGS_NOTPRECALC); + cmsToneCurve* Out = cmsBuildTabulatedToneCurve16(ContextID, 256, NULL); + cmsHPROFILE hXYZ = cmsCreateXYZProfile(); + cmsHTRANSFORM xform = cmsCreateTransformTHR(ContextID, hProfile, TYPE_GRAY_8, hXYZ, TYPE_XYZ_DBL, Intent, cmsFLAGS_NOOPTIMIZE); int i; for (i=0; i < 256; i++) { - BYTE Gray = (BYTE) i; + cmsUInt8Number Gray = (cmsUInt8Number) i; cmsCIEXYZ XYZ; cmsDoTransform(xform, &Gray, &XYZ, 1); - Out ->GammaTable[i] =_cmsClampWord((int) floor(XYZ.Y * 65535.0 + 0.5)); + Out ->Table16[i] =_cmsQuickSaturateWord(XYZ.Y * 65535.0); } cmsDeleteTransform(xform); @@ -1014,17 +881,16 @@ -// Because PostScrip has only 8 bits in /Table, we should use +// Because PostScript has only 8 bits in /Table, we should use // a more perceptually uniform space... I do choose Lab. static -int WriteInputLUT(LPMEMSTREAM m, cmsHPROFILE hProfile, int Intent) +int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags) { cmsHPROFILE hLab; cmsHTRANSFORM xform; - icColorSpaceSignature ColorSpace; - int nChannels; - DWORD InputFormat; + cmsUInt32Number nChannels; + cmsUInt32Number InputFormat; int rc; cmsHPROFILE Profiles[2]; cmsCIEXYZ BlackPointAdaptedToD50; @@ -1032,49 +898,25 @@ // Does create a device-link based transform. // The DeviceLink is next dumped as working CSA. - hLab = cmsCreateLabProfile(NULL); - ColorSpace = cmsGetColorSpace(hProfile); - nChannels = _cmsChannelsOf(ColorSpace); - InputFormat = CHANNELS_SH(nChannels) | BYTES_SH(2); - - cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent,LCMS_BPFLAGS_D50_ADAPTED); - - // Is a devicelink profile? - if (cmsGetDeviceClass(hProfile) == icSigLinkClass) { - - // if devicelink output already Lab, use it directly - - if (cmsGetPCS(hProfile) == icSigLabData) { - - xform = cmsCreateTransform(hProfile, InputFormat, NULL, - TYPE_Lab_DBL, Intent, 0); - } - else { - - // Nope, adjust output to Lab if possible - - Profiles[0] = hProfile; - Profiles[1] = hLab; - - xform = cmsCreateMultiprofileTransform(Profiles, 2, InputFormat, - TYPE_Lab_DBL, Intent, 0); - } + InputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE); + nChannels = T_CHANNELS(InputFormat); - } - else { + cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0); + + // Adjust output to Lab4 + hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); - // This is a normal profile - xform = cmsCreateTransform(hProfile, InputFormat, hLab, - TYPE_Lab_DBL, Intent, 0); - } + Profiles[0] = hProfile; + Profiles[1] = hLab; - + xform = cmsCreateMultiprofileTransform(Profiles, 2, InputFormat, TYPE_Lab_DBL, Intent, 0); + cmsCloseProfile(hLab); if (xform == NULL) { - cmsSignalError(LCMS_ERRC_ABORTED, "Cannot create transform Profile -> Lab"); - return 0; + cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Profile -> Lab"); + return 0; } // Only 1, 3 and 4 channels are allowed @@ -1082,86 +924,82 @@ switch (nChannels) { case 1: { - LPGAMMATABLE Gray2Y = ExtractGray2Y(hProfile, Intent); - EmitCIEBasedA(m, Gray2Y->GammaTable, Gray2Y ->nEntries, &BlackPointAdaptedToD50); - cmsFreeGamma(Gray2Y); + cmsToneCurve* Gray2Y = ExtractGray2Y(m ->ContextID, hProfile, Intent); + EmitCIEBasedA(m, Gray2Y, &BlackPointAdaptedToD50); + cmsFreeToneCurve(Gray2Y); } break; case 3: case 4: { - LPLUT DeviceLink; - _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform; + cmsUInt32Number OutFrm = TYPE_Lab_16; + cmsPipeline* DeviceLink; + _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform; - if (v ->DeviceLink) - rc = EmitCIEBasedDEF(m, v->DeviceLink, Intent, &BlackPointAdaptedToD50); - else { - DeviceLink = _cmsPrecalculateDeviceLink(xform, 0); - rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50); - cmsFreeLUT(DeviceLink); - } + DeviceLink = cmsPipelineDup(v ->Lut); + if (DeviceLink == NULL) return 0; + + dwFlags |= cmsFLAGS_FORCE_CLUT; + _cmsOptimizePipeline(&DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags); + + rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50); + cmsPipelineFree(DeviceLink); } break; default: - cmsSignalError(LCMS_ERRC_ABORTED, "Only 3, 4 channels supported for CSA. This profile has %d channels.", nChannels); - return 0; + cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels supported for CSA. This profile has %d channels.", nChannels); + return 0; } cmsDeleteTransform(xform); - cmsCloseProfile(hLab); + return 1; } +static +cmsFloat64Number* GetPtrToMatrix(const cmsStage* mpe) +{ + _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data; + + return Data -> Double; +} // Does create CSA based on matrix-shaper. Allowed types are gray and RGB based static -int WriteInputMatrixShaper(LPMEMSTREAM m, cmsHPROFILE hProfile) +int WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matrix, cmsStage* Shaper) { - icColorSpaceSignature ColorSpace; - LPMATSHAPER MatShaper; + cmsColorSpaceSignature ColorSpace; int rc; cmsCIEXYZ BlackPointAdaptedToD50; - ColorSpace = cmsGetColorSpace(hProfile); - MatShaper = cmsBuildInputMatrixShaper(hProfile); - cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, INTENT_RELATIVE_COLORIMETRIC, LCMS_BPFLAGS_D50_ADAPTED); - - if (MatShaper == NULL) { + cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, INTENT_RELATIVE_COLORIMETRIC, 0); - cmsSignalError(LCMS_ERRC_ABORTED, "This profile is not suitable for input"); - return 0; - } + if (ColorSpace == cmsSigGrayData) { - if (ColorSpace == icSigGrayData) { - - rc = EmitCIEBasedA(m, MatShaper ->L[0], - MatShaper ->p16.nSamples, - &BlackPointAdaptedToD50); + cmsToneCurve** ShaperCurve = _cmsStageGetPtrToCurveSet(Shaper); + rc = EmitCIEBasedA(m, ShaperCurve[0], &BlackPointAdaptedToD50); } else - if (ColorSpace == icSigRgbData) { - + if (ColorSpace == cmsSigRgbData) { - rc = EmitCIEBasedABC(m, MatShaper->L, - MatShaper ->p16.nSamples, - &MatShaper ->Matrix, - &BlackPointAdaptedToD50); + rc = EmitCIEBasedABC(m, GetPtrToMatrix(Matrix), + _cmsStageGetPtrToCurveSet(Shaper), + &BlackPointAdaptedToD50); } else { - cmsSignalError(LCMS_ERRC_ABORTED, "Profile is not suitable for CSA. Unsupported colorspace."); + cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Profile is not suitable for CSA. Unsupported colorspace."); return 0; } - cmsFreeMatShaper(MatShaper); return rc; } @@ -1171,45 +1009,46 @@ // This is a HP extension, and it works in Lab instead of XYZ static -int WriteNamedColorCSA(LPMEMSTREAM m, cmsHPROFILE hNamedColor, int Intent) +int WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent) { cmsHTRANSFORM xform; cmsHPROFILE hLab; int i, nColors; char ColorName[32]; - + cmsNAMEDCOLORLIST* NamedColorList; - hLab = cmsCreateLabProfile(NULL); - xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, - hLab, TYPE_Lab_DBL, Intent, cmsFLAGS_NOTPRECALC); + hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); + xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, hLab, TYPE_Lab_DBL, Intent, 0); if (xform == NULL) return 0; + NamedColorList = cmsGetNamedColorList(xform); + if (NamedColorList == NULL) return 0; - Writef(m, "<<\n"); - Writef(m, "(colorlistcomment) (%s)\n", "Named color CSA"); - Writef(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n"); - Writef(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n"); + _cmsIOPrintf(m, "<<\n"); + _cmsIOPrintf(m, "(colorlistcomment) (%s)\n", "Named color CSA"); + _cmsIOPrintf(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n"); + _cmsIOPrintf(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n"); - nColors = cmsNamedColorCount(xform); + nColors = cmsNamedColorCount(NamedColorList); for (i=0; i < nColors; i++) { - WORD In[1]; + cmsUInt16Number In[1]; cmsCIELab Lab; - In[0] = (WORD) i; + In[0] = (cmsUInt16Number) i; - if (!cmsNamedColorInfo(xform, i, ColorName, NULL, NULL)) + if (!cmsNamedColorInfo(NamedColorList, i, ColorName, NULL, NULL, NULL, NULL)) continue; cmsDoTransform(xform, In, &Lab, 1); - Writef(m, " (%s) [ %.3f %.3f %.3f ]\n", ColorName, Lab.L, Lab.a, Lab.b); + _cmsIOPrintf(m, " (%s) [ %.3f %.3f %.3f ]\n", ColorName, Lab.L, Lab.a, Lab.b); } - Writef(m, ">>\n"); + _cmsIOPrintf(m, ">>\n"); cmsDeleteTransform(xform); cmsCloseProfile(hLab); @@ -1218,75 +1057,68 @@ // Does create a Color Space Array on XYZ colorspace for PostScript usage - -DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile, - int Intent, - LPVOID Buffer, DWORD dwBufferLen) +static +cmsUInt32Number GenerateCSA(cmsContext ContextID, + cmsHPROFILE hProfile, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags, + cmsIOHANDLER* mem) { - - LPMEMSTREAM mem; - DWORD dwBytesUsed; - - // Set up the serialization engine - mem = CreateMemStream((LPBYTE) Buffer, dwBufferLen, MAXPSCOLS); - if (!mem) return 0; + cmsUInt32Number dwBytesUsed; + cmsPipeline* lut = NULL; + cmsStage* Matrix, *Shaper; // Is a named color profile? - if (cmsGetDeviceClass(hProfile) == icSigNamedColorClass) { - - if (!WriteNamedColorCSA(mem, hProfile, Intent)) { + if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { - _cmsFree((void*) mem); - return 0; - } + if (!WriteNamedColorCSA(mem, hProfile, Intent)) goto Error; } else { - // Any profile class are allowed (including devicelink), but - // output (PCS) colorspace must be XYZ or Lab - icColorSpaceSignature ColorSpace = cmsGetPCS(hProfile); - - if (ColorSpace != icSigXYZData && - ColorSpace != icSigLabData) { + // Any profile class are allowed (including devicelink), but + // output (PCS) colorspace must be XYZ or Lab + cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile); - cmsSignalError(LCMS_ERRC_ABORTED, "Invalid output color space"); - _cmsFree((void*) mem); - return 0; - } + if (ColorSpace != cmsSigXYZData && + ColorSpace != cmsSigLabData) { - // Is there any CLUT? - if (IsLUTbased(hProfile, Intent)) { + cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Invalid output color space"); + goto Error; + } + - // Yes, so handle as LUT-based - if (!WriteInputLUT(mem, hProfile, Intent)) { + // Read the lut with all necessary conversion stages + lut = _cmsReadInputLUT(hProfile, Intent); + if (lut == NULL) goto Error; - _cmsFree((void*) mem); - return 0; - } - } - else { + + // Tone curves + matrix can be implemented without any LUT + if (cmsPipelineCheckAndRetreiveStages(lut, 2, cmsSigCurveSetElemType, cmsSigMatrixElemType, &Shaper, &Matrix)) { - // No, try Matrix-shaper (this only works on XYZ) - - if (!WriteInputMatrixShaper(mem, hProfile)) { + if (!WriteInputMatrixShaper(mem, hProfile, Matrix, Shaper)) goto Error; - _cmsFree((void*) mem); // Something went wrong - return 0; } - } + else { + // We need a LUT for the rest + if (!WriteInputLUT(mem, hProfile, Intent, dwFlags)) goto Error; + } } // Done, keep memory usage - dwBytesUsed = mem ->dwUsed; + dwBytesUsed = mem ->UsedSpace; - // Get rid of memory stream - _cmsFree((void*) mem); + // Get rid of LUT + if (lut != NULL) cmsPipelineFree(lut); // Finally, return used byte count return dwBytesUsed; + +Error: + if (lut != NULL) cmsPipelineFree(lut); + return 0; } // ------------------------------------------------------ Color Rendering Dictionary (CRD) @@ -1356,45 +1188,45 @@ static -void EmitPQRStage(LPMEMSTREAM m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute) +void EmitPQRStage(cmsIOHANDLER* m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute) { if (lIsAbsolute) { // For absolute colorimetric intent, encode back to relative - // and generate a relative LUT + // and generate a relative Pipeline // Relative encoding is obtained across XYZpcs*(D50/WhitePoint) cmsCIEXYZ White; - cmsTakeMediaWhitePoint(&White, hProfile); + _cmsReadMediaWhitePoint(&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"); + _cmsIOPrintf(m,"/MatrixPQR [1 0 0 0 1 0 0 0 1 ]\n"); + _cmsIOPrintf(m,"/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n"); - Writef(m, "%% Absolute colorimetric -- encode to relative to maximize LUT usage\n" + _cmsIOPrintf(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); + White.X, White.Y, White.Z); return; } - Writef(m,"%% Bradford Cone Space\n" + _cmsIOPrintf(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"); + _cmsIOPrintf(m, "/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n"); // No BPC if (!DoBPC) { - Writef(m, "%% VonKries-like transform in Bradford Cone Space\n" + _cmsIOPrintf(m, "%% VonKries-like transform in Bradford Cone Space\n" "/TransformPQR [\n" "{exch pop exch 3 get mul exch pop exch 3 get div} bind\n" "{exch pop exch 4 get mul exch pop exch 4 get div} bind\n" @@ -1403,22 +1235,22 @@ // BPC - Writef(m, "%% VonKries-like transform in Bradford Cone Space plus BPC\n" + _cmsIOPrintf(m, "%% VonKries-like transform in Bradford Cone Space plus BPC\n" "/TransformPQR [\n"); - Writef(m, "{4 index 3 get div 2 index 3 get mul " + _cmsIOPrintf(m, "{4 index 3 get div 2 index 3 get mul " "2 index 3 get 2 index 3 get sub mul " "2 index 3 get 4 index 3 get 3 index 3 get sub mul sub " "3 index 3 get 3 index 3 get exch sub div " "exch pop exch pop exch pop exch pop } bind\n"); - Writef(m, "{4 index 4 get div 2 index 4 get mul " + _cmsIOPrintf(m, "{4 index 4 get div 2 index 4 get mul " "2 index 4 get 2 index 4 get sub mul " "2 index 4 get 4 index 4 get 3 index 4 get sub mul sub " "3 index 4 get 3 index 4 get exch sub div " "exch pop exch pop exch pop exch pop } bind\n"); - Writef(m, "{4 index 5 get div 2 index 5 get mul " + _cmsIOPrintf(m, "{4 index 5 get div 2 index 5 get mul " "2 index 5 get 2 index 5 get sub mul " "2 index 5 get 4 index 5 get 3 index 5 get sub mul sub " "3 index 5 get 3 index 5 get exch sub div " @@ -1431,24 +1263,24 @@ static -void EmitXYZ2Lab(LPMEMSTREAM m) +void EmitXYZ2Lab(cmsIOHANDLER* 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"); - Writef(m, "{ 0.824900 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); - Writef(m, "]\n"); - Writef(m, "/MatrixABC [ 0 1 0 1 -1 1 0 0 -1 ]\n"); - Writef(m, "/EncodeABC [\n"); + _cmsIOPrintf(m, "/RangeLMN [ -0.635 2.0 0 2 -0.635 2.0 ]\n"); + _cmsIOPrintf(m, "/EncodeLMN [\n"); + _cmsIOPrintf(m, "{ 0.964200 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); + _cmsIOPrintf(m, "{ 1.000000 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); + _cmsIOPrintf(m, "{ 0.824900 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); + _cmsIOPrintf(m, "]\n"); + _cmsIOPrintf(m, "/MatrixABC [ 0 1 0 1 -1 1 0 0 -1 ]\n"); + _cmsIOPrintf(m, "/EncodeABC [\n"); - Writef(m, "{ 116 mul 16 sub 100 div } bind\n"); - Writef(m, "{ 500 mul 128 add 256 div } bind\n"); - Writef(m, "{ 200 mul 128 add 256 div } bind\n"); + _cmsIOPrintf(m, "{ 116 mul 16 sub 100 div } bind\n"); + _cmsIOPrintf(m, "{ 500 mul 128 add 256 div } bind\n"); + _cmsIOPrintf(m, "{ 200 mul 128 add 256 div } bind\n"); - Writef(m, "]\n"); + _cmsIOPrintf(m, "]\n"); } @@ -1460,104 +1292,74 @@ // 8 bits. static -int WriteOutputLUT(LPMEMSTREAM m, cmsHPROFILE hProfile, int Intent, DWORD dwFlags) +int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags) { cmsHPROFILE hLab; cmsHTRANSFORM xform; - icColorSpaceSignature ColorSpace; int i, nChannels; - DWORD OutputFormat; - _LPcmsTRANSFORM v; - LPLUT DeviceLink; + cmsUInt32Number OutputFormat; + _cmsTRANSFORM* v; + cmsPipeline* DeviceLink; cmsHPROFILE Profiles[3]; cmsCIEXYZ BlackPointAdaptedToD50; - LCMSBOOL lFreeDeviceLink = FALSE; - LCMSBOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION); - LCMSBOOL lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP); + cmsBool lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION); + cmsBool lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP); + cmsUInt32Number InFrm = TYPE_Lab_16; int RelativeEncodingIntent; - + cmsColorSpaceSignature ColorSpace; - hLab = cmsCreateLabProfile(NULL); + hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); + if (hLab == NULL) return 0; - ColorSpace = cmsGetColorSpace(hProfile); - nChannels = _cmsChannelsOf(ColorSpace); - OutputFormat = CHANNELS_SH(nChannels) | BYTES_SH(2); + OutputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE); + nChannels = T_CHANNELS(OutputFormat); - // For absolute colorimetric, the LUT is encoded as relative - // in order to preserve precission. + ColorSpace = cmsGetColorSpace(hProfile); + + // For absolute colorimetric, the LUT is encoded as relative in order to preserve precision. RelativeEncodingIntent = Intent; if (RelativeEncodingIntent == INTENT_ABSOLUTE_COLORIMETRIC) RelativeEncodingIntent = INTENT_RELATIVE_COLORIMETRIC; - // Is a devicelink profile? - if (cmsGetDeviceClass(hProfile) == icSigLinkClass) { - - // if devicelink input already in Lab - - if (ColorSpace == icSigLabData) { - - // adjust input to Lab to our v4 - - Profiles[0] = hLab; - Profiles[1] = hProfile; + // Use V4 Lab always + Profiles[0] = hLab; + Profiles[1] = hProfile; - xform = cmsCreateMultiprofileTransform(Profiles, 2, TYPE_Lab_DBL, - OutputFormat, RelativeEncodingIntent, - dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION); - - } - else { - cmsSignalError(LCMS_ERRC_ABORTED, "Cannot use devicelink profile for CRD creation"); - return 0; - } - - - } - else { - - // This is a normal profile - xform = cmsCreateTransform(hLab, TYPE_Lab_DBL, hProfile, - OutputFormat, RelativeEncodingIntent, dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION); - } + xform = cmsCreateMultiprofileTransformTHR(m ->ContextID, + Profiles, 2, TYPE_Lab_DBL, + OutputFormat, RelativeEncodingIntent, 0); + cmsCloseProfile(hLab); if (xform == NULL) { - cmsSignalError(LCMS_ERRC_ABORTED, "Cannot create transform Lab -> Profile in CRD creation"); - return 0; + cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Lab -> Profile in CRD creation"); + return 0; } - // Get the internal precalculated devicelink - - v = (_LPcmsTRANSFORM) xform; - DeviceLink = v ->DeviceLink; - - if (!DeviceLink) { - - DeviceLink = _cmsPrecalculateDeviceLink(xform, cmsFLAGS_NOPRELINEARIZATION); - lFreeDeviceLink = TRUE; - } - - Writef(m, "<<\n"); - Writef(m, "/ColorRenderingType 1\n"); + // Get a copy of the internal devicelink + v = (_cmsTRANSFORM*) xform; + DeviceLink = cmsPipelineDup(v ->Lut); + if (DeviceLink == NULL) return 0; - cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, LCMS_BPFLAGS_D50_ADAPTED); + // We need a CLUT + dwFlags |= cmsFLAGS_FORCE_CLUT; + _cmsOptimizePipeline(&DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags); + + _cmsIOPrintf(m, "<<\n"); + _cmsIOPrintf(m, "/ColorRenderingType 1\n"); + + + cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0); // Emit headers, etc. EmitWhiteBlackD50(m, &BlackPointAdaptedToD50); EmitPQRStage(m, hProfile, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC); EmitXYZ2Lab(m); - if (DeviceLink ->wFlags & LUT_HASTL1) { - - // Shouldn't happen - cmsSignalError(LCMS_ERRC_ABORTED, "Internal error (prelinearization on CRD)"); - return 0; - } - // FIXUP: map Lab (100, 0, 0) to perfect white, because the particular encoding for Lab // does map a=b=0 not falling into any specific node. Since range a,b goes -128..127, @@ -1568,31 +1370,30 @@ if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) lFixWhite = FALSE; - Writef(m, "/RenderTable "); + _cmsIOPrintf(m, "/RenderTable "); + - WriteCLUT(m, DeviceLink, 8, "<", ">\n", "", "", FALSE, - lFixWhite, ColorSpace); + WriteCLUT(m, cmsPipelineGetPtrToFirstStage(DeviceLink), "<", ">\n", "", "", lFixWhite, ColorSpace); - Writef(m, " %d {} bind ", nChannels); + _cmsIOPrintf(m, " %d {} bind ", nChannels); for (i=1; i < nChannels; i++) - Writef(m, "dup "); + _cmsIOPrintf(m, "dup "); - Writef(m, "]\n"); + _cmsIOPrintf(m, "]\n"); EmitIntent(m, Intent); - Writef(m, ">>\n"); + _cmsIOPrintf(m, ">>\n"); if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { - Writef(m, "/Current exch /ColorRendering defineresource pop\n"); + _cmsIOPrintf(m, "/Current exch /ColorRendering defineresource pop\n"); } - if (lFreeDeviceLink) cmsFreeLUT(DeviceLink); + cmsPipelineFree(DeviceLink); cmsDeleteTransform(xform); - cmsCloseProfile(hLab); return 1; } @@ -1600,14 +1401,14 @@ // Builds a ASCII string containing colorant list in 0..1.0 range static -void BuildColorantList(char *Colorant, int nColorant, WORD Out[]) +void BuildColorantList(char *Colorant, int nColorant, cmsUInt16Number Out[]) { char Buff[32]; int j; Colorant[0] = 0; - if (nColorant > MAXCHANNELS) - nColorant = MAXCHANNELS; + if (nColorant > cmsMAXCHANNELS) + nColorant = cmsMAXCHANNELS; for (j=0; j < nColorant; j++) { @@ -1624,50 +1425,54 @@ // This is a HP extension. static -int WriteNamedColorCRD(LPMEMSTREAM m, cmsHPROFILE hNamedColor, int Intent, DWORD dwFlags) +int WriteNamedColorCRD(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent, cmsUInt32Number dwFlags) { cmsHTRANSFORM xform; int i, nColors, nColorant; - DWORD OutputFormat; + cmsUInt32Number OutputFormat; char ColorName[32]; char Colorant[128]; + cmsNAMEDCOLORLIST* NamedColorList; - nColorant = _cmsChannelsOf(cmsGetColorSpace(hNamedColor)); - OutputFormat = CHANNELS_SH(nColorant) | BYTES_SH(2); - xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, - NULL, OutputFormat, Intent, cmsFLAGS_NOTPRECALC); + OutputFormat = cmsFormatterForColorspaceOfProfile(hNamedColor, 2, FALSE); + nColorant = T_CHANNELS(OutputFormat); + + + xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, NULL, OutputFormat, Intent, dwFlags); if (xform == NULL) return 0; - Writef(m, "<<\n"); - Writef(m, "(colorlistcomment) (%s) \n", "Named profile"); - Writef(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n"); - Writef(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n"); + NamedColorList = cmsGetNamedColorList(xform); + if (NamedColorList == NULL) return 0; - nColors = cmsNamedColorCount(xform); + _cmsIOPrintf(m, "<<\n"); + _cmsIOPrintf(m, "(colorlistcomment) (%s) \n", "Named profile"); + _cmsIOPrintf(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n"); + _cmsIOPrintf(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n"); + nColors = cmsNamedColorCount(NamedColorList); for (i=0; i < nColors; i++) { - WORD In[1]; - WORD Out[MAXCHANNELS]; + cmsUInt16Number In[1]; + cmsUInt16Number Out[cmsMAXCHANNELS]; - In[0] = (WORD) i; + In[0] = (cmsUInt16Number) i; - if (!cmsNamedColorInfo(xform, i, ColorName, NULL, NULL)) + if (!cmsNamedColorInfo(NamedColorList, i, ColorName, NULL, NULL, NULL, NULL)) continue; cmsDoTransform(xform, In, Out, 1); BuildColorantList(Colorant, nColorant, Out); - Writef(m, " (%s) [ %s ]\n", ColorName, Colorant); + _cmsIOPrintf(m, " (%s) [ %s ]\n", ColorName, Colorant); } - Writef(m, " >>"); + _cmsIOPrintf(m, " >>"); if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { - Writef(m, " /Current exch /HPSpotTable defineresource pop\n"); + _cmsIOPrintf(m, " /Current exch /HPSpotTable defineresource pop\n"); } cmsDeleteTransform(xform); @@ -1680,67 +1485,129 @@ // CRD are always LUT-Based, no matter if profile is // implemented as matrix-shaper. -DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile, - int Intent, DWORD dwFlags, - LPVOID Buffer, DWORD dwBufferLen) +static +cmsUInt32Number GenerateCRD(cmsContext ContextID, + cmsHPROFILE hProfile, + cmsUInt32Number Intent, cmsUInt32Number dwFlags, + cmsIOHANDLER* mem) { - - LPMEMSTREAM mem; - DWORD dwBytesUsed; - - // Set up the serialization artifact - mem = CreateMemStream((LPBYTE) Buffer, dwBufferLen, MAXPSCOLS); - if (!mem) return 0; - + cmsUInt32Number dwBytesUsed; if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { - EmitHeader(mem, "Color Rendering Dictionary (CRD)", hProfile); + EmitHeader(mem, "Color Rendering Dictionary (CRD)", hProfile); } // Is a named color profile? - if (cmsGetDeviceClass(hProfile) == icSigNamedColorClass) { + if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { if (!WriteNamedColorCRD(mem, hProfile, Intent, dwFlags)) { - - _cmsFree((void*) mem); - return 0; + return 0; } } else { - // CRD are always implemented as LUT. - + // CRD are always implemented as LUT - if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) { - _cmsFree((void*) mem); - return 0; - } + if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) { + return 0; + } } if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { - Writef(mem, "%%%%EndResource\n"); - Writef(mem, "\n%% CRD End\n"); + _cmsIOPrintf(mem, "%%%%EndResource\n"); + _cmsIOPrintf(mem, "\n%% CRD End\n"); } // Done, keep memory usage - dwBytesUsed = mem ->dwUsed; + dwBytesUsed = mem ->UsedSpace; + + // Finally, return used byte count + return dwBytesUsed; + + cmsUNUSED_PARAMETER(ContextID); +} + + + + +cmsUInt32Number CMSEXPORT cmsGetPostScriptColorResource(cmsContext ContextID, + cmsPSResourceType Type, + cmsHPROFILE hProfile, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags, + cmsIOHANDLER* io) +{ + cmsUInt32Number rc; + + + switch (Type) { + + case cmsPS_RESOURCE_CSA: + rc = GenerateCSA(ContextID, hProfile, Intent, dwFlags, io); + break; + default: + case cmsPS_RESOURCE_CRD: + rc = GenerateCRD(ContextID, hProfile, Intent, dwFlags, io); + break; + } + + return rc; +} + + + +cmsUInt32Number CMSEXPORT cmsGetPostScriptCRD(cmsContext ContextID, + cmsHPROFILE hProfile, + cmsUInt32Number Intent, cmsUInt32Number dwFlags, + void* Buffer, cmsUInt32Number dwBufferLen) +{ + cmsIOHANDLER* mem; + cmsUInt32Number dwBytesUsed; + + // Set up the serialization engine + if (Buffer == NULL) + mem = cmsOpenIOhandlerFromNULL(ContextID); + else + mem = cmsOpenIOhandlerFromMem(ContextID, Buffer, dwBufferLen, "w"); + + if (!mem) return 0; + + dwBytesUsed = cmsGetPostScriptColorResource(ContextID, cmsPS_RESOURCE_CRD, hProfile, Intent, dwFlags, mem); // Get rid of memory stream - _cmsFree((void*) mem); + cmsCloseIOhandler(mem); - // Finally, return used byte count return dwBytesUsed; } -// For compatibility with previous versions + +// Does create a Color Space Array on XYZ colorspace for PostScript usage +cmsUInt32Number CMSEXPORT cmsGetPostScriptCSA(cmsContext ContextID, + cmsHPROFILE hProfile, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags, + void* Buffer, + cmsUInt32Number dwBufferLen) +{ + cmsIOHANDLER* mem; + cmsUInt32Number dwBytesUsed; -DWORD LCMSEXPORT cmsGetPostScriptCRD(cmsHPROFILE hProfile, - int Intent, - LPVOID Buffer, DWORD dwBufferLen) -{ - return cmsGetPostScriptCRDEx(hProfile, Intent, 0, Buffer, dwBufferLen); + if (Buffer == NULL) + mem = cmsOpenIOhandlerFromNULL(ContextID); + else + mem = cmsOpenIOhandlerFromMem(ContextID, Buffer, dwBufferLen, "w"); + + if (!mem) return 0; + + dwBytesUsed = cmsGetPostScriptColorResource(ContextID, cmsPS_RESOURCE_CSA, hProfile, Intent, dwFlags, mem); + + // Get rid of memory stream + cmsCloseIOhandler(mem); + + return dwBytesUsed; + }