This source file includes following definitions.
- DupContext
- CheckAllocContext
- CheckSimpleContext
- CheckAlarmColorsContext
- CheckAdaptationStateContext
- Fake1Dfloat
- Fake3D16
- my_Interpolators_Factory
- CheckInterp1DPlugin
- CheckInterp3DPlugin
- my_fns
- my_fns2
- Rec709Math
- CheckParametricCurvePlugin
- my_Unroll565
- my_Pack565
- my_FormatterFactory
- my_FormatterFactory2
- CheckFormattersPlugin
- Type_int_Read
- Type_int_Write
- Type_int_Dup
- Type_int_Free
- CheckTagTypePlugin
- EvaluateNegate
- StageAllocNegate
- Type_negate_Read
- Type_negate_Write
- CheckMPEPlugin
- FastEvaluateCurves
- MyOptimize
- CheckOptimizationPlugin
- MyNewIntent
- CheckIntentPlugin
- TrancendentalTransform
- TransformFactory
- CheckTransformPlugin
- MyMtxCreate
- MyMtxDestroy
- MyMtxLock
- MyMtxUnlock
- CheckMutexPlugin
#include "testcms2.h"
static
cmsContext DupContext(cmsContext src, void* Data)
{
cmsContext cpy = cmsDupContext(src, Data);
DebugMemDontCheckThis(cpy);
return cpy;
}
cmsInt32Number CheckAllocContext(void)
{
cmsContext c1, c2, c3, c4;
c1 = cmsCreateContext(NULL, NULL);
DebugMemDontCheckThis(c1);
cmsDeleteContext(c1);
c2 = cmsCreateContext(PluginMemHandler(), NULL);
DebugMemDontCheckThis(c2);
cmsDeleteContext(c2);
c1 = cmsCreateContext(NULL, NULL);
DebugMemDontCheckThis(c1);
c2 = cmsCreateContext(PluginMemHandler(), NULL);
DebugMemDontCheckThis(c2);
cmsPluginTHR(c1, PluginMemHandler());
c3 = DupContext(c1, NULL);
c4 = DupContext(c2, NULL);
cmsDeleteContext(c1);
cmsDeleteContext(c2);
cmsDeleteContext(c3);
cmsDeleteContext(c4);
return 1;
}
cmsInt32Number CheckSimpleContext(void)
{
int a = 1;
int b = 32;
cmsInt32Number rc = 0;
cmsContext c1, c2, c3;
c1 = WatchDogContext(&a);
cmsDeleteContext(c1);
c1 = WatchDogContext(&a);
c2 = DupContext(c1, NULL);
c3 = DupContext(c2, NULL);
rc = (*(int*) cmsGetContextUserData(c3)) == 1 ;
cmsDeleteContext(c1);
cmsDeleteContext(c2);
cmsDeleteContext(c3);
if (!rc) {
Fail("Creation of user data failed");
return 0;
}
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;
}
return rc;
}
cmsInt32Number CheckAlarmColorsContext(void)
{
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);
cmsSetAlarmCodesTHR(c1, codes);
c2 = DupContext(c1, NULL);
c3 = DupContext(c2, NULL);
cmsGetAlarmCodesTHR(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;
}
cmsInt32Number CheckAdaptationStateContext(void)
{
cmsInt32Number rc = 0;
cmsContext c1, c2, c3;
cmsFloat64Number old1, old2;
old1 = cmsSetAdaptationStateTHR(NULL, -1);
c1 = WatchDogContext(NULL);
cmsSetAdaptationStateTHR(c1, 0.7);
c2 = DupContext(c1, NULL);
c3 = DupContext(c2, NULL);
rc = IsGoodVal("Adaptation state", cmsSetAdaptationStateTHR(c3, -1), 0.7, 0.001);
cmsDeleteContext(c1);
cmsDeleteContext(c2);
cmsDeleteContext(c3);
old2 = cmsSetAdaptationStateTHR(NULL, -1);
if (old1 != old2) {
Fail("Adaptation state has changed");
return 0;
}
return rc;
}
static
void Fake1Dfloat(const cmsFloat32Number Value[],
cmsFloat32Number Output[],
const cmsInterpParams* p)
{
cmsFloat32Number val2;
int cell;
const cmsFloat32Number* LutTable = (const cmsFloat32Number*) p ->Table;
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] ;
}
static
void Fake3D16(register const cmsUInt16Number Input[],
register cmsUInt16Number Output[],
register const struct _cms_interp_struc* p)
{
Output[0] = 0xFFFF - Input[2];
Output[1] = 0xFFFF - Input[1];
Output[2] = 0xFFFF - Input[0];
}
cmsInterpFunction my_Interpolators_Factory(cmsUInt32Number nInputChannels,
cmsUInt32Number nOutputChannels,
cmsUInt32Number dwFlags)
{
cmsInterpFunction Interpolation;
cmsBool IsFloat = (dwFlags & CMS_LERP_FLAGS_FLOAT);
memset(&Interpolation, 0, sizeof(Interpolation));
if (nInputChannels == 1 && nOutputChannels == 1 && IsFloat) {
Interpolation.LerpFloat = Fake1Dfloat;
}
else
if (nInputChannels == 3 && nOutputChannels == 3 && !IsFloat) {
Interpolation.Lerp16 = Fake3D16;
}
return Interpolation;
}
static
cmsPluginInterpolation InterpPluginSample = {
{ cmsPluginMagicNumber, 2060, cmsPluginInterpolationSig, NULL },
my_Interpolators_Factory
};
cmsInt32Number CheckInterp1DPlugin(void)
{
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 };
ctx = WatchDogContext(NULL);
if (ctx == NULL) {
Fail("Cannot create context");
goto Error;
}
cmsPluginTHR(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;
}
if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(Sampled1D, 0.10f), 0.10, 0.01)) goto Error;
if (!IsGoodVal("0.13", cmsEvalToneCurveFloat(Sampled1D, 0.13f), 0.10, 0.01)) goto Error;
if (!IsGoodVal("0.55", cmsEvalToneCurveFloat(Sampled1D, 0.55f), 0.50, 0.01)) goto Error;
if (!IsGoodVal("0.9999", cmsEvalToneCurveFloat(Sampled1D, 0.9999f), 0.90, 0.01)) goto Error;
cmsFreeToneCurve(Sampled1D);
cmsDeleteContext(ctx);
cmsDeleteContext(cpy);
Sampled1D = cmsBuildTabulatedToneCurveFloat(NULL, 11, tab);
if (Sampled1D == NULL) {
Fail("Cannot create tone curve (2)");
goto Error;
}
if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(Sampled1D, 0.10f), 0.10, 0.001)) goto Error;
if (!IsGoodVal("0.13", cmsEvalToneCurveFloat(Sampled1D, 0.13f), 0.13, 0.001)) goto Error;
if (!IsGoodVal("0.55", cmsEvalToneCurveFloat(Sampled1D, 0.55f), 0.55, 0.001)) goto Error;
if (!IsGoodVal("0.9999", cmsEvalToneCurveFloat(Sampled1D, 0.9999f), 0.9999, 0.001)) goto Error;
cmsFreeToneCurve(Sampled1D);
return 1;
Error:
if (ctx != NULL) cmsDeleteContext(ctx);
if (cpy != NULL) cmsDeleteContext(ctx);
if (Sampled1D != NULL) cmsFreeToneCurve(Sampled1D);
return 0;
}
cmsInt32Number CheckInterp3DPlugin(void)
{
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;
}
cmsPluginTHR(ctx, &InterpPluginSample);
p = cmsPipelineAlloc(ctx, 3, 3);
clut = cmsStageAllocCLut16bit(ctx, 2, 3, 3, identity);
cmsPipelineInsertStage(p, cmsAT_BEGIN, clut);
In[0] = 0; In[1] = 0; In[2] = 0;
cmsPipelineEval16(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(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(p);
cmsDeleteContext(ctx);
p = cmsPipelineAlloc(NULL, 3, 3);
clut = cmsStageAllocCLut16bit(NULL, 2, 3, 3, identity);
cmsPipelineInsertStage(p, cmsAT_BEGIN, clut);
In[0] = 0; In[1] = 0; In[2] = 0;
cmsPipelineEval16(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(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(p);
return 1;
Error:
cmsPipelineFree(p);
return 0;
}
#define TYPE_SIN 1000
#define TYPE_COS 1010
#define TYPE_TAN 1020
#define TYPE_709 709
static cmsFloat64Number my_fns(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(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(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;
}
cmsPluginParametricCurves Rec709Plugin = {
{ cmsPluginMagicNumber, 2060, cmsPluginParametricCurveSig, NULL },
1, {TYPE_709}, {5}, Rec709Math
};
static
cmsPluginParametricCurves CurvePluginSample = {
{ cmsPluginMagicNumber, 2060, cmsPluginParametricCurveSig, NULL },
2,
{ TYPE_SIN, TYPE_COS },
{ 1, 1 },
my_fns
};
static
cmsPluginParametricCurves CurvePluginSample2 = {
{ cmsPluginMagicNumber, 2060, cmsPluginParametricCurveSig, NULL },
1,
{ TYPE_TAN},
{ 1 },
my_fns2
};
cmsInt32Number CheckParametricCurvePlugin(void)
{
cmsContext ctx = NULL;
cmsContext cpy = NULL;
cmsContext cpy2 = NULL;
cmsToneCurve* sinus;
cmsToneCurve* cosinus;
cmsToneCurve* tangent;
cmsToneCurve* reverse_sinus;
cmsToneCurve* reverse_cosinus;
cmsFloat64Number scale = 1.0;
ctx = WatchDogContext(NULL);
cmsPluginTHR(ctx, &CurvePluginSample);
cpy = DupContext(ctx, NULL);
cmsPluginTHR(cpy, &CurvePluginSample2);
cpy2 = DupContext(cpy, NULL);
cmsPluginTHR(cpy2, &Rec709Plugin);
sinus = cmsBuildParametricToneCurve(cpy, TYPE_SIN, &scale);
cosinus = cmsBuildParametricToneCurve(cpy, TYPE_COS, &scale);
tangent = cmsBuildParametricToneCurve(cpy, TYPE_TAN, &scale);
reverse_sinus = cmsReverseToneCurve(sinus);
reverse_cosinus = cmsReverseToneCurve(cosinus);
if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(sinus, 0.10f), sin(0.10 * M_PI) , 0.001)) goto Error;
if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(sinus, 0.60f), sin(0.60* M_PI), 0.001)) goto Error;
if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(sinus, 0.90f), sin(0.90* M_PI), 0.001)) goto Error;
if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(cosinus, 0.10f), cos(0.10* M_PI), 0.001)) goto Error;
if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(cosinus, 0.60f), cos(0.60* M_PI), 0.001)) goto Error;
if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(cosinus, 0.90f), cos(0.90* M_PI), 0.001)) goto Error;
if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(tangent, 0.10f), tan(0.10* M_PI), 0.001)) goto Error;
if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(tangent, 0.60f), tan(0.60* M_PI), 0.001)) goto Error;
if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(tangent, 0.90f), tan(0.90* M_PI), 0.001)) goto Error;
if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(reverse_sinus, 0.10f), asin(0.10)/M_PI, 0.001)) goto Error;
if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(reverse_sinus, 0.60f), asin(0.60)/M_PI, 0.001)) goto Error;
if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(reverse_sinus, 0.90f), asin(0.90)/M_PI, 0.001)) goto Error;
if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(reverse_cosinus, 0.10f), acos(0.10)/M_PI, 0.001)) goto Error;
if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(reverse_cosinus, 0.60f), acos(0.60)/M_PI, 0.001)) goto Error;
if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(reverse_cosinus, 0.90f), acos(0.90)/M_PI, 0.001)) goto Error;
cmsFreeToneCurve(sinus);
cmsFreeToneCurve(cosinus);
cmsFreeToneCurve(tangent);
cmsFreeToneCurve(reverse_sinus);
cmsFreeToneCurve(reverse_cosinus);
cmsDeleteContext(ctx);
cmsDeleteContext(cpy);
cmsDeleteContext(cpy2);
return 1;
Error:
cmsFreeToneCurve(sinus);
cmsFreeToneCurve(reverse_sinus);
cmsFreeToneCurve(cosinus);
cmsFreeToneCurve(reverse_cosinus);
if (ctx != NULL) cmsDeleteContext(ctx);
if (cpy != NULL) cmsDeleteContext(cpy);
if (cpy2 != NULL) cmsDeleteContext(cpy2);
return 0;
}
#define TYPE_RGB_565 (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(0) | (1 << 23))
cmsUInt8Number* my_Unroll565(register struct _cmstransform_struct* nfo,
register cmsUInt16Number wIn[],
register cmsUInt8Number* accum,
register cmsUInt32Number Stride)
{
cmsUInt16Number pixel = *(cmsUInt16Number*) accum;
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(register _cmsTRANSFORM* info,
register cmsUInt16Number wOut[],
register cmsUInt8Number* output,
register cmsUInt32Number Stride)
{
register 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(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(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,
cmsPluginFormattersSig,
NULL},
my_FormatterFactory };
static
cmsPluginFormatters FormattersPluginSample2 = { {cmsPluginMagicNumber,
2060,
cmsPluginFormattersSig,
NULL},
my_FormatterFactory2 };
cmsInt32Number CheckFormattersPlugin(void)
{
cmsContext ctx = WatchDogContext(NULL);
cmsContext cpy;
cmsContext cpy2;
cmsHTRANSFORM xform;
cmsUInt16Number stream[]= { 0xffffU, 0x1234U, 0x0000U, 0x33ddU };
cmsUInt16Number result[4];
int i;
cmsPluginTHR(ctx, &FormattersPluginSample);
cpy = DupContext(ctx, NULL);
cmsPluginTHR(cpy, &FormattersPluginSample2);
cpy2 = DupContext(cpy, NULL);
xform = cmsCreateTransformTHR(cpy2, NULL, TYPE_RGB_565, NULL, TYPE_RGB_565, INTENT_PERCEPTUAL, cmsFLAGS_NULLTRANSFORM);
cmsDoTransform(xform, stream, result, 4);
cmsDeleteTransform(xform);
cmsDeleteContext(ctx);
cmsDeleteContext(cpy);
cmsDeleteContext(cpy2);
for (i=0; i < 4; i++)
if (stream[i] != result[i]) return 0;
return 1;
}
#define SigIntType ((cmsTagTypeSignature) 0x74747448)
#define SigInt ((cmsTagSignature) 0x74747448)
static
void *Type_int_Read(struct _cms_typehandler_struct* self,
cmsIOHANDLER* io,
cmsUInt32Number* nItems,
cmsUInt32Number SizeOfTag)
{
cmsUInt32Number* Ptr = (cmsUInt32Number*) _cmsMalloc(self ->ContextID, sizeof(cmsUInt32Number));
if (Ptr == NULL) return NULL;
if (!_cmsReadUInt32Number(io, Ptr)) return NULL;
*nItems = 1;
return Ptr;
}
static
cmsBool Type_int_Write(struct _cms_typehandler_struct* self,
cmsIOHANDLER* io,
void* Ptr, cmsUInt32Number nItems)
{
return _cmsWriteUInt32Number(io, *(cmsUInt32Number*) Ptr);
}
static
void* Type_int_Dup(struct _cms_typehandler_struct* self,
const void *Ptr, cmsUInt32Number n)
{
return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsUInt32Number));
}
void Type_int_Free(struct _cms_typehandler_struct* self,
void* Ptr)
{
_cmsFree(self ->ContextID, Ptr);
}
static cmsPluginTag HiddenTagPluginSample = {
{ cmsPluginMagicNumber, 2060, cmsPluginTagSig, NULL},
SigInt, { 1, 1, { SigIntType }, NULL }
};
static cmsPluginTagType TagTypePluginSample = {
{ cmsPluginMagicNumber, 2060, cmsPluginTagTypeSig, (cmsPluginBase*) &HiddenTagPluginSample},
{ SigIntType, Type_int_Read, Type_int_Write, Type_int_Dup, Type_int_Free, NULL }
};
cmsInt32Number CheckTagTypePlugin(void)
{
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);
cmsPluginTHR(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(h, SigInt, &myTag)) {
Fail("Plug-in failed");
goto Error;
}
rc = cmsSaveProfileToMem(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(h, data, &clen);
if (!rc) {
Fail("Save to mem failed");
goto Error;
}
cmsCloseProfile(h);
cmsSetLogErrorHandler(NULL);
h = cmsOpenProfileFromMem(data, clen);
if (h == NULL) {
Fail("Open profile failed");
goto Error;
}
ptr = (cmsUInt32Number*) cmsReadTag(h, SigInt);
if (ptr != NULL) {
Fail("read tag/context switching failed");
goto Error;
}
cmsCloseProfile(h);
ResetFatalError();
h = cmsOpenProfileFromMemTHR(cpy2, data, clen);
if (h == NULL) {
Fail("Open profile from mem failed");
goto Error;
}
free(data); data = NULL;
ptr = (cmsUInt32Number*) cmsReadTag(h, SigInt);
if (ptr == NULL) {
Fail("Read tag/conext switching failed (2)");
return 0;
}
rc = (*ptr == 1234);
cmsCloseProfile(h);
cmsDeleteContext(cpy2);
return rc;
Error:
if (h != NULL) cmsCloseProfile(h);
if (ctx != NULL) cmsDeleteContext(ctx);
if (cpy != NULL) cmsDeleteContext(cpy);
if (cpy2 != NULL) cmsDeleteContext(cpy2);
if (data) free(data);
return 0;
}
#define SigNegateType ((cmsStageSignature)0x6E202020)
static
void EvaluateNegate(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(struct _cms_typehandler_struct* self,
cmsIOHANDLER* io,
cmsUInt32Number* nItems,
cmsUInt32Number SizeOfTag)
{
cmsUInt16Number Chans;
if (!_cmsReadUInt16Number(io, &Chans)) return NULL;
if (Chans != 3) return NULL;
*nItems = 1;
return StageAllocNegate(self -> ContextID);
}
static
cmsBool Type_negate_Write(struct _cms_typehandler_struct* self,
cmsIOHANDLER* io,
void* Ptr, cmsUInt32Number nItems)
{
if (!_cmsWriteUInt16Number(io, 3)) return FALSE;
return TRUE;
}
static
cmsPluginMultiProcessElement MPEPluginSample = {
{cmsPluginMagicNumber, 2060, cmsPluginMultiProcessElementSig, NULL},
{ (cmsTagTypeSignature) SigNegateType, Type_negate_Read, Type_negate_Write, NULL, NULL, NULL }
};
cmsInt32Number CheckMPEPlugin(void)
{
cmsContext ctx = NULL;
cmsContext cpy = NULL;
cmsContext cpy2 = NULL;
cmsHPROFILE h = NULL;
cmsUInt32Number myTag = 1234;
cmsUInt32Number rc = 0;
char* data = NULL;
cmsUInt32Number clen = 0;
cmsFloat32Number In[3], Out[3];
cmsPipeline* pipe;
ctx = WatchDogContext(NULL);
cmsPluginTHR(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(pipe, cmsAT_BEGIN, StageAllocNegate(cpy2));
In[0] = 0.3f; In[1] = 0.2f; In[2] = 0.9f;
cmsPipelineEvalFloat(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(h, cmsSigDToB3Tag, pipe)) {
Fail("Plug-in failed");
goto Error;
}
cmsPipelineFree(pipe);
rc = cmsSaveProfileToMem(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(h, data, &clen);
if (!rc) {
Fail("Save to mem failed");
goto Error;
}
cmsCloseProfile(h);
cmsSetLogErrorHandler(NULL);
h = cmsOpenProfileFromMem(data, clen);
if (h == NULL) {
Fail("Open profile failed");
goto Error;
}
pipe = (cmsPipeline*) cmsReadTag(h, cmsSigDToB3Tag);
if (pipe != NULL) {
Fail("read tag/context switching failed");
goto Error;
}
cmsCloseProfile(h);
ResetFatalError();
h = cmsOpenProfileFromMemTHR(cpy2, data, clen);
if (h == NULL) {
Fail("Open profile from mem failed");
goto Error;
}
free(data); data = NULL;
pipe = (cmsPipeline*) cmsReadTag(h, cmsSigDToB3Tag);
if (pipe == NULL) {
Fail("Read tag/conext switching failed (2)");
return 0;
}
In[0] = 0.3f; In[1] = 0.2f; In[2] = 0.9f;
cmsPipelineEvalFloat(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(h);
cmsDeleteContext(cpy2);
return rc;
Error:
if (h != NULL) cmsCloseProfile(h);
if (ctx != NULL) cmsDeleteContext(ctx);
if (cpy != NULL) cmsDeleteContext(cpy);
if (cpy2 != NULL) cmsDeleteContext(cpy2);
if (data) free(data);
return 0;
}
static
void FastEvaluateCurves(register const cmsUInt16Number In[],
register cmsUInt16Number Out[],
register const void* Data)
{
Out[0] = In[0];
}
static
cmsBool MyOptimize(cmsPipeline** Lut,
cmsUInt32Number Intent,
cmsUInt32Number* InputFormat,
cmsUInt32Number* OutputFormat,
cmsUInt32Number* dwFlags)
{
cmsStage* mpe;
_cmsStageToneCurvesData* Data;
for (mpe = cmsPipelineGetPtrToFirstStage(*Lut);
mpe != NULL;
mpe = cmsStageNext(mpe)) {
if (cmsStageType(mpe) != cmsSigCurveSetElemType) return FALSE;
Data = (_cmsStageToneCurvesData*) cmsStageData(mpe);
if (Data ->nCurves != 1) return FALSE;
if (cmsEstimateGamma(Data->TheCurves[0], 0.1) > 1.0) return FALSE;
}
*dwFlags |= cmsFLAGS_NOCACHE;
_cmsPipelineSetOptimizationParameters(*Lut, FastEvaluateCurves, NULL, NULL, NULL);
return TRUE;
}
cmsPluginOptimization OptimizationPluginSample = {
{cmsPluginMagicNumber, 2060, cmsPluginOptimizationSig, NULL},
MyOptimize
};
cmsInt32Number CheckOptimizationPlugin(void)
{
cmsContext ctx = WatchDogContext(NULL);
cmsContext cpy;
cmsContext cpy2;
cmsHTRANSFORM xform;
cmsUInt8Number In[]= { 10, 20, 30, 40 };
cmsUInt8Number Out[4];
cmsToneCurve* Linear[1];
cmsHPROFILE h;
int i;
cmsPluginTHR(ctx, &OptimizationPluginSample);
cpy = DupContext(ctx, NULL);
cpy2 = DupContext(cpy, NULL);
Linear[0] = cmsBuildGamma(cpy2, 1.0);
h = cmsCreateLinearizationDeviceLinkTHR(cpy2, cmsSigGrayData, Linear);
cmsFreeToneCurve(Linear[0]);
xform = cmsCreateTransformTHR(cpy2, h, TYPE_GRAY_8, h, TYPE_GRAY_8, INTENT_PERCEPTUAL, 0);
cmsCloseProfile(h);
cmsDoTransform(xform, In, Out, 4);
cmsDeleteTransform(xform);
cmsDeleteContext(ctx);
cmsDeleteContext(cpy);
cmsDeleteContext(cpy2);
for (i=0; i < 4; i++)
if (In[i] != Out[i]) return 0;
return 1;
}
#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(hProfiles[0]) != cmsSigGrayData ||
cmsGetColorSpace(hProfiles[nProfiles-1]) != cmsSigGrayData)
return _cmsDefaultICCintents(ContextID, nProfiles,
ICCIntents, hProfiles,
BPC, AdaptationStates,
dwFlags);
Result = cmsPipelineAlloc(ContextID, 1, 1);
if (Result == NULL) return NULL;
cmsPipelineInsertStage(Result, cmsAT_BEGIN,
cmsStageAllocIdentity(ContextID, 1));
return Result;
}
static cmsPluginRenderingIntent IntentPluginSample = {
{cmsPluginMagicNumber, 2060, cmsPluginRenderingIntentSig, NULL},
INTENT_DECEPTIVE, MyNewIntent, "bypass gray to gray rendering intent"
};
cmsInt32Number CheckIntentPlugin(void)
{
cmsContext ctx = WatchDogContext(NULL);
cmsContext cpy;
cmsContext cpy2;
cmsHTRANSFORM xform;
cmsHPROFILE h1, h2;
cmsToneCurve* Linear1;
cmsToneCurve* Linear2;
cmsUInt8Number In[]= { 10, 20, 30, 40 };
cmsUInt8Number Out[4];
int i;
cmsPluginTHR(ctx, &IntentPluginSample);
cpy = DupContext(ctx, NULL);
cpy2 = DupContext(cpy, NULL);
Linear1 = cmsBuildGamma(cpy2, 3.0);
Linear2 = cmsBuildGamma(cpy2, 0.1);
h1 = cmsCreateLinearizationDeviceLinkTHR(cpy2, cmsSigGrayData, &Linear1);
h2 = cmsCreateLinearizationDeviceLinkTHR(cpy2, cmsSigGrayData, &Linear2);
cmsFreeToneCurve(Linear1);
cmsFreeToneCurve(Linear2);
xform = cmsCreateTransformTHR(cpy2, h1, TYPE_GRAY_8, h2, TYPE_GRAY_8, INTENT_DECEPTIVE, 0);
cmsCloseProfile(h1); cmsCloseProfile(h2);
cmsDoTransform(xform, In, Out, 4);
cmsDeleteTransform(xform);
cmsDeleteContext(ctx);
cmsDeleteContext(cpy);
cmsDeleteContext(cpy2);
for (i=0; i < 4; i++)
if (Out[i] != In[i]) return 0;
return 1;
}
static
void TrancendentalTransform(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(_cmsTransformFn* xformPtr,
void** UserData,
_cmsFreeUserDataFn* FreePrivateDataFn,
cmsPipeline** Lut,
cmsUInt32Number* InputFormat,
cmsUInt32Number* OutputFormat,
cmsUInt32Number* dwFlags)
{
if (*OutputFormat == TYPE_GRAY_8)
{
*xformPtr = TrancendentalTransform;
return TRUE;
}
return FALSE;
}
static cmsPluginTransform FullTransformPluginSample = {
{ cmsPluginMagicNumber, 2060, cmsPluginTransformSig, NULL},
TransformFactory
};
cmsInt32Number CheckTransformPlugin(void)
{
cmsContext ctx = WatchDogContext(NULL);
cmsContext cpy;
cmsContext cpy2;
cmsHTRANSFORM xform;
cmsUInt8Number In[]= { 10, 20, 30, 40 };
cmsUInt8Number Out[4];
cmsToneCurve* Linear;
cmsHPROFILE h;
int i;
cmsPluginTHR(ctx, &FullTransformPluginSample);
cpy = DupContext(ctx, NULL);
cpy2 = DupContext(cpy, NULL);
Linear = cmsBuildGamma(cpy2, 1.0);
h = cmsCreateLinearizationDeviceLinkTHR(cpy2, cmsSigGrayData, &Linear);
cmsFreeToneCurve(Linear);
xform = cmsCreateTransformTHR(cpy2, h, TYPE_GRAY_8, h, TYPE_GRAY_8, INTENT_PERCEPTUAL, 0);
cmsCloseProfile(h);
cmsDoTransform(xform, In, Out, 4);
cmsDeleteTransform(xform);
cmsDeleteContext(ctx);
cmsDeleteContext(cpy);
cmsDeleteContext(cpy2);
for (i=0; i < 4; i++)
if (Out[i] != 0x42) return 0;
return 1;
}
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(void)
{
cmsContext ctx = WatchDogContext(NULL);
cmsContext cpy;
cmsContext cpy2;
cmsHTRANSFORM xform;
cmsUInt8Number In[]= { 10, 20, 30, 40 };
cmsUInt8Number Out[4];
cmsToneCurve* Linear;
cmsHPROFILE h;
int i;
cmsPluginTHR(ctx, &MutexPluginSample);
cpy = DupContext(ctx, NULL);
cpy2 = DupContext(cpy, NULL);
Linear = cmsBuildGamma(cpy2, 1.0);
h = cmsCreateLinearizationDeviceLinkTHR(cpy2, cmsSigGrayData, &Linear);
cmsFreeToneCurve(Linear);
xform = cmsCreateTransformTHR(cpy2, h, TYPE_GRAY_8, h, TYPE_GRAY_8, INTENT_PERCEPTUAL, 0);
cmsCloseProfile(h);
cmsDoTransform(xform, In, Out, 4);
cmsDeleteTransform(xform);
cmsDeleteContext(ctx);
cmsDeleteContext(cpy);
cmsDeleteContext(cpy2);
for (i=0; i < 4; i++)
if (Out[i] != In[i]) return 0;
return 1;
}