static int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int 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); EmitIntent(m, Intent); _cmsIOPrintf(m, " >>\n"); _cmsIOPrintf(m, "]\n"); return 1; }
static int EmitCIEBasedABC(cmsIOHANDLER* m, cmsFloat64Number* Matrix, cmsToneCurve** CurveSet, cmsCIEXYZ* BlackPoint) { 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++ ) { _cmsIOPrintf(m, "%.6f %.6f %.6f ", Matrix[0 + 3*i], Matrix[1 + 3*i], Matrix[2 + 3*i]); } _cmsIOPrintf(m, "]\n"); _cmsIOPrintf(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n"); EmitWhiteBlackD50(m, BlackPoint); EmitIntent(m, INTENT_PERCEPTUAL); _cmsIOPrintf(m, ">>\n"); _cmsIOPrintf(m, "]\n"); return 1; }
static int EmitCIEBasedA(cmsIOHANDLER* m, cmsToneCurve* Curve, cmsCIEXYZ* BlackPoint) { _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); EmitIntent(m, INTENT_PERCEPTUAL); _cmsIOPrintf(m, ">>\n"); _cmsIOPrintf(m, "]\n"); return 1; }
static int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags) { cmsHPROFILE hLab; cmsHTRANSFORM xform; int i, nChannels; cmsUInt32Number OutputFormat; _cmsTRANSFORM* v; cmsPipeline* DeviceLink; cmsHPROFILE Profiles[3]; cmsCIEXYZ BlackPointAdaptedToD50; cmsBool lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION); cmsBool lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP); cmsUInt32Number InFrm = TYPE_Lab_16; int RelativeEncodingIntent; cmsColorSpaceSignature ColorSpace; hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); if (hLab == NULL) return 0; OutputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE); nChannels = T_CHANNELS(OutputFormat); ColorSpace = cmsGetColorSpace(hProfile); // For absolute colorimetric, the LUT is encoded as relative in order to preserve precision. RelativeEncodingIntent = Intent; if (RelativeEncodingIntent == INTENT_ABSOLUTE_COLORIMETRIC) RelativeEncodingIntent = INTENT_RELATIVE_COLORIMETRIC; // Use V4 Lab always Profiles[0] = hLab; Profiles[1] = hProfile; xform = cmsCreateMultiprofileTransformTHR(m ->ContextID, Profiles, 2, TYPE_Lab_DBL, OutputFormat, RelativeEncodingIntent, 0); cmsCloseProfile(hLab); if (xform == NULL) { cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Lab -> Profile in CRD creation"); return 0; } // Get a copy of the internal devicelink v = (_cmsTRANSFORM*) xform; DeviceLink = cmsPipelineDup(v ->Lut); if (DeviceLink == NULL) return 0; // We need a CLUT dwFlags |= cmsFLAGS_FORCE_CLUT; _cmsOptimizePipeline(&DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags); _cmsIOPrintf(m, "<<\n"); _cmsIOPrintf(m, "/ColorRenderingType 1\n"); cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0); // Emit headers, etc. EmitWhiteBlackD50(m, &BlackPointAdaptedToD50); EmitPQRStage(m, hProfile, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC); EmitXYZ2Lab(m); // 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. if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) lFixWhite = FALSE; _cmsIOPrintf(m, "/RenderTable "); WriteCLUT(m, cmsPipelineGetPtrToFirstStage(DeviceLink), "<", ">\n", "", "", lFixWhite, ColorSpace); _cmsIOPrintf(m, " %d {} bind ", nChannels); for (i=1; i < nChannels; i++) _cmsIOPrintf(m, "dup "); _cmsIOPrintf(m, "]\n"); EmitIntent(m, Intent); _cmsIOPrintf(m, ">>\n"); if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { _cmsIOPrintf(m, "/Current exch /ColorRendering defineresource pop\n"); } cmsPipelineFree(DeviceLink); cmsDeleteTransform(xform); return 1; }