📄 cmsps2.c
字号:
// ----------------------------------------------------------------- PostScript generation// Removes offending Carriage returnsstatic char* RemoveCR(const char* txt){ static char Buffer[2048]; char* pt; strncpy(Buffer, txt, 2047); Buffer[2047] = 0; for (pt = Buffer; *pt; pt++) if (*pt == '\n' || *pt == '\r') *pt = ' '; return Buffer;}staticvoid EmitHeader(LPMEMSTREAM m, const char* Title, cmsHPROFILE hProfile){ time_t timer; 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");}// Emits White & Black point. White point is always D50, Black point is the device // Black point adapted to D50. staticvoid EmitWhiteBlackD50(LPMEMSTREAM m, LPcmsCIEXYZ BlackPoint){ Writef(m, "/BlackPoint [%f %f %f]\n", BlackPoint -> X, BlackPoint -> Y, BlackPoint -> Z); Writef(m, "/WhitePoint [%f %f %f]\n", cmsD50_XYZ()->X, cmsD50_XYZ()->Y, cmsD50_XYZ()->Z);}staticvoid EmitRangeCheck(LPMEMSTREAM m){ Writef(m, "dup 0.0 lt { pop 0.0 } if " "dup 1.0 gt { pop 1.0 } if ");}// Does write the intentstaticvoid EmitIntent(LPMEMSTREAM m, int RenderingIntent){ const char *intent; switch (RenderingIntent) { case INTENT_PERCEPTUAL: intent = "Perceptual"; break; case INTENT_RELATIVE_COLORIMETRIC: intent = "RelativeColorimetric"; break; case INTENT_ABSOLUTE_COLORIMETRIC: intent = "AbsoluteColorimetric"; break; case INTENT_SATURATION: intent = "Saturation"; break; default: intent = "Undefined"; break; } Writef(m, "/RenderingIntent (%s)\n", intent ); }//// Convert L* to Y//// Y = Yn*[ (L* + 16) / 116] ^ 3 if (L*) >= 6 / 29// = Yn*( L* / 116) / 7.787 if (L*) < 6 / 29///*staticvoid EmitL2Y(LPMEMSTREAM m){ Writef(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 abovestaticvoid EmitLab2XYZ(LPMEMSTREAM 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.0 0.9642 0.0 1.0000 0.0 0.8249 ]\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");}// Outputs a table of words. It does use 16 bitsstaticvoid Emit1Gamma(LPMEMSTREAM m, LPWORD Table, int nEntries){ int i; double gamma; if (nEntries <= 0) return; // Empty table // Suppress whole if identity if (cmsIsLinear(Table, nEntries)) return; // Check if is really an exponential. If so, emit "exp" gamma = cmsEstimateGammaEx(Table, nEntries, 0.001); if (gamma > 0) { Writef(m, "{ %g exp } bind ", gamma); return; } Writef(m, "{ "); // Bounds check EmitRangeCheck(m); // Emit intepolation code // PostScript code Stack // =============== ======================== // v Writef(m, " ["); // TODO: Check for endianess!!! for (i=0; i < nEntries; i++) { Writef(m, "%d ", Table[i]); } Writef(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 Writef(m, " } bind ");}// Compare gamma tablestaticBOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries){ return memcmp(g1, g2, nEntries* sizeof(WORD)) == 0;}// Does write a set of gamma curvesstaticvoid EmitNGamma(LPMEMSTREAM m, int n, LPWORD g[], int nEntries) { int i; for( i=0; i < n; i++ ) { if (i > 0 && GammaTableEquals(g[i-1], g[i], nEntries)) { Writef(m, "dup "); } else { Emit1Gamma(m, g[i], nEntries); } } }// Check whatever a profile has CLUT tables (only on input)staticBOOL 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);}// 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//// In[] The grid location coordinates, normalized to 0..ffff// Out[] The LUT 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 // detect row changing by keeping a copy of last value of first // component. -1 is used to mark begining of whole block.staticint OutputValueSampler(register WORD In[], register WORD Out[], register LPVOID Cargo){ LPSAMPLERCARGO sc = (LPSAMPLERCARGO) Cargo; unsigned int i; if (sc -> FixWhite) { if (In[0] == 0xFFFF) { // Only in L* = 100 if ((In[1] >= 0x8000 && In[1] <= 0x87FF) || (In[2] >= 0x8000 && In[2] <= 0x87FF)) { WORD* Black; WORD* White; int nOutputs; if (!_cmsEndPointsBySpace(sc ->ColorSpace, &White, &Black, &nOutputs)) return 0; for (i=0; i < (unsigned int) nOutputs; i++) Out[i] = White[i]; } } } // Hadle the parenthesis on rows if (In[0] != sc ->FirstComponent) { if (sc ->FirstComponent != -1) { Writef(sc ->m, sc ->PostMin); sc ->SecondComponent = -1; Writef(sc ->m, sc ->PostMaj); } // Begin block sc->m->Col = 0; Writef(sc ->m, sc ->PreMaj); sc ->FirstComponent = In[0]; } if (In[1] != sc ->SecondComponent) { if (sc ->SecondComponent != -1) { Writef(sc ->m, sc ->PostMin); } Writef(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++) { WORD wWordOut = Out[i]; if (sc ->bps == 8) { // Value as byte BYTE wByteOut; // If is input, convert from Lab2 to Lab4 (just divide by 256) if (sc ->lIsInput) { wByteOut = L2Byte(wWordOut); } else wByteOut = Word2Byte(wWordOut); WriteByte(sc -> m, wByteOut); } else { // Value as word WriteByte(sc -> m, (BYTE) (wWordOut & 0xFF)); WriteByte(sc -> m, (BYTE) ((wWordOut >> 8) & 0xFF)); } } return 1;}// Writes a LUT on memstream. Could be 8 or 16 bits basedstaticvoid 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){ unsigned int i; SAMPLERCARGO sc; sc.FirstComponent = -1; sc.SecondComponent = -1; sc.Lut = Lut; 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, "["); for (i=0; i < Lut ->InputChan; i++) Writef(m, " %d ", Lut ->cLutPoints); Writef(m, " [\n"); cmsSample3DGrid(Lut, OutputValueSampler, (LPVOID) &sc, SAMPLER_INSPECT); Writef(m, PostMin); Writef(m, PostMaj); Writef(m, "] "); }// Dumps CIEBasedA Color Space Arraystaticint EmitCIEBasedA(LPMEMSTREAM m, LPWORD Tab, int nEntries, LPcmsCIEXYZ BlackPoint){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -