< prev index next >

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

Print this page

        

*** 28,38 **** // file: // //--------------------------------------------------------------------------------- // // Little Color Management System ! // Copyright (c) 1998-2017 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, --- 28,38 ---- // file: // //--------------------------------------------------------------------------------- // // Little Color Management System ! // 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,116 **** 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 the conversion directly to XYZ [ /CIEBasedABC --- 105,116 ---- Matrix-shaper based ------------------- ! 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,346 **** { 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; --- 322,332 ----
*** 353,363 **** } // ----------------------------------------------------------------- PostScript generation ! // Removes offending Carriage returns static char* RemoveCR(const char* txt) { static char Buffer[2048]; char* pt; --- 339,350 ---- } // ----------------------------------------------------------------- PostScript generation ! // Removes offending carriage returns ! static char* RemoveCR(const char* txt) { static char Buffer[2048]; char* pt;
*** 451,475 **** // // 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) { --- 438,447 ----
*** 486,501 **** _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"); } // Outputs a table of words. It does use 16 bits static ! void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table) { cmsUInt32Number i; cmsFloat64Number gamma; if (Table == NULL) return; // Error --- 458,489 ---- _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, const char* name) { cmsUInt32Number i; cmsFloat64Number gamma; if (Table == NULL) return; // Error
*** 506,537 **** 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); return; } ! _cmsIOPrintf(m, "{ "); ! // Bounds check ! EmitRangeCheck(m); ! // Emit intepolation code // PostScript code Stack // =============== ======================== // v ! _cmsIOPrintf(m, " ["); ! for (i=0; i < Table->nEntries; i++) { ! _cmsIOPrintf(m, "%d ", Table->Table16[i]); ! } ! ! _cmsIOPrintf(m, "] "); // 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 --- 494,530 ---- if (cmsIsToneCurveLinear(Table)) return; // Check if is really an exponential. If so, emit "exp" gamma = cmsEstimateGamma(Table, 0.001); if (gamma > 0) { ! _cmsIOPrintf(m, "/%s { %g exp } bind def\n", name, gamma); return; } ! EmitSafeGuardBegin(m, "lcms2gammatable"); ! _cmsIOPrintf(m, "/lcms2gammatable ["); ! 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 interpolation code // PostScript code Stack // =============== ======================== // v ! _cmsIOPrintf(m, "/%s {\n ", name); ! // 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,549 **** _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 --- 532,542 ---- _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\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,564 **** _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, " } bind "); } // Compare gamma table --- 545,559 ---- _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\n"); // result ! ! _cmsIOPrintf(m, "} bind def\n"); ! EmitSafeGuardEnd(m, "lcms2gammatable", 1); } // Compare gamma table
*** 570,602 **** // Does write a set of gamma curves static ! void EmitNGamma(cmsIOHANDLER* m, cmsUInt32Number n, cmsToneCurve* g[]) { cmsUInt32Number i; 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 "); } else { ! Emit1Gamma(m, g[i]); } } } - - - // 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 --- 565,597 ---- // Does write a set of gamma curves static ! 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, "/%s%d /%s%d load def\n", nameprefix, i, nameprefix, i-1); } else { ! 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,619 **** // 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) { cmsPsSamplerCargo* sc = (cmsPsSamplerCargo*) Cargo; cmsUInt32Number i; --- 604,614 ---- // 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(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Number Out[], CMSREGISTER void* Cargo) { cmsPsSamplerCargo* sc = (cmsPsSamplerCargo*) Cargo; cmsUInt32Number i;
*** 735,749 **** { _cmsIOPrintf(m, "[ /CIEBasedA\n"); _cmsIOPrintf(m, " <<\n"); ! _cmsIOPrintf(m, "/DecodeA "); ! ! Emit1Gamma(m, Curve); ! _cmsIOPrintf(m, " \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); --- 730,744 ---- { _cmsIOPrintf(m, "[ /CIEBasedA\n"); _cmsIOPrintf(m, " <<\n"); ! EmitSafeGuardBegin(m, "lcms2gammaproc"); ! Emit1Gamma(m, Curve, "lcms2gammaproc"); ! _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,777 **** { int i; _cmsIOPrintf(m, "[ /CIEBasedABC\n"); _cmsIOPrintf(m, "<<\n"); - _cmsIOPrintf(m, "/DecodeABC [ "); - - EmitNGamma(m, 3, CurveSet); _cmsIOPrintf(m, "]\n"); _cmsIOPrintf(m, "/MatrixABC [ " ); for( i=0; i < 3; i++ ) { --- 758,780 ---- { int i; _cmsIOPrintf(m, "[ /CIEBasedABC\n"); _cmsIOPrintf(m, "<<\n"); + 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,848 **** static int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, cmsUInt32Number Intent, cmsCIEXYZ* BlackPoint) { const char* PreMaj; const char* PostMaj; ! const char* PreMin, *PostMin; cmsStage* mpe; ! mpe = Pipeline ->Elements; switch (cmsStageInputChannels(mpe)) { case 3: - _cmsIOPrintf(m, "[ /CIEBasedDEF\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)); _cmsIOPrintf(m, "]\n"); ! mpe = mpe ->Next; } if (cmsStageType(mpe) == cmsSigCLutElemType) { _cmsIOPrintf(m, "/Table "); ! WriteCLUT(m, mpe, PreMaj, PostMaj, PreMin, PostMin, FALSE, (cmsColorSpaceSignature) 0); _cmsIOPrintf(m, "]\n"); } EmitLab2XYZ(m); EmitWhiteBlackD50(m, BlackPoint); --- 802,870 ---- static int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, cmsUInt32Number Intent, cmsCIEXYZ* BlackPoint) { const char* PreMaj; const char* PostMaj; ! const char* PreMin, * PostMin; cmsStage* mpe; + int i, numchans; + static char buffer[2048]; ! mpe = Pipeline->Elements; switch (cmsStageInputChannels(mpe)) { case 3: _cmsIOPrintf(m, "[ /CIEBasedDEF\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) { ! 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; } if (cmsStageType(mpe) == cmsSigCLutElemType) { _cmsIOPrintf(m, "/Table "); ! WriteCLUT(m, mpe, PreMaj, PostMaj, PreMin, PostMin, FALSE, (cmsColorSpaceSignature)0); _cmsIOPrintf(m, "]\n"); } EmitLab2XYZ(m); EmitWhiteBlackD50(m, BlackPoint);
*** 950,960 **** } break; default: ! cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels supported for CSA. This profile has %d channels.", nChannels); return 0; } cmsDeleteTransform(xform); --- 972,982 ---- } break; default: ! 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,1277 **** "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) --- 1288,1297 ----
*** 1297,1307 **** } // 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 // 8 bits. static int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags) { --- 1317,1327 ---- } // 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 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 >