| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507 |
- //---------------------------------------------------------------------------------
- //
- // Little Color Management System
- // Copyright (c) 1998-2023 Marti Maria Saguer
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the "Software"),
- // to deal in the Software without restriction, including without limitation
- // the rights to use, copy, modify, merge, publish, distribute, sublicense,
- // and/or sell copies of the Software, and to permit persons to whom the Software
- // is furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- //---------------------------------------------------------------------------------
- //
- #include "testcms2.h"
- // --------------------------------------------------------------------------------------------------
- // Auxiliary, duplicate a context and mark the block as non-debug because in this case the allocator
- // and deallocator have different context owners
- // --------------------------------------------------------------------------------------------------
- static
- cmsContext DupContext(cmsContext src, void* Data)
- {
- cmsContext cpy = cmsDupContext(src, Data);
- DebugMemDontCheckThis(cpy);
- return cpy;
- }
- // --------------------------------------------------------------------------------------------------
- // Simple context functions
- // --------------------------------------------------------------------------------------------------
- // Allocation order
- cmsInt32Number CheckAllocContext(cmsContext ContextID)
- {
- cmsContext c1, c2, c3, c4;
- c1 = cmsCreateContext(NULL, NULL); // This creates a context by using the normal malloc
- DebugMemDontCheckThis(c1);
- cmsDeleteContext(c1);
- c2 = cmsCreateContext(PluginMemHandler(), NULL); // This creates a context by using the debug malloc
- DebugMemDontCheckThis(c2);
- cmsDeleteContext(c2);
- c1 = cmsCreateContext(NULL, NULL);
- DebugMemDontCheckThis(c1);
- c2 = cmsCreateContext(PluginMemHandler(), NULL);
- DebugMemDontCheckThis(c2);
- cmsPlugin(c1, PluginMemHandler()); // Now the context have custom allocators
- c3 = DupContext(c1, NULL);
- c4 = DupContext(c2, NULL);
- cmsDeleteContext(c1); // Should be deleted by using nomal malloc
- cmsDeleteContext(c2); // Should be deleted by using debug malloc
- cmsDeleteContext(c3); // Should be deleted by using nomal malloc
- cmsDeleteContext(c4); // Should be deleted by using debug malloc
- return 1;
- }
- // Test the very basic context capabilities
- cmsInt32Number CheckSimpleContext(cmsContext ContextID)
- {
- int a = 1;
- int b = 32;
- cmsInt32Number rc = 0;
- cmsContext c1, c2, c3;
- // This function creates a context with a special
- // memory manager that check allocation
- c1 = WatchDogContext(&a);
- cmsDeleteContext(c1);
- c1 = WatchDogContext(&a);
- // Let's check duplication
- c2 = DupContext(c1, NULL);
- c3 = DupContext(c2, NULL);
- // User data should have been propagated
- rc = (*(int*) cmsGetContextUserData(c3)) == 1 ;
- // Free resources
- cmsDeleteContext(c1);
- cmsDeleteContext(c2);
- cmsDeleteContext(c3);
- if (!rc) {
- Fail("Creation of user data failed");
- return 0;
- }
- // Back to create 3 levels of inherance
- c1 = cmsCreateContext(NULL, &a);
- DebugMemDontCheckThis(c1);
- c2 = DupContext(c1, NULL);
- c3 = DupContext(c2, &b);
- rc = (*(int*) cmsGetContextUserData(c3)) == 32 ;
- cmsDeleteContext(c1);
- cmsDeleteContext(c2);
- cmsDeleteContext(c3);
- if (!rc) {
- Fail("Modification of user data failed");
- return 0;
- }
- // All seems ok
- return rc;
- }
- // --------------------------------------------------------------------------------------------------
- //Alarm color functions
- // --------------------------------------------------------------------------------------------------
- // This function tests the alarm codes across contexts
- cmsInt32Number CheckAlarmColorsContext(cmsContext ContextID)
- {
- cmsInt32Number rc = 0;
- const cmsUInt16Number codes[] = {0x0000, 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, 0x9999, 0xaaaa, 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff};
- cmsUInt16Number out[16];
- cmsContext c1, c2, c3;
- int i;
- c1 = WatchDogContext(NULL);
- cmsSetAlarmCodes(c1, codes);
- c2 = DupContext(c1, NULL);
- c3 = DupContext(c2, NULL);
- cmsGetAlarmCodes(c3, out);
- rc = 1;
- for (i=0; i < 16; i++) {
- if (out[i] != codes[i]) {
- Fail("Bad alarm code %x != %x", out[i], codes[i]);
- rc = 0;
- break;
- }
- }
- cmsDeleteContext(c1);
- cmsDeleteContext(c2);
- cmsDeleteContext(c3);
- return rc;
- }
- // --------------------------------------------------------------------------------------------------
- //Adaptation state functions
- // --------------------------------------------------------------------------------------------------
- // Similar to the previous, but for adaptation state
- cmsInt32Number CheckAdaptationStateContext(cmsContext ContextID)
- {
- cmsInt32Number rc = 0;
- cmsContext c1, c2, c3;
- cmsFloat64Number old1, old2;
- old1 = cmsSetAdaptationState(NULL, -1);
- c1 = WatchDogContext(NULL);
- cmsSetAdaptationState(c1, 0.7);
- c2 = DupContext(c1, NULL);
- c3 = DupContext(c2, NULL);
- rc = IsGoodVal("Adaptation state", cmsSetAdaptationState(c3, -1), 0.7, 0.001);
- cmsDeleteContext(c1);
- cmsDeleteContext(c2);
- cmsDeleteContext(c3);
- old2 = cmsSetAdaptationState(NULL, -1);
- if (old1 != old2) {
- Fail("Adaptation state has changed");
- return 0;
- }
- return rc;
- }
- // --------------------------------------------------------------------------------------------------
- // Interpolation plugin check: A fake 1D and 3D interpolation will be used to test the functionality.
- // --------------------------------------------------------------------------------------------------
- // This fake interpolation takes always the closest lower node in the interpolation table for 1D
- static
- void Fake1Dfloat(cmsContext ContextID, const cmsFloat32Number Value[],
- cmsFloat32Number Output[],
- const cmsInterpParams* p)
- {
- cmsFloat32Number val2;
- int cell;
- const cmsFloat32Number* LutTable = (const cmsFloat32Number*) p ->Table;
- // Clip upper values
- if (Value[0] >= 1.0) {
- Output[0] = LutTable[p -> Domain[0]];
- return;
- }
- val2 = p -> Domain[0] * Value[0];
- cell = (int) floor(val2);
- Output[0] = LutTable[cell] ;
- }
- // This fake interpolation just uses scrambled negated indexes for output
- static
- void Fake3D16(cmsContext ContextID,
- CMSREGISTER const cmsUInt16Number Input[],
- CMSREGISTER cmsUInt16Number Output[],
- CMSREGISTER const struct _cms_interp_struc* p)
- {
- Output[0] = 0xFFFF - Input[2];
- Output[1] = 0xFFFF - Input[1];
- Output[2] = 0xFFFF - Input[0];
- }
- // The factory chooses interpolation routines on depending on certain conditions.
- cmsInterpFunction my_Interpolators_Factory(cmsContext ContextID, cmsUInt32Number nInputChannels,
- cmsUInt32Number nOutputChannels,
- cmsUInt32Number dwFlags)
- {
- cmsInterpFunction Interpolation;
- cmsBool IsFloat = (dwFlags & CMS_LERP_FLAGS_FLOAT);
- // Initialize the return to zero as a non-supported mark
- memset(&Interpolation, 0, sizeof(Interpolation));
- // For 1D to 1D and floating point
- if (nInputChannels == 1 && nOutputChannels == 1 && IsFloat) {
- Interpolation.LerpFloat = Fake1Dfloat;
- }
- else
- if (nInputChannels == 3 && nOutputChannels == 3 && !IsFloat) {
- // For 3D to 3D and 16 bits
- Interpolation.Lerp16 = Fake3D16;
- }
- // Here is the interpolation
- return Interpolation;
- }
- // Interpolation plug-in
- static
- cmsPluginInterpolation InterpPluginSample = {
- { cmsPluginMagicNumber, 2060-2000, cmsPluginInterpolationSig, NULL },
- my_Interpolators_Factory
- };
- // This is the check code for 1D interpolation plug-in
- cmsInt32Number CheckInterp1DPlugin(cmsContext ContextID)
- {
- cmsToneCurve* Sampled1D = NULL;
- cmsContext ctx = NULL;
- cmsContext cpy = NULL;
- const cmsFloat32Number tab[] = { 0.0f, 0.10f, 0.20f, 0.30f, 0.40f, 0.50f, 0.60f, 0.70f, 0.80f, 0.90f, 1.00f }; // A straight line
- // 1st level context
- ctx = WatchDogContext(NULL);
- if (ctx == NULL) {
- Fail("Cannot create context");
- goto Error;
- }
- cmsPlugin(ctx, &InterpPluginSample);
- cpy = DupContext(ctx, NULL);
- if (cpy == NULL) {
- Fail("Cannot create context (2)");
- goto Error;
- }
- Sampled1D = cmsBuildTabulatedToneCurveFloat(cpy, 11, tab);
- if (Sampled1D == NULL) {
- Fail("Cannot create tone curve (1)");
- goto Error;
- }
- // Do some interpolations with the plugin
- if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(cpy, Sampled1D, 0.10f), 0.10, 0.01)) goto Error;
- if (!IsGoodVal("0.13", cmsEvalToneCurveFloat(cpy, Sampled1D, 0.13f), 0.10, 0.01)) goto Error;
- if (!IsGoodVal("0.55", cmsEvalToneCurveFloat(cpy, Sampled1D, 0.55f), 0.50, 0.01)) goto Error;
- if (!IsGoodVal("0.9999", cmsEvalToneCurveFloat(cpy, Sampled1D, 0.9999f), 0.90, 0.01)) goto Error;
- cmsFreeToneCurve(cpy, Sampled1D);
- cmsDeleteContext(ctx);
- cmsDeleteContext(cpy);
- // Now in global context
- Sampled1D = cmsBuildTabulatedToneCurveFloat(NULL, 11, tab);
- if (Sampled1D == NULL) {
- Fail("Cannot create tone curve (2)");
- goto Error;
- }
- // Now without the plug-in
- if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(NULL, Sampled1D, 0.10f), 0.10, 0.001)) goto Error;
- if (!IsGoodVal("0.13", cmsEvalToneCurveFloat(NULL, Sampled1D, 0.13f), 0.13, 0.001)) goto Error;
- if (!IsGoodVal("0.55", cmsEvalToneCurveFloat(NULL, Sampled1D, 0.55f), 0.55, 0.001)) goto Error;
- if (!IsGoodVal("0.9999", cmsEvalToneCurveFloat(NULL, Sampled1D, 0.9999f), 0.9999, 0.001)) goto Error;
- cmsFreeToneCurve(NULL, Sampled1D);
- return 1;
- Error:
- if (ctx != NULL) cmsDeleteContext(ctx);
- if (cpy != NULL) cmsDeleteContext(ctx);
- if (Sampled1D != NULL) cmsFreeToneCurve(NULL, Sampled1D);
- return 0;
- }
- // Checks the 3D interpolation
- cmsInt32Number CheckInterp3DPlugin(cmsContext ContextID)
- {
- cmsPipeline* p;
- cmsStage* clut;
- cmsContext ctx;
- cmsUInt16Number In[3], Out[3];
- cmsUInt16Number identity[] = {
- 0, 0, 0,
- 0, 0, 0xffff,
- 0, 0xffff, 0,
- 0, 0xffff, 0xffff,
- 0xffff, 0, 0,
- 0xffff, 0, 0xffff,
- 0xffff, 0xffff, 0,
- 0xffff, 0xffff, 0xffff
- };
- ctx = WatchDogContext(NULL);
- if (ctx == NULL) {
- Fail("Cannot create context");
- return 0;
- }
- cmsPlugin(ctx, &InterpPluginSample);
- p = cmsPipelineAlloc(ctx, 3, 3);
- clut = cmsStageAllocCLut16bit(ctx, 2, 3, 3, identity);
- cmsPipelineInsertStage(ctx, p, cmsAT_BEGIN, clut);
- // Do some interpolations with the plugin
- In[0] = 0; In[1] = 0; In[2] = 0;
- cmsPipelineEval16(ctx, In, Out, p);
- if (!IsGoodWord("0", Out[0], 0xFFFF - 0)) goto Error;
- if (!IsGoodWord("1", Out[1], 0xFFFF - 0)) goto Error;
- if (!IsGoodWord("2", Out[2], 0xFFFF - 0)) goto Error;
- In[0] = 0x1234; In[1] = 0x5678; In[2] = 0x9ABC;
- cmsPipelineEval16(ctx, In, Out, p);
- if (!IsGoodWord("0", 0xFFFF - 0x9ABC, Out[0])) goto Error;
- if (!IsGoodWord("1", 0xFFFF - 0x5678, Out[1])) goto Error;
- if (!IsGoodWord("2", 0xFFFF - 0x1234, Out[2])) goto Error;
- cmsPipelineFree(ctx, p);
- cmsDeleteContext(ctx);
- // Now without the plug-in
- p = cmsPipelineAlloc(NULL, 3, 3);
- clut = cmsStageAllocCLut16bit(NULL, 2, 3, 3, identity);
- cmsPipelineInsertStage(NULL, p, cmsAT_BEGIN, clut);
- In[0] = 0; In[1] = 0; In[2] = 0;
- cmsPipelineEval16(NULL, In, Out, p);
- if (!IsGoodWord("0", 0, Out[0])) goto Error;
- if (!IsGoodWord("1", 0, Out[1])) goto Error;
- if (!IsGoodWord("2", 0, Out[2])) goto Error;
- In[0] = 0x1234; In[1] = 0x5678; In[2] = 0x9ABC;
- cmsPipelineEval16(NULL, In, Out, p);
- if (!IsGoodWord("0", 0x1234, Out[0])) goto Error;
- if (!IsGoodWord("1", 0x5678, Out[1])) goto Error;
- if (!IsGoodWord("2", 0x9ABC, Out[2])) goto Error;
- cmsPipelineFree(NULL, p);
- return 1;
- Error:
- cmsPipelineFree(NULL, p);
- return 0;
- }
- // --------------------------------------------------------------------------------------------------
- // Parametric curve plugin check: sin(x)/cos(x) function will be used to test the functionality.
- // --------------------------------------------------------------------------------------------------
- #define TYPE_SIN 1000
- #define TYPE_COS 1010
- #define TYPE_TAN 1020
- #define TYPE_709 709
- static cmsFloat64Number my_fns(cmsContext ContextID, cmsInt32Number Type,
- const cmsFloat64Number Params[],
- cmsFloat64Number R)
- {
- cmsFloat64Number Val;
- switch (Type) {
- case TYPE_SIN:
- Val = Params[0]* sin(R * M_PI);
- break;
- case -TYPE_SIN:
- Val = asin(R) / (M_PI * Params[0]);
- break;
- case TYPE_COS:
- Val = Params[0]* cos(R * M_PI);
- break;
- case -TYPE_COS:
- Val = acos(R) / (M_PI * Params[0]);
- break;
- default: return -1.0;
- }
- return Val;
- }
- static
- cmsFloat64Number my_fns2(cmsContext ContextID, cmsInt32Number Type,
- const cmsFloat64Number Params[],
- cmsFloat64Number R)
- {
- cmsFloat64Number Val;
- switch (Type) {
- case TYPE_TAN:
- Val = Params[0]* tan(R * M_PI);
- break;
- case -TYPE_TAN:
- Val = atan(R) / (M_PI * Params[0]);
- break;
- default: return -1.0;
- }
- return Val;
- }
- static double Rec709Math(cmsContext ContextID, int Type, const double Params[], double R)
- {
- double Fun = 0;
- switch (Type)
- {
- case 709:
- if (R <= (Params[3]*Params[4])) Fun = R / Params[3];
- else Fun = pow(((R - Params[2])/Params[1]), Params[0]);
- break;
- case -709:
- if (R <= Params[4]) Fun = R * Params[3];
- else Fun = Params[1] * pow(R, (1/Params[0])) + Params[2];
- break;
- }
- return Fun;
- }
- // Add nonstandard TRC curves -> Rec709
- cmsPluginParametricCurves Rec709Plugin = {
- { cmsPluginMagicNumber, 2060-2000, cmsPluginParametricCurveSig, NULL },
- 1, {TYPE_709}, {5}, Rec709Math
- };
- static
- cmsPluginParametricCurves CurvePluginSample = {
- { cmsPluginMagicNumber, 2060-2000, cmsPluginParametricCurveSig, NULL },
- 2, // nFunctions
- { TYPE_SIN, TYPE_COS }, // Function Types
- { 1, 1 }, // ParameterCount
- my_fns // Evaluator
- };
- static
- cmsPluginParametricCurves CurvePluginSample2 = {
- { cmsPluginMagicNumber, 2060-2000, cmsPluginParametricCurveSig, NULL },
- 1, // nFunctions
- { TYPE_TAN}, // Function Types
- { 1 }, // ParameterCount
- my_fns2 // Evaluator
- };
- // --------------------------------------------------------------------------------------------------
- // In this test, the DupContext function will be checked as well
- // --------------------------------------------------------------------------------------------------
- cmsInt32Number CheckParametricCurvePlugin(cmsContext ContextID)
- {
- cmsContext ctx = NULL;
- cmsContext cpy = NULL;
- cmsToneCurve* sinus;
- cmsToneCurve* cosinus;
- cmsToneCurve* tangent;
- cmsToneCurve* reverse_sinus;
- cmsToneCurve* reverse_cosinus;
- cmsFloat64Number scale = 1.0;
- ctx = WatchDogContext(NULL);
- cmsPlugin(ctx, &CurvePluginSample);
- cpy = DupContext(ctx, NULL);
- cmsPlugin(cpy, &CurvePluginSample2);
- sinus = cmsBuildParametricToneCurve(cpy, TYPE_SIN, &scale);
- cosinus = cmsBuildParametricToneCurve(cpy, TYPE_COS, &scale);
- tangent = cmsBuildParametricToneCurve(cpy, TYPE_TAN, &scale);
- reverse_sinus = cmsReverseToneCurve(cpy, sinus);
- reverse_cosinus = cmsReverseToneCurve(cpy, cosinus);
- if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(cpy, sinus, 0.10f), sin(0.10 * M_PI) , 0.001)) goto Error;
- if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(cpy, sinus, 0.60f), sin(0.60* M_PI), 0.001)) goto Error;
- if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(cpy, sinus, 0.90f), sin(0.90* M_PI), 0.001)) goto Error;
- if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(cpy, cosinus, 0.10f), cos(0.10* M_PI), 0.001)) goto Error;
- if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(cpy, cosinus, 0.60f), cos(0.60* M_PI), 0.001)) goto Error;
- if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(cpy, cosinus, 0.90f), cos(0.90* M_PI), 0.001)) goto Error;
- if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(cpy, tangent, 0.10f), tan(0.10* M_PI), 0.001)) goto Error;
- if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(cpy, tangent, 0.60f), tan(0.60* M_PI), 0.001)) goto Error;
- if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(cpy, tangent, 0.90f), tan(0.90* M_PI), 0.001)) goto Error;
- if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(cpy, reverse_sinus, 0.10f), asin(0.10)/M_PI, 0.001)) goto Error;
- if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(cpy, reverse_sinus, 0.60f), asin(0.60)/M_PI, 0.001)) goto Error;
- if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(cpy, reverse_sinus, 0.90f), asin(0.90)/M_PI, 0.001)) goto Error;
- if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(cpy, reverse_cosinus, 0.10f), acos(0.10)/M_PI, 0.001)) goto Error;
- if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(cpy, reverse_cosinus, 0.60f), acos(0.60)/M_PI, 0.001)) goto Error;
- if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(cpy, reverse_cosinus, 0.90f), acos(0.90)/M_PI, 0.001)) goto Error;
- cmsFreeToneCurve(cpy, sinus);
- cmsFreeToneCurve(cpy, cosinus);
- cmsFreeToneCurve(cpy, tangent);
- cmsFreeToneCurve(cpy, reverse_sinus);
- cmsFreeToneCurve(cpy, reverse_cosinus);
- cmsDeleteContext(ctx);
- cmsDeleteContext(cpy);
- return 1;
- Error:
- cmsFreeToneCurve(cpy, sinus);
- cmsFreeToneCurve(cpy, reverse_sinus);
- cmsFreeToneCurve(cpy, cosinus);
- cmsFreeToneCurve(cpy, reverse_cosinus);
- if (ctx != NULL) cmsDeleteContext(ctx);
- if (cpy != NULL) cmsDeleteContext(cpy);
- return 0;
- }
- // --------------------------------------------------------------------------------------------------
- // formatters plugin check: 5-6-5 RGB format
- // --------------------------------------------------------------------------------------------------
- // We define this special type as 0 bytes not float, and set the upper bit
- #define TYPE_RGB_565 (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(0) | (1 << 23))
- cmsUInt8Number* my_Unroll565(cmsContext ContextID,
- CMSREGISTER struct _cmstransform_struct* nfo,
- CMSREGISTER cmsUInt16Number wIn[],
- CMSREGISTER cmsUInt8Number* accum,
- CMSREGISTER cmsUInt32Number Stride)
- {
- cmsUInt16Number pixel = *(cmsUInt16Number*) accum; // Take whole pixel
- double r = floor(((double) (pixel & 31) * 65535.0) / 31.0 + 0.5);
- double g = floor((((pixel >> 5) & 63) * 65535.0) / 63.0 + 0.5);
- double b = floor((((pixel >> 11) & 31) * 65535.0) / 31.0 + 0.5);
- wIn[2] = (cmsUInt16Number) r;
- wIn[1] = (cmsUInt16Number) g;
- wIn[0] = (cmsUInt16Number) b;
- return accum + 2;
- }
- cmsUInt8Number* my_Pack565(cmsContext ContextID,
- CMSREGISTER _cmsTRANSFORM* info,
- CMSREGISTER cmsUInt16Number wOut[],
- CMSREGISTER cmsUInt8Number* output,
- CMSREGISTER cmsUInt32Number Stride)
- {
- CMSREGISTER cmsUInt16Number pixel;
- int r, g, b;
- r = (int) floor(( wOut[2] * 31) / 65535.0 + 0.5);
- g = (int) floor(( wOut[1] * 63) / 65535.0 + 0.5);
- b = (int) floor(( wOut[0] * 31) / 65535.0 + 0.5);
- pixel = (r & 31) | (( g & 63) << 5) | ((b & 31) << 11);
- *(cmsUInt16Number*) output = pixel;
- return output + 2;
- }
- cmsFormatter my_FormatterFactory(cmsContext ContextID, cmsUInt32Number Type,
- cmsFormatterDirection Dir,
- cmsUInt32Number dwFlags)
- {
- cmsFormatter Result = { NULL };
- if ((Type == TYPE_RGB_565) &&
- !(dwFlags & CMS_PACK_FLAGS_FLOAT) &&
- (Dir == cmsFormatterInput)) {
- Result.Fmt16 = my_Unroll565;
- }
- return Result;
- }
- cmsFormatter my_FormatterFactory2(cmsContext ContextID, cmsUInt32Number Type,
- cmsFormatterDirection Dir,
- cmsUInt32Number dwFlags)
- {
- cmsFormatter Result = { NULL };
- if ((Type == TYPE_RGB_565) &&
- !(dwFlags & CMS_PACK_FLAGS_FLOAT) &&
- (Dir == cmsFormatterOutput)) {
- Result.Fmt16 = my_Pack565;
- }
- return Result;
- }
- static
- cmsPluginFormatters FormattersPluginSample = { {cmsPluginMagicNumber,
- 2060-2000,
- cmsPluginFormattersSig,
- NULL},
- my_FormatterFactory };
- static
- cmsPluginFormatters FormattersPluginSample2 = { {cmsPluginMagicNumber,
- 2060-2000,
- cmsPluginFormattersSig,
- NULL},
- my_FormatterFactory2 };
- cmsInt32Number CheckFormattersPlugin(cmsContext ContextID)
- {
- cmsContext ctx = WatchDogContext(NULL);
- cmsContext cpy;
- cmsHTRANSFORM xform;
- cmsUInt16Number stream[]= { 0xffffU, 0x1234U, 0x0000U, 0x33ddU };
- cmsUInt16Number result[4];
- int i;
- cmsPlugin(ctx, &FormattersPluginSample);
- cpy = DupContext(ctx, NULL);
- cmsPlugin(cpy, &FormattersPluginSample2);
- xform = cmsCreateTransform(cpy, NULL, TYPE_RGB_565, NULL, TYPE_RGB_565, INTENT_PERCEPTUAL, cmsFLAGS_NULLTRANSFORM);
- cmsDoTransform(cpy, xform, stream, result, 4);
- cmsDeleteTransform(cpy, xform);
- cmsDeleteContext(ctx);
- cmsDeleteContext(cpy);
- for (i=0; i < 4; i++)
- if (stream[i] != result[i]) return 0;
- return 1;
- }
- // --------------------------------------------------------------------------------------------------
- // TagTypePlugin plugin check
- // --------------------------------------------------------------------------------------------------
- #define SigIntType ((cmsTagTypeSignature) 0x74747448) // 'tttH'
- #define SigInt ((cmsTagSignature) 0x74747448) // 'tttH'
- static
- void *Type_int_Read(cmsContext ContextID, struct _cms_typehandler_struct* self,
- cmsIOHANDLER* io,
- cmsUInt32Number* nItems,
- cmsUInt32Number SizeOfTag)
- {
- cmsUInt32Number* Ptr = (cmsUInt32Number*) _cmsMalloc(ContextID, sizeof(cmsUInt32Number));
- if (Ptr == NULL) return NULL;
- if (!_cmsReadUInt32Number(ContextID, io, Ptr)) return NULL;
- *nItems = 1;
- return Ptr;
- }
- static
- cmsBool Type_int_Write(cmsContext ContextID, struct _cms_typehandler_struct* self,
- cmsIOHANDLER* io,
- void* Ptr, cmsUInt32Number nItems)
- {
- return _cmsWriteUInt32Number(ContextID, io, *(cmsUInt32Number*) Ptr);
- }
- static
- void* Type_int_Dup(cmsContext ContextID, struct _cms_typehandler_struct* self,
- const void *Ptr, cmsUInt32Number n)
- {
- return _cmsDupMem(ContextID, Ptr, n * sizeof(cmsUInt32Number));
- }
- void Type_int_Free(cmsContext ContextID, struct _cms_typehandler_struct* self,
- void* Ptr)
- {
- _cmsFree(ContextID, Ptr);
- }
- static cmsPluginTag HiddenTagPluginSample = {
- { cmsPluginMagicNumber, 2060-2000, cmsPluginTagSig, NULL},
- SigInt, { 1, 1, { SigIntType }, NULL }
- };
- static cmsPluginTagType TagTypePluginSample = {
- { cmsPluginMagicNumber, 2060-2000, cmsPluginTagTypeSig, (cmsPluginBase*) &HiddenTagPluginSample},
- { SigIntType, Type_int_Read, Type_int_Write, Type_int_Dup, Type_int_Free, 0 }
- };
- cmsInt32Number CheckTagTypePlugin(cmsContext ContextID)
- {
- cmsContext ctx = NULL;
- cmsContext cpy = NULL;
- cmsContext cpy2 = NULL;
- cmsHPROFILE h = NULL;
- cmsUInt32Number myTag = 1234;
- cmsUInt32Number rc = 0;
- char* data = NULL;
- cmsUInt32Number *ptr = NULL;
- cmsUInt32Number clen = 0;
- ctx = WatchDogContext(NULL);
- cmsPlugin(ctx, &TagTypePluginSample);
- cpy = DupContext(ctx, NULL);
- cpy2 = DupContext(cpy, NULL);
- cmsDeleteContext(ctx);
- cmsDeleteContext(cpy);
- h = cmsCreateProfilePlaceholder(cpy2);
- if (h == NULL) {
- Fail("Create placeholder failed");
- goto Error;
- }
- if (!cmsWriteTag(cpy2, h, SigInt, &myTag)) {
- Fail("Plug-in failed");
- goto Error;
- }
- rc = cmsSaveProfileToMem(cpy2, h, NULL, &clen);
- if (!rc) {
- Fail("Fetch mem size failed");
- goto Error;
- }
- data = (char*) malloc(clen);
- if (data == NULL) {
- Fail("malloc failed ?!?");
- goto Error;
- }
- rc = cmsSaveProfileToMem(cpy2, h, data, &clen);
- if (!rc) {
- Fail("Save to mem failed");
- goto Error;
- }
- cmsCloseProfile(cpy2, h);
- cmsSetLogErrorHandler(ContextID, NULL);
- h = cmsOpenProfileFromMem(ContextID, data, clen);
- if (h == NULL) {
- Fail("Open profile failed");
- goto Error;
- }
- ptr = (cmsUInt32Number*) cmsReadTag(ContextID, h, SigInt);
- if (ptr != NULL) {
- Fail("read tag/context switching failed");
- goto Error;
- }
- cmsCloseProfile(ContextID, h);
- ResetFatalError(ContextID);
- h = cmsOpenProfileFromMem(cpy2, data, clen);
- if (h == NULL) {
- Fail("Open profile from mem failed");
- goto Error;
- }
- // Get rid of data
- free(data); data = NULL;
- ptr = (cmsUInt32Number*) cmsReadTag(cpy2, h, SigInt);
- if (ptr == NULL) {
- Fail("Read tag/context switching failed (2)");
- return 0;
- }
- rc = (*ptr == 1234);
- cmsCloseProfile(cpy2, h);
- cmsDeleteContext(cpy2);
- return rc;
- Error:
- if (h != NULL) cmsCloseProfile(cpy, h);
- if (ctx != NULL) cmsDeleteContext(ctx);
- if (cpy != NULL) cmsDeleteContext(cpy);
- if (data) free(data);
- return 0;
- }
- // --------------------------------------------------------------------------------------------------
- // MPE plugin check:
- // --------------------------------------------------------------------------------------------------
- #define SigNegateType ((cmsStageSignature)0x6E202020)
- static
- void EvaluateNegate(cmsContext ContextID, const cmsFloat32Number In[],
- cmsFloat32Number Out[],
- const cmsStage *mpe)
- {
- Out[0] = 1.0f - In[0];
- Out[1] = 1.0f - In[1];
- Out[2] = 1.0f - In[2];
- }
- static
- cmsStage* StageAllocNegate(cmsContext ContextID)
- {
- return _cmsStageAllocPlaceholder(ContextID,
- SigNegateType, 3, 3, EvaluateNegate,
- NULL, NULL, NULL);
- }
- static
- void *Type_negate_Read(cmsContext ContextID, struct _cms_typehandler_struct* self,
- cmsIOHANDLER* io,
- cmsUInt32Number* nItems,
- cmsUInt32Number SizeOfTag)
- {
- cmsUInt16Number Chans;
- if (!_cmsReadUInt16Number(ContextID, io, &Chans)) return NULL;
- if (Chans != 3) return NULL;
- *nItems = 1;
- return StageAllocNegate(ContextID);
- }
- static
- cmsBool Type_negate_Write(cmsContext ContextID, struct _cms_typehandler_struct* self,
- cmsIOHANDLER* io,
- void* Ptr, cmsUInt32Number nItems)
- {
- if (!_cmsWriteUInt16Number(ContextID, io, 3)) return FALSE;
- return TRUE;
- }
- static
- cmsPluginMultiProcessElement MPEPluginSample = {
- {cmsPluginMagicNumber, 2060-2000, cmsPluginMultiProcessElementSig, NULL},
- { (cmsTagTypeSignature) SigNegateType, Type_negate_Read, Type_negate_Write, NULL, NULL, 0 }
- };
- cmsInt32Number CheckMPEPlugin(cmsContext ContextID)
- {
- cmsContext ctx = NULL;
- cmsContext cpy = NULL;
- cmsContext cpy2 = NULL;
- cmsHPROFILE h = NULL;
- cmsUInt32Number rc = 0;
- char* data = NULL;
- cmsUInt32Number clen = 0;
- cmsFloat32Number In[3], Out[3];
- cmsPipeline* pipe;
- ctx = WatchDogContext(NULL);
- cmsPlugin(ctx, &MPEPluginSample);
- cpy = DupContext(ctx, NULL);
- cpy2 = DupContext(cpy, NULL);
- cmsDeleteContext(ctx);
- cmsDeleteContext(cpy);
- h = cmsCreateProfilePlaceholder(cpy2);
- if (h == NULL) {
- Fail("Create placeholder failed");
- goto Error;
- }
- pipe = cmsPipelineAlloc(cpy2, 3, 3);
- cmsPipelineInsertStage(cpy2, pipe, cmsAT_BEGIN, StageAllocNegate(cpy2));
- In[0] = 0.3f; In[1] = 0.2f; In[2] = 0.9f;
- cmsPipelineEvalFloat(cpy2, In, Out, pipe);
- rc = (IsGoodVal("0", Out[0], 1.0-In[0], 0.001) &&
- IsGoodVal("1", Out[1], 1.0-In[1], 0.001) &&
- IsGoodVal("2", Out[2], 1.0-In[2], 0.001));
- if (!rc) {
- Fail("Pipeline failed");
- goto Error;
- }
- if (!cmsWriteTag(cpy2, h, cmsSigDToB3Tag, pipe)) {
- Fail("Plug-in failed");
- goto Error;
- }
- // This cleans the stage as well
- cmsPipelineFree(cpy2, pipe);
- rc = cmsSaveProfileToMem(cpy2, h, NULL, &clen);
- if (!rc) {
- Fail("Fetch mem size failed");
- goto Error;
- }
- data = (char*) malloc(clen);
- if (data == NULL) {
- Fail("malloc failed ?!?");
- goto Error;
- }
- rc = cmsSaveProfileToMem(cpy2, h, data, &clen);
- if (!rc) {
- Fail("Save to mem failed");
- goto Error;
- }
- cmsCloseProfile(cpy2, h);
- cmsSetLogErrorHandler(ContextID, NULL);
- h = cmsOpenProfileFromMem(ContextID, data, clen);
- if (h == NULL) {
- Fail("Open profile failed");
- goto Error;
- }
- pipe = (cmsPipeline*) cmsReadTag(ContextID, h, cmsSigDToB3Tag);
- if (pipe != NULL) {
- // Unsupported stage, should fail
- Fail("read tag/context switching failed");
- goto Error;
- }
- cmsCloseProfile(ContextID, h);
- ResetFatalError(ContextID);
- h = cmsOpenProfileFromMem(cpy2, data, clen);
- if (h == NULL) {
- Fail("Open profile from mem failed");
- goto Error;
- }
- // Get rid of data
- free(data); data = NULL;
- pipe = (cmsPipeline*) cmsReadTag(cpy2, h, cmsSigDToB3Tag);
- if (pipe == NULL) {
- Fail("Read tag/context switching failed (2)");
- return 0;
- }
- // Evaluate for negation
- In[0] = 0.3f; In[1] = 0.2f; In[2] = 0.9f;
- cmsPipelineEvalFloat(cpy2, In, Out, pipe);
- rc = (IsGoodVal("0", Out[0], 1.0-In[0], 0.001) &&
- IsGoodVal("1", Out[1], 1.0-In[1], 0.001) &&
- IsGoodVal("2", Out[2], 1.0-In[2], 0.001));
- cmsCloseProfile(cpy2, h);
- cmsDeleteContext(cpy2);
- return rc;
- Error:
- if (h != NULL) cmsCloseProfile(cpy2, h);
- if (cpy2 != NULL) cmsDeleteContext(cpy2);
- if (data) free(data);
- return 0;
- }
- // --------------------------------------------------------------------------------------------------
- // Optimization plugin check:
- // --------------------------------------------------------------------------------------------------
- static
- void FastEvaluateCurves(cmsContext ContextID,
- CMSREGISTER const cmsUInt16Number In[],
- CMSREGISTER cmsUInt16Number Out[],
- CMSREGISTER const void* Data)
- {
- Out[0] = In[0];
- }
- static
- cmsBool MyOptimize(cmsContext ContextID, cmsPipeline** Lut,
- cmsUInt32Number Intent,
- cmsUInt32Number* InputFormat,
- cmsUInt32Number* OutputFormat,
- cmsUInt32Number* dwFlags)
- {
- cmsStage* mpe;
- _cmsStageToneCurvesData* Data;
- // Only curves in this LUT? All are identities?
- for (mpe = cmsPipelineGetPtrToFirstStage(ContextID, *Lut);
- mpe != NULL;
- mpe = cmsStageNext(ContextID, mpe)) {
- if (cmsStageType(ContextID, mpe) != cmsSigCurveSetElemType) return FALSE;
- // Check for identity
- Data = (_cmsStageToneCurvesData*) cmsStageData(ContextID, mpe);
- if (Data ->nCurves != 1) return FALSE;
- if (cmsEstimateGamma(ContextID, Data->TheCurves[0], 0.1) > 1.0) return FALSE;
- }
- *dwFlags |= cmsFLAGS_NOCACHE;
- _cmsPipelineSetOptimizationParameters(ContextID, *Lut, FastEvaluateCurves, NULL, NULL, NULL);
- return TRUE;
- }
- cmsPluginOptimization OptimizationPluginSample = {
- {cmsPluginMagicNumber, 2060-2000, cmsPluginOptimizationSig, NULL},
- MyOptimize
- };
- cmsInt32Number CheckOptimizationPlugin(cmsContext ContextID)
- {
- cmsContext ctx = WatchDogContext(NULL);
- cmsContext cpy;
- cmsHTRANSFORM xform;
- cmsUInt8Number In[]= { 10, 20, 30, 40 };
- cmsUInt8Number Out[4];
- cmsToneCurve* Linear[1];
- cmsHPROFILE h;
- int i;
- cmsPlugin(ctx, &OptimizationPluginSample);
- cpy = DupContext(ctx, NULL);
- Linear[0] = cmsBuildGamma(cpy, 1.0);
- h = cmsCreateLinearizationDeviceLink(cpy, cmsSigGrayData, Linear);
- cmsFreeToneCurve(cpy, Linear[0]);
- xform = cmsCreateTransform(cpy, h, TYPE_GRAY_8, h, TYPE_GRAY_8, INTENT_PERCEPTUAL, 0);
- cmsCloseProfile(cpy, h);
- cmsDoTransform(cpy, xform, In, Out, 4);
- cmsDeleteTransform(cpy, xform);
- cmsDeleteContext(ctx);
- cmsDeleteContext(cpy);
- for (i=0; i < 4; i++)
- if (In[i] != Out[i]) return 0;
- return 1;
- }
- // --------------------------------------------------------------------------------------------------
- // Check the intent plug-in
- // --------------------------------------------------------------------------------------------------
- /*
- This example creates a new rendering intent, at intent number 300, that is identical to perceptual
- intent for all color spaces but gray to gray transforms, in this case it bypasses the data.
- Note that it has to clear all occurrences of intent 300 in the intents array to avoid
- infinite recursion.
- */
- #define INTENT_DECEPTIVE 300
- static
- cmsPipeline* MyNewIntent(cmsContext ContextID,
- cmsUInt32Number nProfiles,
- cmsUInt32Number TheIntents[],
- cmsHPROFILE hProfiles[],
- cmsBool BPC[],
- cmsFloat64Number AdaptationStates[],
- cmsUInt32Number dwFlags)
- {
- cmsPipeline* Result;
- cmsUInt32Number ICCIntents[256];
- cmsUInt32Number i;
- for (i=0; i < nProfiles; i++)
- ICCIntents[i] = (TheIntents[i] == INTENT_DECEPTIVE) ? INTENT_PERCEPTUAL :
- TheIntents[i];
- if (cmsGetColorSpace(ContextID, hProfiles[0]) != cmsSigGrayData ||
- cmsGetColorSpace(ContextID, hProfiles[nProfiles-1]) != cmsSigGrayData)
- return _cmsDefaultICCintents(ContextID, nProfiles,
- ICCIntents, hProfiles,
- BPC, AdaptationStates,
- dwFlags);
- Result = cmsPipelineAlloc(ContextID, 1, 1);
- if (Result == NULL) return NULL;
- cmsPipelineInsertStage(ContextID, Result, cmsAT_BEGIN,
- cmsStageAllocIdentity(ContextID, 1));
- return Result;
- }
- static cmsPluginRenderingIntent IntentPluginSample = {
- {cmsPluginMagicNumber, 2060-2000, cmsPluginRenderingIntentSig, NULL},
- INTENT_DECEPTIVE, MyNewIntent, "bypass gray to gray rendering intent"
- };
- cmsInt32Number CheckIntentPlugin(cmsContext ContextID)
- {
- cmsContext ctx = WatchDogContext(NULL);
- cmsContext cpy;
- cmsHTRANSFORM xform;
- cmsHPROFILE h1, h2;
- cmsToneCurve* Linear1;
- cmsToneCurve* Linear2;
- cmsUInt8Number In[]= { 10, 20, 30, 40 };
- cmsUInt8Number Out[4];
- int i;
- cmsPlugin(ctx, &IntentPluginSample);
- cpy = DupContext(ctx, NULL);
- Linear1 = cmsBuildGamma(cpy, 3.0);
- Linear2 = cmsBuildGamma(cpy, 0.1);
- h1 = cmsCreateLinearizationDeviceLink(cpy, cmsSigGrayData, &Linear1);
- h2 = cmsCreateLinearizationDeviceLink(cpy, cmsSigGrayData, &Linear2);
- cmsFreeToneCurve(cpy, Linear1);
- cmsFreeToneCurve(cpy, Linear2);
- xform = cmsCreateTransform(cpy, h1, TYPE_GRAY_8, h2, TYPE_GRAY_8, INTENT_DECEPTIVE, 0);
- cmsCloseProfile(cpy,h1); cmsCloseProfile(cpy, h2);
- cmsDoTransform(cpy, xform, In, Out, 4);
- cmsDeleteTransform(cpy, xform);
- cmsDeleteContext(cpy);
- cmsDeleteContext(ctx);
- for (i=0; i < 4; i++)
- if (Out[i] != In[i]) return 0;
- return 1;
- }
- // --------------------------------------------------------------------------------------------------
- // Check the full transform plug-in
- // --------------------------------------------------------------------------------------------------
- // This is a sample intent that only works for gray8 as output, and always returns '42'
- static
- void TrancendentalTransform(cmsContext ContextID, struct _cmstransform_struct * CMM,
- const void* InputBuffer,
- void* OutputBuffer,
- cmsUInt32Number Size,
- cmsUInt32Number Stride)
- {
- cmsUInt32Number i;
- for (i=0; i < Size; i++)
- {
- ((cmsUInt8Number*) OutputBuffer)[i] = 0x42;
- }
- }
- cmsBool TransformFactory(cmsContext ContextID, _cmsTransformFn* xformPtr,
- void** UserData,
- _cmsFreeUserDataFn* FreePrivateDataFn,
- cmsPipeline** Lut,
- cmsUInt32Number* InputFormat,
- cmsUInt32Number* OutputFormat,
- cmsUInt32Number* dwFlags)
- {
- if (*OutputFormat == TYPE_GRAY_8)
- {
- // *Lut holds the pipeline to be applied
- *xformPtr = TrancendentalTransform;
- return TRUE;
- }
- return FALSE;
- }
- // The Plug-in entry point
- static cmsPluginTransform FullTransformPluginSample = {
- { cmsPluginMagicNumber, 2060-2000, cmsPluginTransformSig, NULL},
- { TransformFactory }
- };
- cmsInt32Number CheckTransformPlugin(cmsContext ContextID)
- {
- cmsContext ctx = WatchDogContext(NULL);
- cmsContext cpy;
- cmsHTRANSFORM xform;
- cmsUInt8Number In[]= { 10, 20, 30, 40 };
- cmsUInt8Number Out[4];
- cmsToneCurve* Linear;
- cmsHPROFILE h;
- int i;
- cmsPlugin(ctx, &FullTransformPluginSample);
- cpy = DupContext(ctx, NULL);
- Linear = cmsBuildGamma(cpy, 1.0);
- h = cmsCreateLinearizationDeviceLink(cpy, cmsSigGrayData, &Linear);
- cmsFreeToneCurve(cpy, Linear);
- xform = cmsCreateTransform(cpy, h, TYPE_GRAY_8, h, TYPE_GRAY_8, INTENT_PERCEPTUAL, 0);
- cmsCloseProfile(cpy, h);
- cmsDoTransform(cpy, xform, In, Out, 4);
- cmsDeleteTransform(cpy, xform);
- cmsDeleteContext(ctx);
- cmsDeleteContext(cpy);
- for (i=0; i < 4; i++)
- if (Out[i] != 0x42) return 0;
- return 1;
- }
- // --------------------------------------------------------------------------------------------------
- // Check the mutex plug-in
- // --------------------------------------------------------------------------------------------------
- typedef struct {
- int nlocks;
- } MyMtx;
- static
- void* MyMtxCreate(cmsContext id)
- {
- MyMtx* mtx = (MyMtx*) _cmsMalloc(id, sizeof(MyMtx));
- mtx ->nlocks = 0;
- return mtx;
- }
- static
- void MyMtxDestroy(cmsContext id, void* mtx)
- {
- MyMtx* mtx_ = (MyMtx*) mtx;
- if (mtx_->nlocks != 0)
- Die("Locks != 0 when setting free a mutex");
- _cmsFree(id, mtx);
- }
- static
- cmsBool MyMtxLock(cmsContext id, void* mtx)
- {
- MyMtx* mtx_ = (MyMtx*) mtx;
- mtx_->nlocks++;
- return TRUE;
- }
- static
- void MyMtxUnlock(cmsContext id, void* mtx)
- {
- MyMtx* mtx_ = (MyMtx*) mtx;
- mtx_->nlocks--;
- }
- static cmsPluginMutex MutexPluginSample = {
- { cmsPluginMagicNumber, 2060, cmsPluginMutexSig, NULL},
- MyMtxCreate, MyMtxDestroy, MyMtxLock, MyMtxUnlock
- };
- cmsInt32Number CheckMutexPlugin(cmsContext ContextID)
- {
- cmsContext ctx = WatchDogContext(NULL);
- cmsContext cpy;
- cmsHTRANSFORM xform;
- cmsUInt8Number In[]= { 10, 20, 30, 40 };
- cmsUInt8Number Out[4];
- cmsToneCurve* Linear;
- cmsHPROFILE h;
- int i;
- cmsPlugin(ctx, &MutexPluginSample);
- cpy = DupContext(ctx, NULL);
- Linear = cmsBuildGamma(cpy, 1.0);
- h = cmsCreateLinearizationDeviceLink(cpy, cmsSigGrayData, &Linear);
- cmsFreeToneCurve(cpy, Linear);
- xform = cmsCreateTransform(cpy, h, TYPE_GRAY_8, h, TYPE_GRAY_8, INTENT_PERCEPTUAL, 0);
- cmsCloseProfile(cpy, h);
- cmsDoTransform(cpy, xform, In, Out, 4);
- cmsDeleteTransform(cpy, xform);
- cmsDeleteContext(ctx);
- cmsDeleteContext(cpy);
- for (i=0; i < 4; i++)
- if (Out[i] != In[i]) return 0;
- return 1;
- }
- cmsInt32Number CheckMethodPackDoublesFromFloat(cmsContext ContextID)
- {
- cmsContext ctx = WatchDogContext(NULL);
- cmsHTRANSFORM xform;
- cmsHTRANSFORM l_pFakeProfileLAB;
- cmsFloat64Number l_D_OutputColorArrayBlack[8];
- cmsFloat64Number l_D_OutputColorArrayBlue[8];
- cmsCIELab LabInBlack;
- cmsCIELab LabInBlue;
- cmsUInt16Number Lab_UI16_Black[3];
- cmsUInt16Number Lab_UI16_Blue[3];
- cmsHPROFILE OutputCMYKProfile;
- cmsUInt32Number l_UI32_OutputFormat;
- cmsPlugin(ctx, &FullTransformPluginSample);
- l_pFakeProfileLAB = cmsCreateLab2Profile(ctx, NULL);
- if (l_pFakeProfileLAB == NULL)
- return 0;
- OutputCMYKProfile = cmsOpenProfileFromFile(ctx, "TestCLT.icc", "r");
- if (OutputCMYKProfile == NULL)
- return 0;
- l_UI32_OutputFormat = 0;
- l_UI32_OutputFormat |= COLORSPACE_SH(PT_CMYK);
- l_UI32_OutputFormat |= PLANAR_SH(1);
- l_UI32_OutputFormat |= CHANNELS_SH(4);
- l_UI32_OutputFormat |= BYTES_SH(0);
- l_UI32_OutputFormat |= FLOAT_SH(1);
- xform = cmsCreateTransform(ctx, l_pFakeProfileLAB, TYPE_Lab_DBL, OutputCMYKProfile, l_UI32_OutputFormat, INTENT_PERCEPTUAL, 0);
- cmsCloseProfile(ctx, OutputCMYKProfile);
- cmsCloseProfile(ctx, l_pFakeProfileLAB);
- Lab_UI16_Black[0] = 0;
- Lab_UI16_Black[1] = 32768;
- Lab_UI16_Black[2] = 32768;
- Lab_UI16_Blue[0] = 0;
- Lab_UI16_Blue[1] = 8192;
- Lab_UI16_Blue[2] = 8192;
- cmsLabEncoded2Float(ctx, &LabInBlack, Lab_UI16_Black);
- cmsLabEncoded2Float(ctx, &LabInBlue, Lab_UI16_Blue);
- memset(l_D_OutputColorArrayBlack, 0, sizeof(l_D_OutputColorArrayBlack));
- memset(l_D_OutputColorArrayBlue, 0, sizeof(l_D_OutputColorArrayBlue));
- cmsDoTransform(ctx, xform, &LabInBlack, l_D_OutputColorArrayBlack, 1);
- cmsDoTransform(ctx, xform, &LabInBlue, l_D_OutputColorArrayBlue, 1);
- cmsDeleteTransform(ctx, xform);
- cmsDeleteContext(ctx);
- return 1;
- }
|