📄 cmsps2.c
字号:
(WPout - BPout)*X - WPout*(BPin - BPout) out = --------------------------------------- WPout - BPin Algorithm discussion ==================== TransformPQR(WPin, BPin, WPout, BPout, PQR) Wpin,etc= { Xws Yws Zws Pws Qws Rws } Algorithm Stack 0...n =========================================================== PQR BPout WPout BPin WPin 4 index 3 get WPin PQR BPout WPout BPin WPin div (PQR/WPin) BPout WPout BPin WPin 2 index 3 get WPout (PQR/WPin) BPout WPout BPin WPin mult WPout*(PQR/WPin) BPout WPout BPin WPin 2 index 3 get WPout WPout*(PQR/WPin) BPout WPout BPin WPin 2 index 3 get BPout WPout WPout*(PQR/WPin) BPout WPout BPin WPin sub (WPout-BPout) WPout*(PQR/WPin) BPout WPout BPin WPin mult (WPout-BPout)* WPout*(PQR/WPin) BPout WPout BPin WPin 2 index 3 get WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin 4 index 3 get BPin WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin 3 index 3 get BPout BPin WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin sub (BPin-BPout) WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin mult (BPin-BPout)*WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin sub (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin 3 index 3 get BPin (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin 3 index 3 get WPout BPin (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin exch sub (WPout-BPin) (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin div exch pop exch pop exch pop exch pop*/staticvoid EmitPQRStage(LPMEMSTREAM m, int DoBPC, int lIsAbsolute){ 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) { Writef(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" "{exch pop exch 5 get mul exch pop exch 5 get div} bind\n]\n"); } else { // BPC Writef(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 " "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 " "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 " "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 " "exch pop exch pop exch pop exch pop } bind\n]\n"); } }staticvoid EmitXYZ2Lab(LPMEMSTREAM m){ 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"); 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, "{ 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"); }// 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.staticint WriteOutputLUT(LPMEMSTREAM m, cmsHPROFILE hProfile, int Intent, DWORD dwFlags){ cmsHPROFILE hLab; cmsHTRANSFORM xform; icColorSpaceSignature ColorSpace; int i, nChannels; DWORD OutputFormat; _LPcmsTRANSFORM v; LPLUT DeviceLink; cmsHPROFILE Profiles[3]; cmsCIEXYZ BlackPointAdaptedToD50; BOOL lFreeDeviceLink = FALSE; BOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION); // 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); ColorSpace = cmsGetColorSpace(hProfile); nChannels = _cmsChannelsOf(ColorSpace); OutputFormat = CHANNELS_SH(nChannels) | BYTES_SH(2); // Is a devicelink profile? if (cmsGetDeviceClass(hProfile) == icSigLinkClass) { // if devicelink input already in Lab if (ColorSpace == icSigLabData) { // adjust input to Lab to out v4 Profiles[0] = hLab; Profiles[1] = hProfile; xform = cmsCreateMultiprofileTransform(Profiles, 2, TYPE_Lab_DBL, OutputFormat, Intent, 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, Intent, cmsFLAGS_NOPRELINEARIZATION); } if (xform == NULL) { cmsSignalError(LCMS_ERRC_ABORTED, "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, 0); lFreeDeviceLink = TRUE; } Writef(m, "<<\n"); Writef(m, "/ColorRenderingType 1\n"); cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, LCMS_BPFLAGS_D50_ADAPTED); // Emit headers, etc. EmitWhiteBlackD50(m, &BlackPointAdaptedToD50); EmitPQRStage(m, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC); EmitXYZ2Lab(m); if (DeviceLink ->wFlags & LUT_HASTL1) { // Shouldn't happen cmsSignalError(LCMS_ERRC_ABORTED, "Internal error (prelinearization on CRD)"); } // 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, // zero is slightly moved towards right, so assure next node (in L=100 slice) is mapped to // zero. This would sacrifice a bit of highlights, but failure to do so would cause // scum dot. Ouch. Writef(m, "/RenderTable "); WriteCLUT(m, DeviceLink, 8, "<", ">\n", "", "", FALSE, (Intent != INTENT_ABSOLUTE_COLORIMETRIC), ColorSpace); Writef(m, " %d {} bind ", nChannels); for (i=1; i < nChannels; i++) Writef(m, "dup "); Writef(m, "]\n"); EmitIntent(m, Intent); Writef(m, ">>\n"); if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { Writef(m, "/Current exch /ColorRendering defineresource pop\n"); } if (lFreeDeviceLink) cmsFreeLUT(DeviceLink); cmsDeleteTransform(xform); cmsCloseProfile(hLab); return 1; }// Builds a ASCII string containing colorant list in 0..1.0 rangestaticvoid BuildColorantList(char *Colorant, int nColorant, WORD Out[]){ char Buff[32]; int j; Colorant[0] = 0; for (j=0; j < nColorant; j++) { sprintf(Buff, "%.3f", Out[j] / 65535.0); strcat(Colorant, Buff); if (j < nColorant -1) strcat(Colorant, " "); } }// Creates a PostScript color list from a named profile data. // This is a HP extension.staticint WriteNamedColorCRD(LPMEMSTREAM m, cmsHPROFILE hNamedColor, int Intent, DWORD dwFlags){ cmsHTRANSFORM xform; int i, nColors, nColorant; DWORD OutputFormat; char ColorName[32]; char Colorant[128]; nColorant = _cmsChannelsOf(cmsGetColorSpace(hNamedColor)); OutputFormat = CHANNELS_SH(nColorant) | BYTES_SH(2); xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, NULL, OutputFormat, Intent, cmsFLAGS_NOTPRECALC); 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"); nColors = cmsNamedColorCount(xform); for (i=0; i < nColors; i++) { WORD In[1]; WORD Out[MAXCHANNELS]; In[0] = (WORD) i; if (!cmsNamedColorInfo(xform, i, ColorName, NULL, NULL)) continue; cmsDoTransform(xform, In, Out, 1); BuildColorantList(Colorant, nColorant, Out); Writef(m, " (%s) [ %s ]\n", ColorName, Colorant); } Writef(m, " >>"); if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { Writef(m, " /Current exch /HPSpotTable defineresource pop\n"); } cmsDeleteTransform(xform); return 1;}// This one does create a Color Rendering Dictionary. // 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){ LPMEMSTREAM mem; DWORD dwBytesUsed; // Set up the serialization artifact mem = CreateMemStream((LPBYTE) Buffer, dwBufferLen, MAXPSCOLS); if (!mem) return 0; if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { EmitHeader(mem, "Color Rendering Dictionary (CRD)", hProfile); } // Is a named color profile? if (cmsGetDeviceClass(hProfile) == icSigNamedColorClass) { if (!WriteNamedColorCRD(mem, hProfile, Intent, dwFlags)) { free((void*) mem); return 0; } } else { // CRD are always implemented as LUT. if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) { free((void*) mem); return 0; } } if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { Writef(mem, "%%%%EndResource\n"); Writef(mem, "\n%% CRD End\n"); } // Done, keep memory usage dwBytesUsed = mem ->dwUsed; // Get rid of memory stream free((void*) mem); // Finally, return used byte count return dwBytesUsed;}// For compatibility with previous versionsDWORD LCMSEXPORT cmsGetPostScriptCRD(cmsHPROFILE hProfile, int Intent, LPVOID Buffer, DWORD dwBufferLen){ return cmsGetPostScriptCRDEx(hProfile, Intent, 0, Buffer, dwBufferLen);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -