/* Get the link from the CMS, but include proofing and/or a device link profile. */ gcmmhlink_t gscms_get_link_proof_devlink(gcmmhprofile_t lcms_srchandle, gcmmhprofile_t lcms_proofhandle, gcmmhprofile_t lcms_deshandle, gcmmhprofile_t lcms_devlinkhandle, gsicc_rendering_param_t *rendering_params, bool src_dev_link, int cmm_flags, gs_memory_t *mem) { DWORD src_data_type,des_data_type; icColorSpaceSignature src_color_space,des_color_space; int src_nChannels,des_nChannels; int lcms_src_color_space, lcms_des_color_space; cmsHPROFILE hProfiles[5]; int nProfiles = 0; /* First handle all the source stuff */ src_color_space = cmsGetColorSpace(lcms_srchandle); lcms_src_color_space = _cmsLCMScolorSpace(src_color_space); /* littlecms returns -1 for types it does not (but should) understand */ if (lcms_src_color_space < 0) lcms_src_color_space = 0; src_nChannels = _cmsChannelsOf(src_color_space); /* For now, just do single byte data, interleaved. We can change this when we use the transformation. */ src_data_type = (COLORSPACE_SH(lcms_src_color_space)| CHANNELS_SH(src_nChannels)|BYTES_SH(2)); if (lcms_deshandle != NULL) { des_color_space = cmsGetColorSpace(lcms_deshandle); } else { /* We must have a device link profile. */ des_color_space = cmsGetPCS(lcms_deshandle); } lcms_des_color_space = _cmsLCMScolorSpace(des_color_space); if (lcms_des_color_space < 0) lcms_des_color_space = 0; des_nChannels = _cmsChannelsOf(des_color_space); des_data_type = (COLORSPACE_SH(lcms_des_color_space)| CHANNELS_SH(des_nChannels)|BYTES_SH(2)); /* lcms proofing transform has a clunky API and can't include the device link profile if we have both. So use cmsCreateMultiprofileTransform instead and round trip the proofing profile. */ hProfiles[nProfiles++] = lcms_srchandle; if (lcms_proofhandle != NULL) { hProfiles[nProfiles++] = lcms_proofhandle; hProfiles[nProfiles++] = lcms_proofhandle; } hProfiles[nProfiles++] = lcms_deshandle; if (lcms_devlinkhandle != NULL) { hProfiles[nProfiles++] = lcms_devlinkhandle; } return(cmsCreateMultiprofileTransform(hProfiles, nProfiles, src_data_type, des_data_type, rendering_params->rendering_intent, (cmm_flags | cmsFLAGS_BLACKPOINTCOMPENSATION | cmsFLAGS_HIGHRESPRECALC | cmsFLAGS_NOTCACHE))); }
static int GetDevicelinkColorSpace(cmsHPROFILE hProfile) { cmsColorSpaceSignature ProfileSpace = cmsGetPCS(hProfile); return _cmsLCMScolorSpace(ProfileSpace); }
// Equivalence between ICC color spaces and lcms color spaces static int GetProfileColorSpace(cmsHPROFILE hProfile) { cmsColorSpaceSignature ProfileSpace = cmsGetColorSpace(hProfile); return _cmsLCMScolorSpace(ProfileSpace); }
/* Get the link from the CMS. TODO: Add error checking */ gcmmhlink_t gscms_get_link(gcmmhprofile_t lcms_srchandle, gcmmhprofile_t lcms_deshandle, gsicc_rendering_param_t *rendering_params) { DWORD src_data_type,des_data_type; icColorSpaceSignature src_color_space,des_color_space; int src_nChannels,des_nChannels; int lcms_src_color_space, lcms_des_color_space; /* Check for case of request for a transfrom from a device link profile in that case, the destination profile is NULL */ /* First handle all the source stuff */ src_color_space = cmsGetColorSpace(lcms_srchandle); lcms_src_color_space = _cmsLCMScolorSpace(src_color_space); /* littlecms returns -1 for types it does not (but should) understand */ if (lcms_src_color_space < 0) lcms_src_color_space = 0; src_nChannels = _cmsChannelsOf(src_color_space); /* For now, just do single byte data, interleaved. We can change this when we use the transformation. */ src_data_type = (COLORSPACE_SH(lcms_src_color_space)| CHANNELS_SH(src_nChannels)|BYTES_SH(2)); if (lcms_deshandle != NULL) { des_color_space = cmsGetColorSpace(lcms_deshandle); } else { /* We must have a device link profile. */ des_color_space = cmsGetPCS(lcms_deshandle); } lcms_des_color_space = _cmsLCMScolorSpace(des_color_space); if (lcms_des_color_space < 0) lcms_des_color_space = 0; des_nChannels = _cmsChannelsOf(des_color_space); des_data_type = (COLORSPACE_SH(lcms_des_color_space)| CHANNELS_SH(des_nChannels)|BYTES_SH(2)); /* Create the link */ return(cmsCreateTransform(lcms_srchandle, src_data_type, lcms_deshandle, des_data_type, rendering_params->rendering_intent, (cmsFLAGS_BLACKPOINTCOMPENSATION | cmsFLAGS_HIGHRESPRECALC))); /* cmsFLAGS_HIGHRESPRECALC) cmsFLAGS_NOTPRECALC cmsFLAGS_LOWRESPRECALC*/ }
// Check colorspace static cmsBool IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat) { int Space1 = T_COLORSPACE(dwFormat); int Space2 = _cmsLCMScolorSpace(Check); if (Space1 == PT_ANY) return TRUE; if (Space1 == Space2) return TRUE; if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE; if (Space1 == PT_Lab && Space2 == PT_LabV2) return TRUE; return FALSE; }
void IccColorProfile::calculateFloatUIMinMax(void) { QVector<KoChannelInfo::DoubleRange> &ret = d->shared->uiMinMaxes; cmsHPROFILE cprofile = d->shared->lcmsProfile->lcmsProfile(); Q_ASSERT(cprofile); cmsColorSpaceSignature color_space_sig = cmsGetColorSpace(cprofile); unsigned int num_channels = cmsChannelsOf(color_space_sig); unsigned int color_space_mask = _cmsLCMScolorSpace(color_space_sig); Q_ASSERT(num_channels>=1 && num_channels <=4); // num_channels==1 is for grayscale, we need to handle it Q_ASSERT(color_space_mask); // to try to find the max range of float/doubles for this profile, // pass in min/max int and make the profile convert that // this is far from perfect, we need a better way, if possible to get the "bounds" of a profile uint16_t in_min_pixel[4] = {0,0,0,0}; uint16_t in_max_pixel[4] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF}; double out_min_pixel[4] = {0,0,0,0}; double out_max_pixel[4] = {0,0,0,0}; cmsHTRANSFORM trans = cmsCreateTransform( cprofile, (COLORSPACE_SH(color_space_mask)|CHANNELS_SH(num_channels)|BYTES_SH(2)), cprofile, (COLORSPACE_SH(color_space_mask)|FLOAT_SH(1)|CHANNELS_SH(num_channels)|BYTES_SH(0)), //NOTE THAT 'BYTES' FIELD IS SET TO ZERO ON DLB because 8 bytes overflows the bitfield INTENT_PERCEPTUAL, 0); // does the intent matter in this case? if (trans) { cmsDoTransform(trans, in_min_pixel, out_min_pixel, 1); cmsDoTransform(trans, in_max_pixel, out_max_pixel, 1); cmsDeleteTransform(trans); }//else, we'll just default to [0..1] below ret.resize(num_channels); for (unsigned int i=0; i<num_channels; ++i) { if (out_min_pixel[i] < out_max_pixel[i]) { ret[i].minVal = out_min_pixel[i]; ret[i].maxVal = out_max_pixel[i]; } else { // aparently we can't even guarentee that converted_to_double(0x0000) < converted_to_double(0xFFFF) // assume [0..1] in such cases // we need to find a really solid way of determining the bounds of a profile, if possible ret[i].minVal = 0; ret[i].maxVal = 1; } } }
// This function creates a named color profile dumping all the contents of transform to a single profile // In this way, LittleCMS may be used to "group" several named color databases into a single profile. // It has, however, several minor limitations. PCS is always Lab, which is not very critic since this // is the normal PCS for named color profiles. static cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform) { _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform; cmsHPROFILE hICC = NULL; int i, nColors; cmsNAMEDCOLORLIST *nc2 = NULL, *Original = NULL; // Create an empty placeholder hICC = cmsCreateProfilePlaceholder(v->ContextID); if (hICC == NULL) return NULL; // Critical information cmsSetDeviceClass(hICC, cmsSigNamedColorClass); cmsSetColorSpace(hICC, v ->ExitColorSpace); cmsSetPCS(hICC, cmsSigLabData); // Tag profile with information if (!SetTextTags(hICC, L"Named color devicelink")) goto Error; Original = cmsGetNamedColorList(xform); if (Original == NULL) goto Error; nColors = cmsNamedColorCount(Original); nc2 = cmsDupNamedColorList(Original); if (nc2 == NULL) goto Error; // Colorant count now depends on the output space nc2 ->ColorantCount = cmsPipelineOutputChannels(v ->Lut); // Make sure we have proper formatters cmsChangeBuffersFormat(xform, TYPE_NAMED_COLOR_INDEX, FLOAT_SH(0) | COLORSPACE_SH(_cmsLCMScolorSpace(v ->ExitColorSpace)) | BYTES_SH(2) | CHANNELS_SH(cmsChannelsOf(v ->ExitColorSpace))); // Apply the transfor to colorants. for (i=0; i < nColors; i++) { cmsDoTransform(xform, &i, nc2 ->List[i].DeviceColorant, 1); } if (!cmsWriteTag(hICC, cmsSigNamedColor2Tag, (void*) nc2)) goto Error; cmsFreeNamedColorList(nc2); return hICC; Error: if (hICC != NULL) cmsCloseProfile(hICC); return NULL; }
static int TransformImage(TIFF* in, TIFF* out, const char *cDefInpProf, const char *cOutProf) { cmsHPROFILE hIn, hOut, hProof, hInkLimit = NULL; cmsHTRANSFORM xform; DWORD wInput, wOutput; int OutputColorSpace; int bps = (Width16 ? 2 : 1); DWORD dwFlags = 0; int nPlanes; // Observer adaptation state (only meaningful on absolute colorimetric intent) cmsSetAdaptationState(ObserverAdaptationState); if (EmbedProfile && cOutProf) DoEmbedProfile(out, cOutProf); if (BlackWhiteCompensation) dwFlags |= cmsFLAGS_WHITEBLACKCOMPENSATION; if (PreserveBlack) { dwFlags |= cmsFLAGS_PRESERVEBLACK; if (PrecalcMode == 0) PrecalcMode = 1; } switch (PrecalcMode) { case 0: dwFlags |= cmsFLAGS_NOTPRECALC; break; case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break; case 3: dwFlags |= cmsFLAGS_LOWRESPRECALC; break; case 1: break; default: FatalError("Unknown precalculation mode '%d'", PrecalcMode); } if (GamutCheck) dwFlags |= cmsFLAGS_GAMUTCHECK; hProof = NULL; hOut = NULL; if (lIsDeviceLink) { hIn = cmsOpenProfileFromFile(cDefInpProf, "r"); } else { hIn = GetTIFFProfile(in); if (hIn == NULL) hIn = OpenStockProfile(cDefInpProf); hOut = OpenStockProfile(cOutProf); if (cProofing != NULL) { hProof = OpenStockProfile(cProofing); dwFlags |= cmsFLAGS_SOFTPROOFING; } } // Take input color space wInput = GetInputPixelType(in); // Assure both, input profile and input TIFF are on same colorspace if (_cmsLCMScolorSpace(cmsGetColorSpace(hIn)) != (int) T_COLORSPACE(wInput)) FatalError("Input profile is not operating in proper color space"); if (!lIsDeviceLink) OutputColorSpace = _cmsLCMScolorSpace(cmsGetColorSpace(hOut)); else OutputColorSpace = _cmsLCMScolorSpace(cmsGetPCS(hIn)); wOutput = ComputeOutputFormatDescriptor(wInput, OutputColorSpace, bps); WriteOutputTags(out, OutputColorSpace, bps); CopyOtherTags(in, out); // Ink limit if (InkLimit != 400.0 && (OutputColorSpace == PT_CMYK || OutputColorSpace == PT_CMY)) { cmsHPROFILE hProfiles[10]; int nProfiles = 0; hInkLimit = cmsCreateInkLimitingDeviceLink(cmsGetColorSpace(hOut), InkLimit); hProfiles[nProfiles++] = hIn; if (hProof) { hProfiles[nProfiles++] = hProof; hProfiles[nProfiles++] = hProof; } hProfiles[nProfiles++] = hOut; hProfiles[nProfiles++] = hInkLimit; xform = cmsCreateMultiprofileTransform(hProfiles, nProfiles, wInput, wOutput, Intent, dwFlags); } else { xform = cmsCreateProofingTransform(hIn, wInput, hOut, wOutput, hProof, Intent, ProofingIntent, dwFlags); } // Planar stuff if (T_PLANAR(wInput)) nPlanes = T_CHANNELS(wInput) + T_EXTRA(wInput); else nPlanes = 1; // TIFF Lab of 8 bits need special handling if (wInput == TYPE_Lab_8 && !InputLabUsingICC && cInpProf != NULL && stricmp(cInpProf, "*Lab") == 0) { cmsSetUserFormatters(xform, TYPE_Lab_8, UnrollTIFFLab8, TYPE_Lab_8, NULL); } if (wOutput == TYPE_Lab_8 && cOutProf != NULL && stricmp(cOutProf, "*Lab") == 0) { cmsSetUserFormatters(xform, TYPE_Lab_8, NULL, TYPE_Lab_8, PackTIFFLab8); } // Handle tile by tile or strip by strip if (TIFFIsTiled(in)) { TileBasedXform(xform, in, out, nPlanes); } else { StripBasedXform(xform, in, out, nPlanes); } cmsDeleteTransform(xform); cmsCloseProfile(hIn); cmsCloseProfile(hOut); if (hInkLimit) cmsCloseProfile(hInkLimit); if (hProof) cmsCloseProfile(hProof); TIFFWriteDirectory(out); return 1; }
// Does convert a transform into a device link profile cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags) { cmsHPROFILE hProfile = NULL; cmsUInt32Number FrmIn, FrmOut, ChansIn, ChansOut; cmsUInt32Number ColorSpaceBitsIn, ColorSpaceBitsOut; _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; cmsPipeline* LUT = NULL; cmsStage* mpe; cmsContext ContextID = cmsGetTransformContextID(hTransform); const cmsAllowedLUT* AllowedLUT; cmsTagSignature DestinationTag; cmsProfileClassSignature deviceClass; _cmsAssert(hTransform != NULL); // Get the first mpe to check for named color mpe = cmsPipelineGetPtrToFirstStage(xform ->Lut); // Check if is a named color transform if (mpe != NULL) { if (cmsStageType(mpe) == cmsSigNamedColorElemType) { return CreateNamedColorDevicelink(hTransform); } } // First thing to do is to get a copy of the transformation LUT = cmsPipelineDup(xform ->Lut); if (LUT == NULL) return NULL; // Time to fix the Lab2/Lab4 issue. if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) { if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID))) goto Error; } // On the output side too if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) { if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID))) goto Error; } hProfile = cmsCreateProfilePlaceholder(ContextID); if (!hProfile) goto Error; // can't allocate cmsSetProfileVersion(hProfile, Version); FixColorSpaces(hProfile, xform -> EntryColorSpace, xform -> ExitColorSpace, dwFlags); // Optimize the LUT and precalculate a devicelink ChansIn = cmsChannelsOf(xform -> EntryColorSpace); ChansOut = cmsChannelsOf(xform -> ExitColorSpace); ColorSpaceBitsIn = _cmsLCMScolorSpace(xform -> EntryColorSpace); ColorSpaceBitsOut = _cmsLCMScolorSpace(xform -> ExitColorSpace); FrmIn = COLORSPACE_SH(ColorSpaceBitsIn) | CHANNELS_SH(ChansIn)|BYTES_SH(2); FrmOut = COLORSPACE_SH(ColorSpaceBitsOut) | CHANNELS_SH(ChansOut)|BYTES_SH(2); deviceClass = cmsGetDeviceClass(hProfile); if (deviceClass == cmsSigOutputClass) DestinationTag = cmsSigBToA0Tag; else DestinationTag = cmsSigAToB0Tag; // Check if the profile/version can store the result if (dwFlags & cmsFLAGS_FORCE_CLUT) AllowedLUT = NULL; else AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); if (AllowedLUT == NULL) { // Try to optimize _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); } // If no way, then force CLUT that for sure can be written if (AllowedLUT == NULL) { dwFlags |= cmsFLAGS_FORCE_CLUT; _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); // Put identity curves if needed if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType) if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn))) goto Error; if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType) if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut))) goto Error; AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); } // Somethings is wrong... if (AllowedLUT == NULL) { goto Error; } if (dwFlags & cmsFLAGS_8BITS_DEVICELINK) cmsPipelineSetSaveAs8bitsFlag(LUT, TRUE); // Tag profile with information if (!SetTextTags(hProfile, L"devicelink")) goto Error; // Store result if (!cmsWriteTag(hProfile, DestinationTag, LUT)) goto Error; if (xform -> InputColorant != NULL) { if (!cmsWriteTag(hProfile, cmsSigColorantTableTag, xform->InputColorant)) goto Error; } if (xform -> OutputColorant != NULL) { if (!cmsWriteTag(hProfile, cmsSigColorantTableOutTag, xform->OutputColorant)) goto Error; } if ((deviceClass == cmsSigLinkClass) && (xform ->Sequence != NULL)) { if (!_cmsWriteProfileSequence(hProfile, xform ->Sequence)) goto Error; } // Set the white point if (deviceClass == cmsSigInputClass) { if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->EntryWhitePoint)) goto Error; } else { if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->ExitWhitePoint)) goto Error; } // Per 7.2.15 in spec 4.3 cmsSetHeaderRenderingIntent(hProfile, xform ->RenderingIntent); cmsPipelineFree(LUT); return hProfile; Error: if (LUT != NULL) cmsPipelineFree(LUT); cmsCloseProfile(hProfile); return NULL; }
int dt_apply_printer_profile(int imgid, void **in, uint32_t width, uint32_t height, int bpp, cmsHPROFILE hOutProfile, int intent, gboolean black_point_compensation) { cmsHPROFILE hInProfile; cmsHTRANSFORM hTransform; cmsUInt32Number wInput, wOutput; int OutputColorSpace; if(!hOutProfile) return 1; const dt_colorspaces_color_profile_t *in_profile = dt_colorspaces_get_output_profile(imgid); if(!in_profile || !in_profile->profile) { fprintf(stderr, "error getting output profile for image %d\n", imgid); return 1; } hInProfile = in_profile->profile; wInput = ComputeFormatDescriptor (PT_RGB, (bpp==8?1:2)); OutputColorSpace = _cmsLCMScolorSpace(cmsGetColorSpace(hOutProfile)); wOutput = ComputeOutputFormatDescriptor(wInput, OutputColorSpace, 1); hTransform = cmsCreateTransform (hInProfile, wInput, hOutProfile, wOutput, intent, black_point_compensation ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0); void *out = (void *)malloc(width*height*3); if (bpp == 8) { const uint8_t *ptr_in = (uint8_t *)*in; uint8_t *ptr_out = (uint8_t *)out; #ifdef _OPENMP #pragma omp parallel for schedule(static) default(none) shared(ptr_in, ptr_out, hTransform, height, width) #endif for (int k=0; k<height; k++) cmsDoTransform(hTransform, (const void *)&ptr_in[k*width*3], (void *)&ptr_out[k*width*3], width); } else { const uint16_t *ptr_in = (uint16_t *)*in; uint8_t *ptr_out = (uint8_t *)out; #ifdef _OPENMP #pragma omp parallel for schedule(static) default(none) shared(ptr_in, ptr_out, hTransform, height, width) #endif for (int k=0; k<height; k++) cmsDoTransform(hTransform, (const void *)&ptr_in[k*width*3], (void *)&ptr_out[k*width*3], width); } cmsDeleteTransform(hTransform); free(*in); *in = out; return 0; }
void Color::LoadICCProfiles() { if(m_iccSearchPaths!= NULL){ delete m_iccSearchPaths; } const Int32 NUMSEARCHPATHS = 4; m_iccSearchPaths = new String[NUMSEARCHPATHS]; Filename cmykDir = GeGetPluginPath(); cmykDir += Filename(String("cmyk")); m_iccSearchPaths[0] = cmykDir.GetString(); m_iccSearchPaths[1] = "/Library/ColorSync/Profiles/"; m_iccSearchPaths[2] = "/Users/vidarn/Library/ColorSync"; m_iccSearchPaths[3] = "C:\\Windows\\System32\\Spool\\Drivers\\Color\\"; Logger::AddLine("Creating LAB profile",1); m_LABProfile = cmsCreateLab4Profile(NULL); Logger::AddLine("Creating default sRGB profile",1); m_displayProfile = cmsCreate_sRGBProfile(); m_RGBProfiles.Insert(vnColorProfile("sRGB",m_displayProfile),0); for(Int32 i=0;i<NUMSEARCHPATHS;++i){ BrowseFiles* bf = BrowseFiles::Alloc(); Filename dir(m_iccSearchPaths[i]); bf->Init(dir,FALSE); int RGBPos = m_RGBProfiles.GetCount(); int CMYKPos = m_CMYKProfiles.GetCount(); int spotPos = m_spotProfiles.GetCount(); if (bf) { while (bf->GetNext()) { Filename fileName = bf->GetFilename(); fileName.SetDirectory(dir); String str = fileName.GetString(); Char *buffer = new Char[str.GetCStringLen()+1]; str.GetCString(buffer,str.GetCStringLen()+1); Logger::AddLine(buffer,1); cmsHPROFILE profile = cmsOpenProfileFromFile(buffer, "r"); if(profile != NULL){ cmsColorSpaceSignature sig = cmsGetColorSpace(profile); Int32 length = cmsGetProfileInfoASCII(profile,cmsInfoDescription,"en","US",NULL,0); Char *buffer2 = new Char[length]; cmsGetProfileInfoASCII(profile,cmsInfoDescription,"en","US",buffer2,length); String info(buffer2); int pt = _cmsLCMScolorSpace(sig); if(PT_RGB == pt){ Logger::AddLine("RGB profile",1); m_RGBProfiles.Insert(vnColorProfile(info,profile),RGBPos); RGBPos++; } if(PT_CMYK == pt){ cmsHTRANSFORM xform = cmsCreateTransform(profile,TYPE_NAMED_COLOR_INDEX,m_displayProfile,TYPE_RGB_DBL,INTENT_PERCEPTUAL,0); if(xform != NULL){ cmsNAMEDCOLORLIST* colorList = cmsGetNamedColorList(xform); if(colorList != NULL){ m_spotProfiles.Insert(vnColorProfile(info,profile),spotPos); spotPos++; } else{ Logger::AddLine("CMYK profile",1); m_CMYKProfiles.Insert(vnColorProfile(info,profile),CMYKPos); CMYKPos++; } cmsDeleteTransform(xform); } } delete buffer2; } else { Logger::AddLine("Invalid",1); } delete buffer; } } BrowseFiles::Free(bf); } }
/* Get the link from the CMS, but include proofing and/or a device link profile. Note also, that the source may be a device link profile, in which case we will not have a destination profile but could still have a proof profile or an additional device link profile */ gcmmhlink_t gscms_get_link_proof_devlink(gcmmhprofile_t lcms_srchandle, gcmmhprofile_t lcms_proofhandle, gcmmhprofile_t lcms_deshandle, gcmmhprofile_t lcms_devlinkhandle, gsicc_rendering_param_t *rendering_params, bool src_dev_link, int cmm_flags, gs_memory_t *memory) { cmsUInt32Number src_data_type,des_data_type; cmsColorSpaceSignature src_color_space,des_color_space; int src_nChannels,des_nChannels; int lcms_src_color_space, lcms_des_color_space; cmsHPROFILE hProfiles[5]; int nProfiles = 0; unsigned int flag; /* Check if the rendering intent is something other than relative colorimetric and if we have a proofing profile. In this case we need to create the combined profile a bit different. LCMS does not allow us to use different intents in the cmsCreateMultiprofileTransform transform. Also, don't even think about doing this if someone has snuck in a source based device link profile into the mix */ if (lcms_proofhandle != NULL && rendering_params->rendering_intent != gsRELATIVECOLORIMETRIC && !src_dev_link) { /* First handle the source to proof profile with its particular intent as a device link profile */ cmsHPROFILE src_to_proof; cmsHTRANSFORM temptransform; temptransform = gscms_get_link(lcms_srchandle, lcms_proofhandle, rendering_params, cmm_flags, memory); /* Now mash that to a device link profile */ flag = cmsFLAGS_HIGHRESPRECALC; if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON || rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) { flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION); } src_to_proof = cmsTransform2DeviceLink(temptransform, 3.4, flag); /* Free up the link handle */ cmsDeleteTransform(temptransform); src_color_space = cmsGetColorSpace(src_to_proof); lcms_src_color_space = _cmsLCMScolorSpace(src_color_space); /* littlecms returns -1 for types it does not (but should) understand */ if (lcms_src_color_space < 0) lcms_src_color_space = 0; src_nChannels = cmsChannelsOf(src_color_space); /* For now, just do single byte data, interleaved. We can change this when we use the transformation. */ src_data_type = (COLORSPACE_SH(lcms_src_color_space)| CHANNELS_SH(src_nChannels)|BYTES_SH(2)); if (lcms_devlinkhandle == NULL) { des_color_space = cmsGetColorSpace(lcms_deshandle); } else { des_color_space = cmsGetPCS(lcms_devlinkhandle); } lcms_des_color_space = _cmsLCMScolorSpace(des_color_space); if (lcms_des_color_space < 0) lcms_des_color_space = 0; des_nChannels = cmsChannelsOf(des_color_space); des_data_type = (COLORSPACE_SH(lcms_des_color_space)| CHANNELS_SH(des_nChannels)|BYTES_SH(2)); /* Now, we need to go back through the proofing profile, to the destination and then to the device link profile if there was one. */ hProfiles[nProfiles++] = src_to_proof; /* Src to proof with special intent */ hProfiles[nProfiles++] = lcms_proofhandle; /* Proof to CIELAB */ if (lcms_deshandle != NULL) { hProfiles[nProfiles++] = lcms_deshandle; /* Our destination */ } /* The output device link profile */ if (lcms_devlinkhandle != NULL) { hProfiles[nProfiles++] = lcms_devlinkhandle; } flag = cmsFLAGS_HIGHRESPRECALC; if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON || rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) { flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION); } /* Use relative colorimetric here */ temptransform = cmsCreateMultiprofileTransformTHR((cmsContext)memory, hProfiles, nProfiles, src_data_type, des_data_type, gsRELATIVECOLORIMETRIC, flag); cmsCloseProfile(src_to_proof); return temptransform; } else { /* First handle all the source stuff */ src_color_space = cmsGetColorSpace(lcms_srchandle); lcms_src_color_space = _cmsLCMScolorSpace(src_color_space); /* littlecms returns -1 for types it does not (but should) understand */ if (lcms_src_color_space < 0) lcms_src_color_space = 0; src_nChannels = cmsChannelsOf(src_color_space); /* For now, just do single byte data, interleaved. We can change this when we use the transformation. */ src_data_type = (COLORSPACE_SH(lcms_src_color_space)| CHANNELS_SH(src_nChannels)|BYTES_SH(2)); if (lcms_devlinkhandle == NULL) { if (src_dev_link) { des_color_space = cmsGetPCS(lcms_srchandle); } else { des_color_space = cmsGetColorSpace(lcms_deshandle); } } else { des_color_space = cmsGetPCS(lcms_devlinkhandle); } lcms_des_color_space = _cmsLCMScolorSpace(des_color_space); if (lcms_des_color_space < 0) lcms_des_color_space = 0; des_nChannels = cmsChannelsOf(des_color_space); des_data_type = (COLORSPACE_SH(lcms_des_color_space)| CHANNELS_SH(des_nChannels)|BYTES_SH(2)); /* lcms proofing transform has a clunky API and can't include the device link profile if we have both. So use cmsCreateMultiprofileTransform instead and round trip the proofing profile. */ hProfiles[nProfiles++] = lcms_srchandle; /* Note if source is device link, we cannot do any proofing */ if (lcms_proofhandle != NULL && !src_dev_link) { hProfiles[nProfiles++] = lcms_proofhandle; hProfiles[nProfiles++] = lcms_proofhandle; } /* This should be NULL if we have a source device link */ if (lcms_deshandle != NULL) { hProfiles[nProfiles++] = lcms_deshandle; } /* Someone could have a device link at the output, giving us possibly two device link profiles to smash together */ if (lcms_devlinkhandle != NULL) { hProfiles[nProfiles++] = lcms_devlinkhandle; } flag = cmsFLAGS_HIGHRESPRECALC; if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON || rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) { flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION); } return cmsCreateMultiprofileTransformTHR((cmsContext)memory, hProfiles, nProfiles, src_data_type, des_data_type, rendering_params->rendering_intent, flag); } }
/* Get the link from the CMS. TODO: Add error checking */ gcmmhlink_t gscms_get_link(gcmmhprofile_t lcms_srchandle, gcmmhprofile_t lcms_deshandle, gsicc_rendering_param_t *rendering_params, int cmm_flags, gs_memory_t *memory) { cmsUInt32Number src_data_type,des_data_type; cmsColorSpaceSignature src_color_space,des_color_space; int src_nChannels,des_nChannels; int lcms_src_color_space, lcms_des_color_space; unsigned int flag; /* Check for case of request for a transfrom from a device link profile in that case, the destination profile is NULL */ /* First handle all the source stuff */ src_color_space = cmsGetColorSpace(lcms_srchandle); lcms_src_color_space = _cmsLCMScolorSpace(src_color_space); /* littlecms returns -1 for types it does not (but should) understand */ if (lcms_src_color_space < 0) lcms_src_color_space = 0; src_nChannels = cmsChannelsOf(src_color_space); /* For now, just do single byte data, interleaved. We can change this when we use the transformation. */ src_data_type = (COLORSPACE_SH(lcms_src_color_space)| CHANNELS_SH(src_nChannels)|BYTES_SH(2)); #if 0 src_data_type = src_data_type | ENDIAN16_SH(1); #endif if (lcms_deshandle != NULL) { des_color_space = cmsGetColorSpace(lcms_deshandle); } else { /* We must have a device link profile. */ des_color_space = cmsGetPCS(lcms_deshandle); } lcms_des_color_space = _cmsLCMScolorSpace(des_color_space); if (lcms_des_color_space < 0) lcms_des_color_space = 0; des_nChannels = cmsChannelsOf(des_color_space); des_data_type = (COLORSPACE_SH(lcms_des_color_space)| CHANNELS_SH(des_nChannels)|BYTES_SH(2)); /* endian */ #if 0 des_data_type = des_data_type | ENDIAN16_SH(1); #endif /* Set up the flags */ flag = cmsFLAGS_HIGHRESPRECALC; if (rendering_params->black_point_comp == gsBLACKPTCOMP_ON || rendering_params->black_point_comp == gsBLACKPTCOMP_ON_OR) { flag = (flag | cmsFLAGS_BLACKPOINTCOMPENSATION); } if (rendering_params->preserve_black == gsBLACKPRESERVE_KONLY) { switch (rendering_params->rendering_intent) { case INTENT_PERCEPTUAL: rendering_params->rendering_intent = INTENT_PRESERVE_K_ONLY_PERCEPTUAL; break; case INTENT_RELATIVE_COLORIMETRIC: rendering_params->rendering_intent = INTENT_PRESERVE_K_ONLY_RELATIVE_COLORIMETRIC; break; case INTENT_SATURATION: rendering_params->rendering_intent = INTENT_PRESERVE_K_ONLY_SATURATION; break; default: break; } } if (rendering_params->preserve_black == gsBLACKPRESERVE_KPLANE) { switch (rendering_params->rendering_intent) { case INTENT_PERCEPTUAL: rendering_params->rendering_intent = INTENT_PRESERVE_K_PLANE_PERCEPTUAL; break; case INTENT_RELATIVE_COLORIMETRIC: rendering_params->rendering_intent = INTENT_PRESERVE_K_PLANE_RELATIVE_COLORIMETRIC; break; case INTENT_SATURATION: rendering_params->rendering_intent = INTENT_PRESERVE_K_PLANE_SATURATION; break; default: break; } } /* Create the link */ return cmsCreateTransformTHR((cmsContext)memory, lcms_srchandle, src_data_type, lcms_deshandle, des_data_type, rendering_params->rendering_intent, flag | cmm_flags); /* cmsFLAGS_HIGHRESPRECALC) cmsFLAGS_NOTPRECALC cmsFLAGS_LOWRESPRECALC*/ }