📄 cmswtpnt.c
字号:
double uj,vj,tj,di,dj,mi,mj; double Tc = -1, xs, ys; di = mi = 0; xs = v -> x; ys = v -> y; // convert (x,y) to CIE 1960 (u,v) us = (2*xs) / (-xs + 6*ys + 1.5); vs = (3*ys) / (-xs + 6*ys + 1.5); for (j=0; j < NISO; j++) { uj = isotempdata[j].ut; vj = isotempdata[j].vt; tj = isotempdata[j].tt; mj = isotempdata[j].mirek; dj = ((vs - vj) - tj * (us - uj)) / sqrt(1 + tj*tj); if ((j!=0) && (di/dj < 0.0)) { Tc = 1000000.0 / (mi + (di / (di - dj)) * (mj - mi)); break; } di = dj; mi = mj; } if (j == NISO) return -1; return Tc;}staticBOOL InRange(LPcmsCIExyY a, LPcmsCIExyY b, double tolerance){ double dist_x, dist_y; dist_x = fabs(a->x - b->x); dist_y = fabs(a->y - b->y); return (tolerance >= dist_x * dist_x + dist_y * dist_y);}typedef struct { char Name[30]; cmsCIExyY Val; } WHITEPOINTS,FAR *LPWHITEPOINTS;staticint FromD40toD150(LPWHITEPOINTS pts){ int i, n; n = 0; for (i=40; i < 150; i ++) { sprintf(pts[n].Name, "D%d", i); cmsWhitePointFromTemp((int) (i*100.0), &pts[n].Val); n++; } return n;}void _cmsIdentifyWhitePoint(char *Buffer, LPcmsCIEXYZ WhitePt){ int i, n; cmsCIExyY Val; double T; WHITEPOINTS SomeIlluminants[140] = { {"CIE illuminant A", {0.4476, 0.4074, 1.0}}, {"CIE illuminant C", {0.3101, 0.3162, 1.0}}, {"D65 (daylight)", {0.3127, 0.3291, 1.0}}, }; n = FromD40toD150(&SomeIlluminants[3]) + 3; cmsXYZ2xyY(&Val, WhitePt); Val.Y = 1.; for (i=0; i < n; i++) { if (InRange(&Val, &SomeIlluminants[i].Val, 0.000005)) { strcpy(Buffer, "WhitePoint : "); strcat(Buffer, SomeIlluminants[i].Name); return; } } T = Robertson(&Val); if (T > 0) sprintf(Buffer, "White point near %dK", (int) T); else { sprintf(Buffer, "Unknown white point (X:%1.2g, Y:%1.2g, Z:%1.2g)", WhitePt -> X, WhitePt -> Y, WhitePt -> Z); } }// Use darker colorant to obtain black pointstaticint BlackPointAsDarkerColorant(cmsHPROFILE hInput, int Intent, LPcmsCIEXYZ BlackPoint, DWORD dwFlags){ WORD *Black, *White; cmsHTRANSFORM xform; icColorSpaceSignature Space; int nChannels; DWORD dwFormat; cmsHPROFILE hLab; cmsCIELab Lab; cmsCIEXYZ BlackXYZ, MediaWhite; // If the profile does not support input direction, assume Black point 0 if (!cmsIsIntentSupported(hInput, Intent, LCMS_USED_AS_INPUT)) { BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; return 0; } // Try to get black by using black colorant Space = cmsGetColorSpace(hInput); if (!_cmsEndPointsBySpace(Space, &White, &Black, &nChannels)) { BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; return 0; } dwFormat = CHANNELS_SH(nChannels)|BYTES_SH(2); hLab = cmsCreateLabProfile(NULL); xform = cmsCreateTransform(hInput, dwFormat, hLab, TYPE_Lab_DBL, Intent, cmsFLAGS_NOTPRECALC); cmsDoTransform(xform, Black, &Lab, 1); // Force it to be neutral, clip to max. L* of 50 Lab.a = Lab.b = 0; if (Lab.L > 50) Lab.L = 50; cmsCloseProfile(hLab); cmsDeleteTransform(xform); cmsLab2XYZ(NULL, &BlackXYZ, &Lab); if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) { *BlackPoint = BlackXYZ; } else { if (!(dwFlags & LCMS_BPFLAGS_D50_ADAPTED)) { cmsTakeMediaWhitePoint(&MediaWhite, hInput); cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &BlackXYZ); } else *BlackPoint = BlackXYZ; } return 1;}// Get a black point of output CMYK profile, discounting any ink-limiting embedded // in the profile. Fou doing that, use perceptual intent in input direction:// Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Labstaticint BlackPointUsingPerceptualBlack(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, DWORD dwFlags){ cmsHTRANSFORM hPercLab2CMYK, hRelColCMYK2Lab; cmsHPROFILE hLab; cmsCIELab LabIn, LabOut; WORD CMYK[MAXCHANNELS]; cmsCIEXYZ BlackXYZ, MediaWhite; if (!cmsIsIntentSupported(hProfile, INTENT_PERCEPTUAL, LCMS_USED_AS_INPUT)) { BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; return 0; } hLab = cmsCreateLabProfile(NULL); hPercLab2CMYK = cmsCreateTransform(hLab, TYPE_Lab_DBL, hProfile, TYPE_CMYK_16, INTENT_PERCEPTUAL, cmsFLAGS_NOTPRECALC); hRelColCMYK2Lab = cmsCreateTransform(hProfile, TYPE_CMYK_16, hLab, TYPE_Lab_DBL, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOTPRECALC); LabIn.L = LabIn.a = LabIn.b = 0; cmsDoTransform(hPercLab2CMYK, &LabIn, CMYK, 1); cmsDoTransform(hRelColCMYK2Lab, CMYK, &LabOut, 1); if (LabOut.L > 50) LabOut.L = 50; LabOut.a = LabOut.b = 0; cmsDeleteTransform(hPercLab2CMYK); cmsDeleteTransform(hRelColCMYK2Lab); cmsCloseProfile(hLab); cmsLab2XYZ(NULL, &BlackXYZ, &LabOut); if (!(dwFlags & LCMS_BPFLAGS_D50_ADAPTED)){ cmsTakeMediaWhitePoint(&MediaWhite, hProfile); cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &BlackXYZ); } else *BlackPoint = BlackXYZ; return 1;}// Get Perceptual black of v4 profiles.staticint GetV4PerceptualBlack(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, DWORD dwFlags){ if (dwFlags & LCMS_BPFLAGS_D50_ADAPTED) { BlackPoint->X = PERCEPTUAL_BLACK_X; BlackPoint->Y = PERCEPTUAL_BLACK_Y; BlackPoint->Z = PERCEPTUAL_BLACK_Z; } else { cmsCIEXYZ D50BlackPoint, MediaWhite; cmsTakeMediaWhitePoint(&MediaWhite, hProfile); D50BlackPoint.X = PERCEPTUAL_BLACK_X; D50BlackPoint.Y = PERCEPTUAL_BLACK_Y; D50BlackPoint.Z = PERCEPTUAL_BLACK_Z; cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &D50BlackPoint); } return 1;}// This function shouldn't exist at all -- there is such quantity of broken// profiles on black point tag, that we must somehow fix chromaticity to // avoid huge tint when doing Black point compensation. This function does// just that. If BP is specified, then forces it to neutral and uses only L// component. If does not exist, computes it by taking 400% of ink or RGB=0 This// works well on relative intent and is undefined on perceptual & saturation.// However, I will support all intents for tricking & trapping.int cmsDetectBlackPoint(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, int Intent, DWORD dwFlags){ // v4 + perceptual & saturation intents does have its own black point if ((cmsGetProfileICCversion(hProfile) >= 0x4000000) && (Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) { // Matrix shaper share MRC & perceptual intents if (_cmsIsMatrixShaper(hProfile)) return BlackPointAsDarkerColorant(hProfile, INTENT_RELATIVE_COLORIMETRIC, BlackPoint, cmsFLAGS_NOTPRECALC); // Get fixed value return GetV4PerceptualBlack(BlackPoint, hProfile, dwFlags); }#ifdef HONOR_BLACK_POINT_TAG // v2, v4 rel/abs colorimetric if (cmsIsTag(hProfile, icSigMediaBlackPointTag) && Intent == INTENT_RELATIVE_COLORIMETRIC) { cmsCIEXYZ BlackXYZ, UntrustedBlackPoint, TrustedBlackPoint, MediaWhite; cmsCIELab Lab; // If black point is specified, then use it, cmsTakeMediaBlackPoint(&BlackXYZ, hProfile); cmsTakeMediaWhitePoint(&MediaWhite, hProfile); // Black point is absolute XYZ, so adapt to D50 to get PCS value cmsAdaptToIlluminant(&UntrustedBlackPoint, &MediaWhite, cmsD50_XYZ(), &BlackXYZ); // Force a=b=0 to get rid of any chroma cmsXYZ2Lab(NULL, &Lab, &UntrustedBlackPoint); Lab.a = Lab.b = 0; if (Lab.L > 50) Lab.L = 50; // Clip to L* <= 50 cmsLab2XYZ(NULL, &TrustedBlackPoint, &Lab); // Return BP as D50 relative or absolute XYZ (depends on flags) if (!(dwFlags & LCMS_BPFLAGS_D50_ADAPTED)) cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &TrustedBlackPoint); else *BlackPoint = TrustedBlackPoint; return 1; }#endif // If output profile, discount ink-limiting if (Intent == INTENT_RELATIVE_COLORIMETRIC && (cmsGetDeviceClass(hProfile) == icSigOutputClass) && (cmsGetColorSpace(hProfile) == icSigCmykData)) return BlackPointUsingPerceptualBlack(BlackPoint, hProfile, dwFlags); // Nope, compute BP using current intent. return BlackPointAsDarkerColorant(hProfile, Intent, BlackPoint, dwFlags);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -