< prev index next >

src/java.desktop/share/native/liblcms/cmsps2.c

Print this page

        

@@ -28,11 +28,11 @@
 // file:
 //
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2017 Marti Maria Saguer
+//  Copyright (c) 1998-2020 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"),
 // to deal in the Software without restriction, including without limitation
 // the rights to use, copy, modify, merge, publish, distribute, sublicense,

@@ -105,12 +105,12 @@
 
 
    Matrix-shaper based
    -------------------
 
-   This is implemented both with /CIEBasedABC or /CIEBasedDEF on dependig
-   of profile implementation. Since here there are no interpolation tables, I do
+   This is implemented both with /CIEBasedABC or /CIEBasedDEF depending on the
+   profile implementation. Since here there are no interpolation tables, I do
    the conversion directly to XYZ
 
 
 
     [ /CIEBasedABC

@@ -322,25 +322,11 @@
 {
     return (cmsUInt8Number) floor((cmsFloat64Number) w / 257.0 + 0.5);
 }
 
 
-// Convert to byte (using ICC2 notation)
-/*
-static
-cmsUInt8Number L2Byte(cmsUInt16Number w)
-{
-    int ww = w + 0x0080;
-
-    if (ww > 0xFFFF) return 0xFF;
-
-    return (cmsUInt8Number) ((cmsUInt16Number) (ww >> 8) & 0xFF);
-}
-*/
-
 // Write a cooked byte
-
 static
 void WriteByte(cmsIOHANDLER* m, cmsUInt8Number b)
 {
     _cmsIOPrintf(m, "%02x", b);
     _cmsPSActualColumn += 2;

@@ -353,11 +339,12 @@
 }
 
 // ----------------------------------------------------------------- PostScript generation
 
 
-// Removes offending Carriage returns
+// Removes offending carriage returns
+
 static
 char* RemoveCR(const char* txt)
 {
     static char Buffer[2048];
     char* pt;

@@ -451,25 +438,10 @@
 //
 //      Y = Yn*[ (L* + 16) / 116] ^ 3   if (L*) >= 6 / 29
 //        = Yn*( L* / 116) / 7.787      if (L*) < 6 / 29
 //
 
-/*
-static
-void EmitL2Y(cmsIOHANDLER* m)
-{
-    _cmsIOPrintf(m,
-            "{ "
-                "100 mul 16 add 116 div "               // (L * 100 + 16) / 116
-                 "dup 6 29 div ge "                     // >= 6 / 29 ?
-                 "{ dup dup mul mul } "                 // yes, ^3 and done
-                 "{ 4 29 div sub 108 841 div mul } "    // no, slope limiting
-            "ifelse } bind ");
-}
-*/
-
-
 // Lab -> XYZ, see the discussion above
 
 static
 void EmitLab2XYZ(cmsIOHANDLER* m)
 {

@@ -486,16 +458,32 @@
     _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");
 }
 
+static
+void EmitSafeGuardBegin(cmsIOHANDLER* m, const char* name)
+{
+    _cmsIOPrintf(m, "%%LCMS2: Save previous definition of %s on the operand stack\n", name);
+    _cmsIOPrintf(m, "currentdict /%s known { /%s load } { null } ifelse\n", name, name);
+}
 
+static
+void EmitSafeGuardEnd(cmsIOHANDLER* m, const char* name, int depth)
+{
+    _cmsIOPrintf(m, "%%LCMS2: Restore previous definition of %s\n", name);
+    if (depth > 1) {
+        // cycle topmost items on the stack to bring the previous definition to the front
+        _cmsIOPrintf(m, "%d -1 roll ", depth);
+    }
+    _cmsIOPrintf(m, "dup null eq { pop currentdict /%s undef } { /%s exch def } ifelse\n", name, name);
+}
 
 // Outputs a table of words. It does use 16 bits
 
 static
-void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table)
+void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table, const char* name)
 {
     cmsUInt32Number i;
     cmsFloat64Number gamma;
 
     if (Table == NULL) return; // Error

@@ -506,32 +494,37 @@
     if (cmsIsToneCurveLinear(Table)) return;
 
     // Check if is really an exponential. If so, emit "exp"
     gamma = cmsEstimateGamma(Table, 0.001);
      if (gamma > 0) {
-            _cmsIOPrintf(m, "{ %g exp } bind ", gamma);
+            _cmsIOPrintf(m, "/%s { %g exp } bind def\n", name, gamma);
             return;
      }
 
-    _cmsIOPrintf(m, "{ ");
+    EmitSafeGuardBegin(m, "lcms2gammatable");
+    _cmsIOPrintf(m, "/lcms2gammatable [");
 
-    // Bounds check
-    EmitRangeCheck(m);
+    for (i=0; i < Table->nEntries; i++) {
+        if (i % 10 == 0)
+            _cmsIOPrintf(m, "\n  ");
+        _cmsIOPrintf(m, "%d ", Table->Table16[i]);
+    }
+
+    _cmsIOPrintf(m, "] def\n");
 
-    // Emit intepolation code
+
+    // Emit interpolation code
 
     // PostScript code                      Stack
     // ===============                      ========================
                                             // v
-    _cmsIOPrintf(m, " [");
+    _cmsIOPrintf(m, "/%s {\n  ", name);
 
-    for (i=0; i < Table->nEntries; i++) {
-        _cmsIOPrintf(m, "%d ", Table->Table16[i]);
-    }
-
-    _cmsIOPrintf(m, "] ");                        // v tab
+    // Bounds check
+    EmitRangeCheck(m);
 
+    _cmsIOPrintf(m, "\n  //lcms2gammatable ");    // v tab
     _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

@@ -539,11 +532,11 @@
     _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, "get\n  ");                   // 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

@@ -552,13 +545,15 @@
     _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
+    _cmsIOPrintf(m, "65535 div\n");               // result
+
+    _cmsIOPrintf(m, "} bind def\n");
 
-    _cmsIOPrintf(m, " } bind ");
+    EmitSafeGuardEnd(m, "lcms2gammatable", 1);
 }
 
 
 // Compare gamma table
 

@@ -570,33 +565,33 @@
 
 
 // Does write a set of gamma curves
 
 static
-void EmitNGamma(cmsIOHANDLER* m, cmsUInt32Number n, cmsToneCurve* g[])
+void EmitNGamma(cmsIOHANDLER* m, cmsUInt32Number n, cmsToneCurve* g[], const char* nameprefix)
 {
     cmsUInt32Number i;
+    static char buffer[2048];
 
     for( i=0; i < n; i++ )
     {
         if (g[i] == NULL) return; // Error
 
         if (i > 0 && GammaTableEquals(g[i-1]->Table16, g[i]->Table16, g[i]->nEntries)) {
 
-            _cmsIOPrintf(m, "dup ");
+            _cmsIOPrintf(m, "/%s%d /%s%d load def\n", nameprefix, i, nameprefix, i-1);
         }
         else {
-            Emit1Gamma(m, g[i]);
+            snprintf(buffer, sizeof(buffer), "%s%d", nameprefix, i);
+            buffer[sizeof(buffer)-1] = '\0';
+            Emit1Gamma(m, g[i], buffer);
         }
     }
 
 }
 
 
-
-
-
 // Following code dumps a LUT onto memory stream
 
 
 // This is the sampler. Intended to work in SAMPLER_INSPECT mode,
 // that is, the callback will be called for each knot with

@@ -609,11 +604,11 @@
 //  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 beginning of whole block.
 
 static
-int OutputValueSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
+int OutputValueSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Number Out[], CMSREGISTER void* Cargo)
 {
     cmsPsSamplerCargo* sc = (cmsPsSamplerCargo*) Cargo;
     cmsUInt32Number i;
 
 

@@ -735,15 +730,15 @@
 {
 
     _cmsIOPrintf(m, "[ /CIEBasedA\n");
     _cmsIOPrintf(m, "  <<\n");
 
-    _cmsIOPrintf(m, "/DecodeA ");
-
-    Emit1Gamma(m, Curve);
+    EmitSafeGuardBegin(m, "lcms2gammaproc");
+    Emit1Gamma(m, Curve, "lcms2gammaproc");
 
-    _cmsIOPrintf(m, " \n");
+    _cmsIOPrintf(m, "/DecodeA /lcms2gammaproc load\n");
+    EmitSafeGuardEnd(m, "lcms2gammaproc", 3);
 
     _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);

@@ -763,15 +758,23 @@
 {
     int i;
 
     _cmsIOPrintf(m, "[ /CIEBasedABC\n");
     _cmsIOPrintf(m, "<<\n");
-    _cmsIOPrintf(m, "/DecodeABC [ ");
-
-    EmitNGamma(m, 3, CurveSet);
 
+    EmitSafeGuardBegin(m, "lcms2gammaproc0");
+    EmitSafeGuardBegin(m, "lcms2gammaproc1");
+    EmitSafeGuardBegin(m, "lcms2gammaproc2");
+    EmitNGamma(m, 3, CurveSet, "lcms2gammaproc");
+    _cmsIOPrintf(m, "/DecodeABC [\n");
+    _cmsIOPrintf(m, "   /lcms2gammaproc0 load\n");
+    _cmsIOPrintf(m, "   /lcms2gammaproc1 load\n");
+    _cmsIOPrintf(m, "   /lcms2gammaproc2 load\n");
     _cmsIOPrintf(m, "]\n");
+    EmitSafeGuardEnd(m, "lcms2gammaproc2", 3);
+    EmitSafeGuardEnd(m, "lcms2gammaproc1", 3);
+    EmitSafeGuardEnd(m, "lcms2gammaproc0", 3);
 
     _cmsIOPrintf(m, "/MatrixABC [ " );
 
     for( i=0; i < 3; i++ ) {
 

@@ -799,50 +802,69 @@
 static
 int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, cmsUInt32Number Intent, cmsCIEXYZ* BlackPoint)
 {
     const char* PreMaj;
     const char* PostMaj;
-    const char* PreMin, *PostMin;
+    const char* PreMin, * PostMin;
     cmsStage* mpe;
+    int i, numchans;
+    static char buffer[2048];
 
-    mpe = Pipeline ->Elements;
+    mpe = Pipeline->Elements;
 
     switch (cmsStageInputChannels(mpe)) {
     case 3:
-
             _cmsIOPrintf(m, "[ /CIEBasedDEF\n");
-            PreMaj ="<";
-            PostMaj= ">\n";
+        PreMaj = "<";
+        PostMaj = ">\n";
             PreMin = PostMin = "";
             break;
+
     case 4:
             _cmsIOPrintf(m, "[ /CIEBasedDEFG\n");
             PreMaj = "[";
             PostMaj = "]\n";
             PreMin = "<";
             PostMin = ">\n";
             break;
+
     default:
             return 0;
 
     }
 
     _cmsIOPrintf(m, "<<\n");
 
     if (cmsStageType(mpe) == cmsSigCurveSetElemType) {
 
-        _cmsIOPrintf(m, "/DecodeDEF [ ");
-        EmitNGamma(m, cmsStageOutputChannels(mpe), _cmsStageGetPtrToCurveSet(mpe));
+        numchans = cmsStageOutputChannels(mpe);
+        for (i = 0; i < numchans; ++i) {
+            snprintf(buffer, sizeof(buffer), "lcms2gammaproc%d", i);
+            buffer[sizeof(buffer) - 1] = '\0';
+            EmitSafeGuardBegin(m, buffer);
+        }
+        EmitNGamma(m, cmsStageOutputChannels(mpe), _cmsStageGetPtrToCurveSet(mpe), "lcms2gammaproc");
+        _cmsIOPrintf(m, "/DecodeDEF [\n");
+        for (i = 0; i < numchans; ++i) {
+            snprintf(buffer, sizeof(buffer), "  /lcms2gammaproc%d load\n", i);
+            buffer[sizeof(buffer) - 1] = '\0';
+            _cmsIOPrintf(m, buffer);
+        }
         _cmsIOPrintf(m, "]\n");
+        for (i = numchans - 1; i >= 0; --i) {
+            snprintf(buffer, sizeof(buffer), "lcms2gammaproc%d", i);
+            buffer[sizeof(buffer) - 1] = '\0';
+            EmitSafeGuardEnd(m, buffer, 3);
+        }
 
-        mpe = mpe ->Next;
+        mpe = mpe->Next;
     }
 
     if (cmsStageType(mpe) == cmsSigCLutElemType) {
 
             _cmsIOPrintf(m, "/Table ");
-            WriteCLUT(m, mpe, PreMaj, PostMaj, PreMin, PostMin, FALSE, (cmsColorSpaceSignature) 0);
+        WriteCLUT(m, mpe, PreMaj, PostMaj, PreMin, PostMin, FALSE, (cmsColorSpaceSignature)0);
             _cmsIOPrintf(m, "]\n");
     }
 
     EmitLab2XYZ(m);
     EmitWhiteBlackD50(m, BlackPoint);

@@ -950,11 +972,11 @@
             }
             break;
 
     default:
 
-        cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels supported for CSA. This profile has %d channels.", nChannels);
+        cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels are supported for CSA. This profile has %d channels.", nChannels);
         return 0;
     }
 
 
     cmsDeleteTransform(xform);

@@ -1266,12 +1288,10 @@
                     "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 "
                     "exch pop exch pop exch pop exch pop } bind\n]\n");
 
         }
-
-
 }
 
 
 static
 void EmitXYZ2Lab(cmsIOHANDLER* m)

@@ -1297,11 +1317,11 @@
 }
 
 // Due to impedance mismatch between XYZ and almost all RGB and CMYK spaces
 // I choose to dump LUTS in Lab instead of XYZ. There is still a lot of wasted
 // space on 3D CLUT, but since space seems not to be a problem here, 33 points
-// would give a reasonable accurancy. Note also that CRD tables must operate in
+// would give a reasonable accuracy. Note also that CRD tables must operate in
 // 8 bits.
 
 static
 int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
 {
< prev index next >