/* * Class: sun_java2d_cmm_lcms_LCMS * Method: createNativeTransform * Signature: ([JI)J */ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform (JNIEnv *env, jclass cls, jlongArray profileIDs, jint renderType, jobject disposerRef) { LPLCMSICCPROFILE _iccArray[DF_ICC_BUF_SIZE]; LPLCMSICCPROFILE *iccArray = &_iccArray[0]; cmsHTRANSFORM transform; storeID_t sTrans; int i, j, size; jlong* ids; size = (*env)->GetArrayLength (env, profileIDs); ids = (*env)->GetPrimitiveArrayCritical(env, profileIDs, 0); if (DF_ICC_BUF_SIZE < size*2) { iccArray = (LPLCMSICCPROFILE*) malloc( size*2*sizeof(LPLCMSICCPROFILE)); if (iccArray == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "getXForm: iccArray == NULL"); return NULL; } } j = 0; for (i = 0; i < size; i++) { LPLCMSICCPROFILE icc; sTrans.j = ids[i]; icc = sTrans.pf; iccArray[j++] = icc; /* Middle non-abstract profiles should be doubled before passing to * the cmsCreateMultiprofileTransform function */ if (size > 2 && i != 0 && i != size - 1 && icc->ColorSpace != icSigXYZData && icc->ColorSpace != icSigLabData) { iccArray[j++] = icc; } } sTrans.xf = cmsCreateMultiprofileTransform(iccArray, j, 0, 0, renderType, 0); (*env)->ReleasePrimitiveArrayCritical(env, profileIDs, ids, 0); if (sTrans.xf == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_createNativeTransform: " "sTrans.xf == NULL"); JNU_ThrowByName(env, "java/awt/color/CMMException", "Cannot get color transform"); } else { Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sTrans.j); } if (iccArray != &_iccArray[0]) { free(iccArray); } return sTrans.j; }
/* 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))); }
/****************************************************************************** * CreateMultiProfileTransform [MSCMS.@] * * Create a color transform from an array of color profiles. * * PARAMS * profiles [I] Array of color profiles. * nprofiles [I] Number of color profiles. * intents [I] Array of rendering intents. * flags [I] Flags. * cmm [I] Profile to take the CMM from. * * RETURNS * Success: Handle to a transform. * Failure: NULL */ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofiles, PDWORD intents, DWORD nintents, DWORD flags, DWORD cmm ) { HTRANSFORM ret = NULL; #ifdef HAVE_LCMS2 cmsHPROFILE *cmsprofiles; struct transform transform; struct profile *profile0, *profile1; TRACE( "( %p, 0x%08x, %p, 0x%08x, 0x%08x, 0x%08x )\n", profiles, nprofiles, intents, nintents, flags, cmm ); if (!profiles || !nprofiles || !intents) return NULL; if (nprofiles > 2) { FIXME("more than 2 profiles not supported\n"); return NULL; } profile0 = grab_profile( profiles[0] ); if (!profile0) return NULL; profile1 = grab_profile( profiles[1] ); if (!profile1) { release_profile( profile0 ); return NULL; } if ((cmsprofiles = HeapAlloc( GetProcessHeap(), 0, (nprofiles + 1) * sizeof(cmsHPROFILE) ))) { cmsprofiles[0] = profile0->cmsprofile; cmsprofiles[1] = profile1->cmsprofile; transform.cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, 0, 0, *intents, 0 ); HeapFree( GetProcessHeap(), 0, cmsprofiles ); if (!transform.cmstransform) { release_profile( profile0 ); release_profile( profile1 ); return FALSE; } ret = create_transform( &transform ); } release_profile( profile0 ); release_profile( profile1 ); #endif /* HAVE_LCMS2 */ return ret; }
static int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags) { cmsHPROFILE hLab; cmsHTRANSFORM xform; cmsUInt32Number nChannels; cmsUInt32Number InputFormat; int rc; cmsHPROFILE Profiles[2]; cmsCIEXYZ BlackPointAdaptedToD50; // Does create a device-link based transform. // The DeviceLink is next dumped as working CSA. InputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE); nChannels = T_CHANNELS(InputFormat); cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0); // Adjust output to Lab4 hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); Profiles[0] = hProfile; Profiles[1] = hLab; xform = cmsCreateMultiprofileTransform(Profiles, 2, InputFormat, TYPE_Lab_DBL, Intent, 0); cmsCloseProfile(hLab); if (xform == NULL) { cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Profile -> Lab"); return 0; } // Only 1, 3 and 4 channels are allowed switch (nChannels) { case 1: { cmsToneCurve* Gray2Y = ExtractGray2Y(m ->ContextID, hProfile, Intent); EmitCIEBasedA(m, Gray2Y, &BlackPointAdaptedToD50); cmsFreeToneCurve(Gray2Y); } break; case 3: case 4: { cmsUInt32Number OutFrm = TYPE_Lab_16; cmsPipeline* DeviceLink; _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform; DeviceLink = cmsPipelineDup(v ->Lut); if (DeviceLink == NULL) return 0; dwFlags |= cmsFLAGS_FORCE_CLUT; _cmsOptimizePipeline(&DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags); rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50); cmsPipelineFree(DeviceLink); } break; default: cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels supported for CSA. This profile has %d channels.", nChannels); return 0; } cmsDeleteTransform(xform); return 1; }
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; }
/****************************************************************************** * CreateMultiProfileTransform [MSCMS.@] * * Create a color transform from an array of color profiles. * * PARAMS * profiles [I] Array of color profiles. * nprofiles [I] Number of color profiles. * intents [I] Array of rendering intents. * flags [I] Flags. * cmm [I] Profile to take the CMM from. * * RETURNS * Success: Handle to a transform. * Failure: NULL */ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofiles, PDWORD intents, DWORD nintents, DWORD flags, DWORD cmm ) { HTRANSFORM ret = NULL; #ifdef HAVE_LCMS cmsHPROFILE *cmsprofiles, cmsconvert = NULL; struct transform transform; struct profile *profile0, *profile1; DWORD in_format, out_format; TRACE( "( %p, 0x%08x, %p, 0x%08x, 0x%08x, 0x%08x )\n", profiles, nprofiles, intents, nintents, flags, cmm ); if (!profiles || !nprofiles || !intents) return NULL; if (nprofiles > 2) { FIXME("more than 2 profiles not supported\n"); return NULL; } profile0 = grab_profile( profiles[0] ); if (!profile0) return NULL; profile1 = grab_profile( profiles[1] ); if (!profile1) { release_profile( profile0 ); return NULL; } in_format = from_profile( profiles[0] ); out_format = from_profile( profiles[nprofiles - 1] ); if (in_format != out_format) { /* insert a conversion profile for pairings that lcms doesn't handle */ if (out_format == TYPE_RGB_16) cmsconvert = cmsCreate_sRGBProfile(); if (out_format == TYPE_Lab_16) cmsconvert = cmsCreateLabProfile( NULL ); } cmsprofiles = HeapAlloc( GetProcessHeap(), 0, (nprofiles + 1) * sizeof(cmsHPROFILE) ); if (cmsprofiles) { cmsprofiles[0] = profile0->cmsprofile; if (cmsconvert) { cmsprofiles[1] = cmsconvert; cmsprofiles[2] = profile1->cmsprofile; nprofiles++; } else { cmsprofiles[1] = profile1->cmsprofile; } transform.cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, in_format, out_format, *intents, 0 ); HeapFree( GetProcessHeap(), 0, cmsprofiles ); ret = create_transform( &transform ); } release_profile( profile0 ); release_profile( profile1 ); #endif /* HAVE_LCMS */ return ret; }
int main(int argc, char *argv[]) { int i, nargs; cmsHPROFILE Profiles[257]; cmsHPROFILE hProfile; DWORD dwFlags = 0; cmsHTRANSFORM hTransform; fprintf(stderr, "little cms device link generator - v1.7\n"); HandleSwitches(argc, argv); cmsSetErrorHandler(MyErrorHandler); nargs = (argc - xoptind); if (nargs < 1) Help(0); if (nargs > 255) FatalError("ERROR: Holy profile! what are you trying to do with so many profiles?"); for (i=0; i < nargs; i++) { Profiles[i] = OpenProfile(argv[i + xoptind]); } switch (PrecalcMode) { case 0: dwFlags |= cmsFLAGS_LOWRESPRECALC; break; case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break; case 1: if (NumOfGridPoints > 0) dwFlags |= cmsFLAGS_GRIDPOINTS(NumOfGridPoints); break; default: FatalError("ERROR: Unknown precalculation mode '%d'", PrecalcMode); } if (BlackPointCompensation) dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION; if (BlackPreservation > 0) { dwFlags |= cmsFLAGS_PRESERVEBLACK; cmsSetCMYKPreservationStrategy(BlackPreservation-1); } if (TagResult) dwFlags |= cmsFLAGS_GUESSDEVICECLASS; if (NoPrelinearization) dwFlags |= cmsFLAGS_NOPRELINEARIZATION; if (InkLimit != 400.0) { cmsHPROFILE hInkLimit = cmsCreateInkLimitingDeviceLink( cmsGetColorSpace(Profiles[nargs-1]), InkLimit); Profiles[nargs++] = hInkLimit; } if (lUse8bits) dwFlags |= cmsFLAGS_NOPRELINEARIZATION; hTransform = cmsCreateMultiprofileTransform(Profiles, nargs, 0, 0, Intent, dwFlags); if (hTransform) { size_t size = sizeof(int) + nargs * sizeof(cmsPSEQDESC); LPcmsSEQ pseq = (LPcmsSEQ) _cmsMalloc(size); ZeroMemory(pseq, size); pseq ->n = nargs; for (i=0; i < nargs; i++) { strcpy(pseq ->seq[i].Manufacturer, cmsTakeManufacturer(Profiles[i])); strcpy(pseq ->seq[1].Model, cmsTakeModel(Profiles[i])); } hProfile = cmsTransform2DeviceLink(hTransform, dwFlags); cmsAddTag(hProfile, icSigProfileDescriptionTag, (LPVOID) Description); cmsAddTag(hProfile, icSigCopyrightTag, (LPVOID) "Generated by littlecms icclink. No copyright, use freely"); cmsAddTag(hProfile, icSigProfileSequenceDescTag, (LPVOID) pseq); if (lUse8bits) _cmsSetLUTdepth(hProfile, 8); if (_cmsSaveProfile(hProfile, cOutProf)) fprintf(stderr, "Ok"); else fprintf(stderr, "Error saving file!"); cmsCloseProfile(hProfile); _cmsFree(pseq); } cmsDeleteTransform(hTransform); for (i=0; i < nargs; i++) { cmsCloseProfile(Profiles[i]); } return 0; }
static void OpenTransforms(int argc, char *argv[]) { DWORD dwIn, dwOut, dwFlags; if (lMultiProfileChain) { int i; cmsHTRANSFORM hTmp; nProfiles = argc - xoptind; for (i=0; i < nProfiles; i++) { hProfiles[i] = OpenProfile(argv[i+xoptind]); } // Create a temporary devicelink hTmp = cmsCreateMultiprofileTransform(hProfiles, nProfiles, 0, 0, Intent, GetFlags()); hInput = cmsTransform2DeviceLink(hTmp, 0); hOutput = NULL; cmsDeleteTransform(hTmp); InputColorSpace = cmsGetColorSpace(hInput); OutputColorSpace = cmsGetPCS(hInput); lIsDeviceLink = TRUE; } else if (lIsDeviceLink) { hInput = cmsOpenProfileFromFile(cInProf, "r"); hOutput = NULL; InputColorSpace = cmsGetColorSpace(hInput); OutputColorSpace = cmsGetPCS(hInput); } else { hInput = OpenProfile(cInProf); hOutput = OpenProfile(cOutProf); InputColorSpace = cmsGetColorSpace(hInput); OutputColorSpace = cmsGetColorSpace(hOutput); if (cmsGetDeviceClass(hInput) == icSigLinkClass || cmsGetDeviceClass(hOutput) == icSigLinkClass) FatalError("Use %cl flag for devicelink profiles!\n", SW); } if (Verbose) { mexPrintf("From: %s\n", cmsTakeProductName(hInput)); if (hOutput) mexPrintf("To : %s\n\n", cmsTakeProductName(hOutput)); } OutputChannels = _cmsChannelsOf(OutputColorSpace); InputChannels = _cmsChannelsOf(InputColorSpace); dwIn = MakeFormatDescriptor(InputColorSpace, nBytesDepth); dwOut = MakeFormatDescriptor(OutputColorSpace, nBytesDepth); dwFlags = GetFlags(); if (cProofing != NULL) { hProof = OpenProfile(cProofing); dwFlags |= cmsFLAGS_SOFTPROOFING; } hColorTransform = cmsCreateProofingTransform(hInput, dwIn, hOutput, dwOut, hProof, Intent, ProofingIntent, dwFlags); }
int main(int argc, char *argv[]) { int i, nargs, rc; cmsHPROFILE Profiles[257]; cmsHPROFILE hProfile; cmsUInt32Number dwFlags; cmsHTRANSFORM hTransform = NULL; // Here we are fprintf(stderr, "little cms ICC device link generator - v2.2 [LittleCMS %2.2f]\n", LCMS_VERSION / 1000.0); fflush(stderr); // Initialize InitUtils("linkicc"); rc = 0; // Get the options HandleSwitches(argc, argv); // How many profiles to link? nargs = (argc - xoptind); if (nargs < 1) return Help(0); if (nargs > 255) { FatalError("Holy profile! what are you trying to do with so many profiles!?"); goto Cleanup; } // Open all profiles memset(Profiles, 0, sizeof(Profiles)); for (i=0; i < nargs; i++) { Profiles[i] = OpenStockProfile(0, argv[i + xoptind]); if (Profiles[i] == NULL) goto Cleanup; if (Verbose >= 1) { PrintProfileInformation(Profiles[i]); } } // Ink limiting if (InkLimit != 400.0) { cmsColorSpaceSignature EndingColorSpace = cmsGetColorSpace(Profiles[nargs-1]); Profiles[nargs++] = cmsCreateInkLimitingDeviceLink(EndingColorSpace, InkLimit); } // Set the flags dwFlags = cmsFLAGS_KEEP_SEQUENCE; switch (PrecalcMode) { case 0: dwFlags |= cmsFLAGS_LOWRESPRECALC; break; case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break; case 1: if (NumOfGridPoints > 0) dwFlags |= cmsFLAGS_GRIDPOINTS(NumOfGridPoints); break; default: { FatalError("Unknown precalculation mode '%d'", PrecalcMode); goto Cleanup; } } if (BlackPointCompensation) dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION; if (TagResult) dwFlags |= cmsFLAGS_GUESSDEVICECLASS; if (KeepLinearization) dwFlags |= cmsFLAGS_CLUT_PRE_LINEARIZATION|cmsFLAGS_CLUT_POST_LINEARIZATION; if (lUse8bits) dwFlags |= cmsFLAGS_8BITS_DEVICELINK; cmsSetAdaptationState(ObserverAdaptationState); // Create the color transform. Specify 0 for the format is safe as the transform // is intended to be used only for the devicelink. hTransform = cmsCreateMultiprofileTransform(Profiles, nargs, 0, 0, Intent, dwFlags|cmsFLAGS_NOOPTIMIZE); if (hTransform == NULL) { FatalError("Transform creation failed"); goto Cleanup; } hProfile = cmsTransform2DeviceLink(hTransform, Version, dwFlags); if (hProfile == NULL) { FatalError("Devicelink creation failed"); goto Cleanup; } SetTextTags(hProfile); cmsSetHeaderRenderingIntent(hProfile, Intent); if (cmsSaveProfileToFile(hProfile, cOutProf)) { if (Verbose > 0) fprintf(stderr, "Ok"); } else FatalError("Error saving file!"); cmsCloseProfile(hProfile); Cleanup: if (hTransform != NULL) cmsDeleteTransform(hTransform); for (i=0; i < nargs; i++) { if (Profiles[i] != NULL) cmsCloseProfile(Profiles[i]); } return rc; }