123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644 |
- /*
- * pyCMS
- * a Python / PIL interface to the littleCMS ICC Color Management System
- * Copyright (C) 2002-2003 Kevin Cazabon
- * kevin@cazabon.com
- * http://www.cazabon.com
- * Adapted/reworked for PIL by Fredrik Lundh
- * Copyright (c) 2009 Fredrik Lundh
- * Updated to LCMS2
- * Copyright (c) 2013 Eric Soroos
- *
- * pyCMS home page: http://www.cazabon.com/pyCMS
- * littleCMS home page: http://www.littlecms.com
- * (littleCMS is Copyright (C) 1998-2001 Marti Maria)
- *
- * Originally released under LGPL. Graciously donated to PIL in
- * March 2009, for distribution under the standard PIL license
- */
- #define COPYRIGHTINFO "\
- pyCMS\n\
- a Python / PIL interface to the littleCMS ICC Color Management System\n\
- Copyright (C) 2002-2003 Kevin Cazabon\n\
- kevin@cazabon.com\n\
- http://www.cazabon.com\n\
- "
- #define PY_SSIZE_T_CLEAN
- #include "Python.h" // Include before wchar.h so _GNU_SOURCE is set
- #include "wchar.h"
- #include "datetime.h"
- #include "lcms2.h"
- #include "Imaging.h"
- #include "py3.h"
- #define PYCMSVERSION "1.0.0 pil"
- /* version history */
- /*
- 1.0.0 pil Integrating littleCMS2
- 0.1.0 pil integration & refactoring
- 0.0.2 alpha: Minor updates, added interfaces to littleCMS features, Jan 6, 2003
- - fixed some memory holes in how transforms/profiles were created and passed back to Python
- due to improper destructor setup for PyCObjects
- - added buildProofTransformFromOpenProfiles() function
- - eliminated some code redundancy, centralizing several common tasks with internal functions
- 0.0.1 alpha: First public release Dec 26, 2002
- */
- /* known to-do list with current version:
- Verify that PILmode->littleCMStype conversion in findLCMStype is correct for all
- PIL modes (it probably isn't for the more obscure ones)
- Add support for creating custom RGB profiles on the fly
- Add support for checking presence of a specific tag in a profile
- Add support for other littleCMS features as required
- */
- /*
- INTENT_PERCEPTUAL 0
- INTENT_RELATIVE_COLORIMETRIC 1
- INTENT_SATURATION 2
- INTENT_ABSOLUTE_COLORIMETRIC 3
- */
- /* -------------------------------------------------------------------- */
- /* wrapper classes */
- /* a profile represents the ICC characteristics for a specific device */
- typedef struct {
- PyObject_HEAD
- cmsHPROFILE profile;
- } CmsProfileObject;
- static PyTypeObject CmsProfile_Type;
- #define CmsProfile_Check(op) (Py_TYPE(op) == &CmsProfile_Type)
- static PyObject*
- cms_profile_new(cmsHPROFILE profile)
- {
- CmsProfileObject* self;
- self = PyObject_New(CmsProfileObject, &CmsProfile_Type);
- if (!self)
- return NULL;
- self->profile = profile;
- return (PyObject*) self;
- }
- static PyObject*
- cms_profile_open(PyObject* self, PyObject* args)
- {
- cmsHPROFILE hProfile;
- char* sProfile;
- if (!PyArg_ParseTuple(args, "s:profile_open", &sProfile))
- return NULL;
- hProfile = cmsOpenProfileFromFile(sProfile, "r");
- if (!hProfile) {
- PyErr_SetString(PyExc_IOError, "cannot open profile file");
- return NULL;
- }
- return cms_profile_new(hProfile);
- }
- static PyObject*
- cms_profile_fromstring(PyObject* self, PyObject* args)
- {
- cmsHPROFILE hProfile;
- char* pProfile;
- Py_ssize_t nProfile;
- #if PY_VERSION_HEX >= 0x03000000
- if (!PyArg_ParseTuple(args, "y#:profile_frombytes", &pProfile, &nProfile))
- return NULL;
- #else
- if (!PyArg_ParseTuple(args, "s#:profile_fromstring", &pProfile, &nProfile))
- return NULL;
- #endif
- hProfile = cmsOpenProfileFromMem(pProfile, nProfile);
- if (!hProfile) {
- PyErr_SetString(PyExc_IOError, "cannot open profile from string");
- return NULL;
- }
- return cms_profile_new(hProfile);
- }
- static PyObject*
- cms_profile_tobytes(PyObject* self, PyObject* args)
- {
- char *pProfile =NULL;
- cmsUInt32Number nProfile;
- PyObject* CmsProfile;
- cmsHPROFILE *profile;
- PyObject* ret;
- if (!PyArg_ParseTuple(args, "O", &CmsProfile)){
- return NULL;
- }
- profile = ((CmsProfileObject*)CmsProfile)->profile;
- if (!cmsSaveProfileToMem(profile, pProfile, &nProfile)) {
- PyErr_SetString(PyExc_IOError, "Could not determine profile size");
- return NULL;
- }
- pProfile = (char*)malloc(nProfile);
- if (!pProfile) {
- PyErr_SetString(PyExc_IOError, "Out of Memory");
- return NULL;
- }
- if (!cmsSaveProfileToMem(profile, pProfile, &nProfile)) {
- PyErr_SetString(PyExc_IOError, "Could not get profile");
- free(pProfile);
- return NULL;
- }
- #if PY_VERSION_HEX >= 0x03000000
- ret = PyBytes_FromStringAndSize(pProfile, (Py_ssize_t)nProfile);
- #else
- ret = PyString_FromStringAndSize(pProfile, (Py_ssize_t)nProfile);
- #endif
- free(pProfile);
- return ret;
- }
- static void
- cms_profile_dealloc(CmsProfileObject* self)
- {
- (void) cmsCloseProfile(self->profile);
- PyObject_Del(self);
- }
- /* a transform represents the mapping between two profiles */
- typedef struct {
- PyObject_HEAD
- char mode_in[8];
- char mode_out[8];
- cmsHTRANSFORM transform;
- } CmsTransformObject;
- static PyTypeObject CmsTransform_Type;
- #define CmsTransform_Check(op) (Py_TYPE(op) == &CmsTransform_Type)
- static PyObject*
- cms_transform_new(cmsHTRANSFORM transform, char* mode_in, char* mode_out)
- {
- CmsTransformObject* self;
- self = PyObject_New(CmsTransformObject, &CmsTransform_Type);
- if (!self)
- return NULL;
- self->transform = transform;
- strcpy(self->mode_in, mode_in);
- strcpy(self->mode_out, mode_out);
- return (PyObject*) self;
- }
- static void
- cms_transform_dealloc(CmsTransformObject* self)
- {
- cmsDeleteTransform(self->transform);
- PyObject_Del(self);
- }
- /* -------------------------------------------------------------------- */
- /* internal functions */
- static const char*
- findICmode(cmsColorSpaceSignature cs)
- {
- switch (cs) {
- case cmsSigXYZData: return "XYZ";
- case cmsSigLabData: return "LAB";
- case cmsSigLuvData: return "LUV";
- case cmsSigYCbCrData: return "YCbCr";
- case cmsSigYxyData: return "YXY";
- case cmsSigRgbData: return "RGB";
- case cmsSigGrayData: return "L";
- case cmsSigHsvData: return "HSV";
- case cmsSigHlsData: return "HLS";
- case cmsSigCmykData: return "CMYK";
- case cmsSigCmyData: return "CMY";
- default: return ""; /* other TBA */
- }
- }
- static cmsUInt32Number
- findLCMStype(char* PILmode)
- {
- if (strcmp(PILmode, "RGB") == 0) {
- return TYPE_RGBA_8;
- }
- else if (strcmp(PILmode, "RGBA") == 0) {
- return TYPE_RGBA_8;
- }
- else if (strcmp(PILmode, "RGBX") == 0) {
- return TYPE_RGBA_8;
- }
- else if (strcmp(PILmode, "RGBA;16B") == 0) {
- return TYPE_RGBA_16;
- }
- else if (strcmp(PILmode, "CMYK") == 0) {
- return TYPE_CMYK_8;
- }
- else if (strcmp(PILmode, "L") == 0) {
- return TYPE_GRAY_8;
- }
- else if (strcmp(PILmode, "L;16") == 0) {
- return TYPE_GRAY_16;
- }
- else if (strcmp(PILmode, "L;16B") == 0) {
- return TYPE_GRAY_16_SE;
- }
- else if (strcmp(PILmode, "YCCA") == 0) {
- return TYPE_YCbCr_8;
- }
- else if (strcmp(PILmode, "YCC") == 0) {
- return TYPE_YCbCr_8;
- }
- else if (strcmp(PILmode, "LAB") == 0) {
- // LabX equivalent like ALab, but not reversed -- no #define in lcms2
- return (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1));
- }
- else {
- /* take a wild guess... but you probably should fail instead. */
- return TYPE_GRAY_8; /* so there's no buffer overrun... */
- }
- }
- #define Cms_Min(a, b) ((a) < (b) ? (a) : (b))
- static int
- pyCMSgetAuxChannelChannel (cmsUInt32Number format, int auxChannelNdx)
- {
- int numColors = T_CHANNELS(format);
- int numExtras = T_EXTRA(format);
- if (T_SWAPFIRST(format) && T_DOSWAP(format)) {
- // reverse order, before anything but last extra is shifted last
- if (auxChannelNdx == numExtras - 1)
- return numColors + numExtras - 1;
- else
- return numExtras - 2 - auxChannelNdx;
- }
- else if (T_SWAPFIRST(format)) {
- // in order, after color channels, but last extra is shifted to first
- if (auxChannelNdx == numExtras - 1)
- return 0;
- else
- return numColors + 1 + auxChannelNdx;
- }
- else if (T_DOSWAP(format)) {
- // reverse order, before anything
- return numExtras - 1 - auxChannelNdx;
- }
- else {
- // in order, after color channels
- return numColors + auxChannelNdx;
- }
- }
- static void
- pyCMScopyAux (cmsHTRANSFORM hTransform, Imaging imDst, const Imaging imSrc)
- {
- cmsUInt32Number dstLCMSFormat;
- cmsUInt32Number srcLCMSFormat;
- int numSrcExtras;
- int numDstExtras;
- int numExtras;
- int ySize;
- int xSize;
- int channelSize;
- int srcChunkSize;
- int dstChunkSize;
- int e;
- // trivially copied
- if (imDst == imSrc)
- return;
- dstLCMSFormat = cmsGetTransformOutputFormat(hTransform);
- srcLCMSFormat = cmsGetTransformInputFormat(hTransform);
- // currently, all Pillow formats are chunky formats, but check it anyway
- if (T_PLANAR(dstLCMSFormat) || T_PLANAR(srcLCMSFormat))
- return;
- // copy only if channel format is identical, except OPTIMIZED is ignored as it
- // does not affect the aux channel
- if (T_FLOAT(dstLCMSFormat) != T_FLOAT(srcLCMSFormat)
- || T_FLAVOR(dstLCMSFormat) != T_FLAVOR(srcLCMSFormat)
- || T_ENDIAN16(dstLCMSFormat) != T_ENDIAN16(srcLCMSFormat)
- || T_BYTES(dstLCMSFormat) != T_BYTES(srcLCMSFormat))
- return;
- numSrcExtras = T_EXTRA(srcLCMSFormat);
- numDstExtras = T_EXTRA(dstLCMSFormat);
- numExtras = Cms_Min(numSrcExtras, numDstExtras);
- ySize = Cms_Min(imSrc->ysize, imDst->ysize);
- xSize = Cms_Min(imSrc->xsize, imDst->xsize);
- channelSize = T_BYTES(dstLCMSFormat);
- srcChunkSize = (T_CHANNELS(srcLCMSFormat) + T_EXTRA(srcLCMSFormat)) * channelSize;
- dstChunkSize = (T_CHANNELS(dstLCMSFormat) + T_EXTRA(dstLCMSFormat)) * channelSize;
- for (e = 0; e < numExtras; ++e) {
- int y;
- int dstChannel = pyCMSgetAuxChannelChannel(dstLCMSFormat, e);
- int srcChannel = pyCMSgetAuxChannelChannel(srcLCMSFormat, e);
- for (y = 0; y < ySize; y++) {
- int x;
- char* pDstExtras = imDst->image[y] + dstChannel * channelSize;
- const char* pSrcExtras = imSrc->image[y] + srcChannel * channelSize;
- for (x = 0; x < xSize; x++)
- memcpy(pDstExtras + x * dstChunkSize, pSrcExtras + x * srcChunkSize, channelSize);
- }
- }
- }
- static int
- pyCMSdoTransform(Imaging im, Imaging imOut, cmsHTRANSFORM hTransform)
- {
- int i;
- if (im->xsize > imOut->xsize || im->ysize > imOut->ysize)
- return -1;
- Py_BEGIN_ALLOW_THREADS
- // transform color channels only
- for (i = 0; i < im->ysize; i++)
- cmsDoTransform(hTransform, im->image[i], imOut->image[i], im->xsize);
- // lcms by default does nothing to the auxiliary channels leaving those
- // unchanged. To do "the right thing" here, i.e. maintain identical results
- // with and without inPlace, we replicate those channels to the output.
- //
- // As of lcms 2.8, a new cmsFLAGS_COPY_ALPHA flag is introduced which would
- // do the same thing automagically. Unfortunately, lcms2.8 is not yet widely
- // enough available on all platforms, so we polyfill it here for now.
- pyCMScopyAux(hTransform, imOut, im);
- Py_END_ALLOW_THREADS
- return 0;
- }
- static cmsHTRANSFORM
- _buildTransform(cmsHPROFILE hInputProfile, cmsHPROFILE hOutputProfile, char *sInMode, char *sOutMode, int iRenderingIntent, cmsUInt32Number cmsFLAGS)
- {
- cmsHTRANSFORM hTransform;
- Py_BEGIN_ALLOW_THREADS
- /* create the transform */
- hTransform = cmsCreateTransform(hInputProfile,
- findLCMStype(sInMode),
- hOutputProfile,
- findLCMStype(sOutMode),
- iRenderingIntent, cmsFLAGS);
- Py_END_ALLOW_THREADS
- if (!hTransform)
- PyErr_SetString(PyExc_ValueError, "cannot build transform");
- return hTransform; /* if NULL, an exception is set */
- }
- static cmsHTRANSFORM
- _buildProofTransform(cmsHPROFILE hInputProfile, cmsHPROFILE hOutputProfile, cmsHPROFILE hProofProfile, char *sInMode, char *sOutMode, int iRenderingIntent, int iProofIntent, cmsUInt32Number cmsFLAGS)
- {
- cmsHTRANSFORM hTransform;
- Py_BEGIN_ALLOW_THREADS
- /* create the transform */
- hTransform = cmsCreateProofingTransform(hInputProfile,
- findLCMStype(sInMode),
- hOutputProfile,
- findLCMStype(sOutMode),
- hProofProfile,
- iRenderingIntent,
- iProofIntent,
- cmsFLAGS);
- Py_END_ALLOW_THREADS
- if (!hTransform)
- PyErr_SetString(PyExc_ValueError, "cannot build proof transform");
- return hTransform; /* if NULL, an exception is set */
- }
- /* -------------------------------------------------------------------- */
- /* Python callable functions */
- static PyObject *
- buildTransform(PyObject *self, PyObject *args) {
- CmsProfileObject *pInputProfile;
- CmsProfileObject *pOutputProfile;
- char *sInMode;
- char *sOutMode;
- int iRenderingIntent = 0;
- int cmsFLAGS = 0;
- cmsHTRANSFORM transform = NULL;
- if (!PyArg_ParseTuple(args, "O!O!ss|ii:buildTransform", &CmsProfile_Type, &pInputProfile, &CmsProfile_Type, &pOutputProfile, &sInMode, &sOutMode, &iRenderingIntent, &cmsFLAGS))
- return NULL;
- transform = _buildTransform(pInputProfile->profile, pOutputProfile->profile, sInMode, sOutMode, iRenderingIntent, cmsFLAGS);
- if (!transform)
- return NULL;
- return cms_transform_new(transform, sInMode, sOutMode);
- }
- static PyObject *
- buildProofTransform(PyObject *self, PyObject *args)
- {
- CmsProfileObject *pInputProfile;
- CmsProfileObject *pOutputProfile;
- CmsProfileObject *pProofProfile;
- char *sInMode;
- char *sOutMode;
- int iRenderingIntent = 0;
- int iProofIntent = 0;
- int cmsFLAGS = 0;
- cmsHTRANSFORM transform = NULL;
- if (!PyArg_ParseTuple(args, "O!O!O!ss|iii:buildProofTransform", &CmsProfile_Type, &pInputProfile, &CmsProfile_Type, &pOutputProfile, &CmsProfile_Type, &pProofProfile, &sInMode, &sOutMode, &iRenderingIntent, &iProofIntent, &cmsFLAGS))
- return NULL;
- transform = _buildProofTransform(pInputProfile->profile, pOutputProfile->profile, pProofProfile->profile, sInMode, sOutMode, iRenderingIntent, iProofIntent, cmsFLAGS);
- if (!transform)
- return NULL;
- return cms_transform_new(transform, sInMode, sOutMode);
- }
- static PyObject *
- cms_transform_apply(CmsTransformObject *self, PyObject *args)
- {
- Py_ssize_t idIn;
- Py_ssize_t idOut;
- Imaging im;
- Imaging imOut;
- int result;
- if (!PyArg_ParseTuple(args, "nn:apply", &idIn, &idOut))
- return NULL;
- im = (Imaging) idIn;
- imOut = (Imaging) idOut;
- result = pyCMSdoTransform(im, imOut, self->transform);
- return Py_BuildValue("i", result);
- }
- /* -------------------------------------------------------------------- */
- /* Python-Callable On-The-Fly profile creation functions */
- static PyObject *
- createProfile(PyObject *self, PyObject *args)
- {
- char *sColorSpace;
- cmsHPROFILE hProfile;
- cmsFloat64Number dColorTemp = 0.0;
- cmsCIExyY whitePoint;
- cmsBool result;
- if (!PyArg_ParseTuple(args, "s|d:createProfile", &sColorSpace, &dColorTemp))
- return NULL;
- if (strcmp(sColorSpace, "LAB") == 0) {
- if (dColorTemp > 0.0) {
- result = cmsWhitePointFromTemp(&whitePoint, dColorTemp);
- if (!result) {
- PyErr_SetString(PyExc_ValueError, "ERROR: Could not calculate white point from color temperature provided, must be float in degrees Kelvin");
- return NULL;
- }
- hProfile = cmsCreateLab2Profile(&whitePoint);
- } else {
- hProfile = cmsCreateLab2Profile(NULL);
- }
- }
- else if (strcmp(sColorSpace, "XYZ") == 0) {
- hProfile = cmsCreateXYZProfile();
- }
- else if (strcmp(sColorSpace, "sRGB") == 0) {
- hProfile = cmsCreate_sRGBProfile();
- }
- else {
- hProfile = NULL;
- }
- if (!hProfile) {
- PyErr_SetString(PyExc_ValueError, "failed to create requested color space");
- return NULL;
- }
- return cms_profile_new(hProfile);
- }
- /* -------------------------------------------------------------------- */
- /* profile methods */
- static PyObject *
- cms_profile_is_intent_supported(CmsProfileObject *self, PyObject *args)
- {
- cmsBool result;
- int intent;
- int direction;
- if (!PyArg_ParseTuple(args, "ii:is_intent_supported", &intent, &direction))
- return NULL;
- result = cmsIsIntentSupported(self->profile, intent, direction);
- /* printf("cmsIsIntentSupported(%p, %d, %d) => %d\n", self->profile, intent, direction, result); */
- return PyInt_FromLong(result != 0);
- }
- #ifdef _WIN32
- #ifdef _WIN64
- #define F_HANDLE "K"
- #else
- #define F_HANDLE "k"
- #endif
- static PyObject *
- cms_get_display_profile_win32(PyObject* self, PyObject* args)
- {
- char filename[MAX_PATH];
- cmsUInt32Number filename_size;
- BOOL ok;
- HANDLE handle = 0;
- int is_dc = 0;
- if (!PyArg_ParseTuple(args, "|" F_HANDLE "i:get_display_profile", &handle, &is_dc))
- return NULL;
- filename_size = sizeof(filename);
- if (is_dc) {
- ok = GetICMProfile((HDC) handle, &filename_size, filename);
- } else {
- HDC dc = GetDC((HWND) handle);
- ok = GetICMProfile(dc, &filename_size, filename);
- ReleaseDC((HWND) handle, dc);
- }
- if (ok)
- return PyUnicode_FromStringAndSize(filename, filename_size-1);
- Py_INCREF(Py_None);
- return Py_None;
- }
- #endif
- /* -------------------------------------------------------------------- */
- /* Helper functions. */
- static PyObject*
- _profile_read_mlu(CmsProfileObject* self, cmsTagSignature info)
- {
- PyObject *uni;
- char *lc = "en";
- char *cc = cmsNoCountry;
- cmsMLU *mlu;
- cmsUInt32Number len;
- wchar_t *buf;
- if (!cmsIsTag(self->profile, info)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- mlu = cmsReadTag(self->profile, info);
- if (!mlu) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- len = cmsMLUgetWide(mlu, lc, cc, NULL, 0);
- if (len == 0) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- buf = malloc(len);
- if (!buf) {
- PyErr_SetString(PyExc_IOError, "Out of Memory");
- return NULL;
- }
- /* Just in case the next call fails. */
- buf[0] = '\0';
- cmsMLUgetWide(mlu, lc, cc, buf, len);
- // buf contains additional junk after \0
- uni = PyUnicode_FromWideChar(buf, wcslen(buf));
- free(buf);
- return uni;
- }
- static PyObject*
- _profile_read_int_as_string(cmsUInt32Number nr)
- {
- PyObject* ret;
- char buf[5];
- buf[0] = (char) ((nr >> 24) & 0xff);
- buf[1] = (char) ((nr >> 16) & 0xff);
- buf[2] = (char) ((nr >> 8) & 0xff);
- buf[3] = (char) (nr & 0xff);
- buf[4] = 0;
- #if PY_VERSION_HEX >= 0x03000000
- ret = PyUnicode_DecodeASCII(buf, 4, NULL);
- #else
- ret = PyString_FromStringAndSize(buf, 4);
- #endif
- return ret;
- }
- static PyObject*
- _profile_read_signature(CmsProfileObject* self, cmsTagSignature info)
- {
- unsigned int *sig;
- if (!cmsIsTag(self->profile, info)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- sig = (unsigned int *) cmsReadTag(self->profile, info);
- if (!sig) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return _profile_read_int_as_string(*sig);
- }
- static PyObject*
- _xyz_py(cmsCIEXYZ* XYZ)
- {
- cmsCIExyY xyY;
- cmsXYZ2xyY(&xyY, XYZ);
- return Py_BuildValue("((d,d,d),(d,d,d))", XYZ->X, XYZ->Y, XYZ->Z, xyY.x, xyY.y, xyY.Y);
- }
- static PyObject*
- _xyz3_py(cmsCIEXYZ* XYZ)
- {
- cmsCIExyY xyY[3];
- cmsXYZ2xyY(&xyY[0], &XYZ[0]);
- cmsXYZ2xyY(&xyY[1], &XYZ[1]);
- cmsXYZ2xyY(&xyY[2], &XYZ[2]);
- return Py_BuildValue("(((d,d,d),(d,d,d),(d,d,d)),((d,d,d),(d,d,d),(d,d,d)))",
- XYZ[0].X, XYZ[0].Y, XYZ[0].Z,
- XYZ[1].X, XYZ[1].Y, XYZ[1].Z,
- XYZ[2].X, XYZ[2].Y, XYZ[2].Z,
- xyY[0].x, xyY[0].y, xyY[0].Y,
- xyY[1].x, xyY[1].y, xyY[1].Y,
- xyY[2].x, xyY[2].y, xyY[2].Y);
- }
- static PyObject*
- _profile_read_ciexyz(CmsProfileObject* self, cmsTagSignature info, int multi)
- {
- cmsCIEXYZ* XYZ;
- if (!cmsIsTag(self->profile, info)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- XYZ = (cmsCIEXYZ*) cmsReadTag(self->profile, info);
- if (!XYZ) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- if (multi)
- return _xyz3_py(XYZ);
- else
- return _xyz_py(XYZ);
- }
- static PyObject*
- _profile_read_ciexyy_triple(CmsProfileObject* self, cmsTagSignature info)
- {
- cmsCIExyYTRIPLE* triple;
- if (!cmsIsTag(self->profile, info)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- triple = (cmsCIExyYTRIPLE*) cmsReadTag(self->profile, info);
- if (!triple) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- /* Note: lcms does all the heavy lifting and error checking (nr of
- channels == 3). */
- return Py_BuildValue("((d,d,d),(d,d,d),(d,d,d)),",
- triple->Red.x, triple->Red.y, triple->Red.Y,
- triple->Green.x, triple->Green.y, triple->Green.Y,
- triple->Blue.x, triple->Blue.y, triple->Blue.Y);
- }
- static PyObject*
- _profile_read_named_color_list(CmsProfileObject* self, cmsTagSignature info)
- {
- cmsNAMEDCOLORLIST* ncl;
- int i, n;
- char name[cmsMAX_PATH];
- PyObject* result;
- if (!cmsIsTag(self->profile, info)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- ncl = (cmsNAMEDCOLORLIST*) cmsReadTag(self->profile, info);
- if (ncl == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- n = cmsNamedColorCount(ncl);
- result = PyList_New(n);
- if (!result) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- for (i = 0; i < n; i++) {
- PyObject* str;
- cmsNamedColorInfo(ncl, i, name, NULL, NULL, NULL, NULL);
- str = PyUnicode_FromString(name);
- if (str == NULL) {
- Py_DECREF(result);
- Py_INCREF(Py_None);
- return Py_None;
- }
- PyList_SET_ITEM(result, i, str);
- }
- return result;
- }
- static cmsBool _calculate_rgb_primaries(CmsProfileObject* self, cmsCIEXYZTRIPLE* result)
- {
- double input[3][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
- cmsHPROFILE hXYZ;
- cmsHTRANSFORM hTransform;
- /* https://littlecms2.blogspot.com/2009/07/less-is-more.html */
- // double array of RGB values with max on each identity
- hXYZ = cmsCreateXYZProfile();
- if (hXYZ == NULL)
- return 0;
- // transform from our profile to XYZ using doubles for highest precision
- hTransform = cmsCreateTransform(self->profile, TYPE_RGB_DBL,
- hXYZ, TYPE_XYZ_DBL,
- INTENT_RELATIVE_COLORIMETRIC,
- cmsFLAGS_NOCACHE | cmsFLAGS_NOOPTIMIZE);
- cmsCloseProfile(hXYZ);
- if (hTransform == NULL)
- return 0;
- cmsDoTransform(hTransform, (void*) input, result, 3);
- cmsDeleteTransform(hTransform);
- return 1;
- }
- static cmsBool _check_intent(int clut, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number UsedDirection)
- {
- if (clut) {
- return cmsIsCLUT(hProfile, Intent, UsedDirection);
- }
- else {
- return cmsIsIntentSupported(hProfile, Intent, UsedDirection);
- }
- }
- #define INTENTS 200
- static PyObject*
- _is_intent_supported(CmsProfileObject* self, int clut)
- {
- PyObject* result;
- int n;
- int i;
- cmsUInt32Number intent_ids[INTENTS];
- char *intent_descs[INTENTS];
- result = PyDict_New();
- if (result == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- n = cmsGetSupportedIntents(INTENTS,
- intent_ids,
- intent_descs);
- for (i = 0; i < n; i++) {
- int intent = (int) intent_ids[i];
- PyObject* id;
- PyObject* entry;
- /* Only valid for ICC Intents (otherwise we read invalid memory in lcms cmsio1.c). */
- if (!(intent == INTENT_PERCEPTUAL || intent == INTENT_RELATIVE_COLORIMETRIC
- || intent == INTENT_SATURATION || intent == INTENT_ABSOLUTE_COLORIMETRIC))
- continue;
- id = PyInt_FromLong((long) intent);
- entry = Py_BuildValue("(OOO)",
- _check_intent(clut, self->profile, intent, LCMS_USED_AS_INPUT) ? Py_True : Py_False,
- _check_intent(clut, self->profile, intent, LCMS_USED_AS_OUTPUT) ? Py_True : Py_False,
- _check_intent(clut, self->profile, intent, LCMS_USED_AS_PROOF) ? Py_True : Py_False);
- if (id == NULL || entry == NULL) {
- Py_XDECREF(id);
- Py_XDECREF(entry);
- Py_XDECREF(result);
- Py_INCREF(Py_None);
- return Py_None;
- }
- PyDict_SetItem(result, id, entry);
- }
- return result;
- }
- /* -------------------------------------------------------------------- */
- /* Python interface setup */
- static PyMethodDef pyCMSdll_methods[] = {
- {"profile_open", cms_profile_open, 1},
- {"profile_frombytes", cms_profile_fromstring, 1},
- {"profile_fromstring", cms_profile_fromstring, 1},
- {"profile_tobytes", cms_profile_tobytes, 1},
- /* profile and transform functions */
- {"buildTransform", buildTransform, 1},
- {"buildProofTransform", buildProofTransform, 1},
- {"createProfile", createProfile, 1},
- /* platform specific tools */
- #ifdef _WIN32
- {"get_display_profile_win32", cms_get_display_profile_win32, 1},
- #endif
- {NULL, NULL}
- };
- static struct PyMethodDef cms_profile_methods[] = {
- {"is_intent_supported", (PyCFunction) cms_profile_is_intent_supported, 1},
- {NULL, NULL} /* sentinel */
- };
- static PyObject*
- _profile_getattr(CmsProfileObject* self, cmsInfoType field)
- {
- // UNDONE -- check that I'm getting the right fields on these.
- // return PyUnicode_DecodeFSDefault(cmsTakeProductName(self->profile));
- //wchar_t buf[256]; -- UNDONE need wchar_t for unicode version.
- char buf[256];
- cmsUInt32Number written;
- written = cmsGetProfileInfoASCII(self->profile,
- field,
- "en",
- "us",
- buf,
- 256);
- if (written) {
- return PyUnicode_FromString(buf);
- }
- // UNDONE suppressing error here by sending back blank string.
- return PyUnicode_FromString("");
- }
- static PyObject*
- cms_profile_getattr_product_desc(CmsProfileObject* self, void* closure)
- {
- PyErr_WarnEx(PyExc_DeprecationWarning,
- "product_desc is deprecated. Use Unicode profile_description instead.", 1);
- // description was Description != 'Copyright' || or "%s - %s" (manufacturer, model) in 1.x
- return _profile_getattr(self, cmsInfoDescription);
- }
- /* use these four for the individual fields.
- */
- static PyObject*
- cms_profile_getattr_product_description(CmsProfileObject* self, void* closure)
- {
- PyErr_WarnEx(PyExc_DeprecationWarning,
- "product_description is deprecated. Use Unicode profile_description instead.", 1);
- return _profile_getattr(self, cmsInfoDescription);
- }
- static PyObject*
- cms_profile_getattr_product_model(CmsProfileObject* self, void* closure)
- {
- PyErr_WarnEx(PyExc_DeprecationWarning,
- "product_model is deprecated. Use Unicode model instead.", 1);
- return _profile_getattr(self, cmsInfoModel);
- }
- static PyObject*
- cms_profile_getattr_product_manufacturer(CmsProfileObject* self, void* closure)
- {
- PyErr_WarnEx(PyExc_DeprecationWarning,
- "product_manufacturer is deprecated. Use Unicode manufacturer instead.", 1);
- return _profile_getattr(self, cmsInfoManufacturer);
- }
- static PyObject*
- cms_profile_getattr_product_copyright(CmsProfileObject* self, void* closure)
- {
- PyErr_WarnEx(PyExc_DeprecationWarning,
- "product_copyright is deprecated. Use Unicode copyright instead.", 1);
- return _profile_getattr(self, cmsInfoCopyright);
- }
- static PyObject*
- cms_profile_getattr_rendering_intent(CmsProfileObject* self, void* closure)
- {
- return PyInt_FromLong(cmsGetHeaderRenderingIntent(self->profile));
- }
- static PyObject*
- cms_profile_getattr_pcs(CmsProfileObject* self, void* closure)
- {
- PyErr_WarnEx(PyExc_DeprecationWarning,
- "pcs is deprecated. Use padded connection_space instead.", 1);
- return PyUnicode_DecodeFSDefault(findICmode(cmsGetPCS(self->profile)));
- }
- static PyObject*
- cms_profile_getattr_color_space(CmsProfileObject* self, void* closure)
- {
- PyErr_WarnEx(PyExc_DeprecationWarning,
- "color_space is deprecated. Use padded xcolor_space instead.", 1);
- return PyUnicode_DecodeFSDefault(findICmode(cmsGetColorSpace(self->profile)));
- }
- /* New-style unicode interfaces. */
- static PyObject*
- cms_profile_getattr_copyright(CmsProfileObject* self, void* closure)
- {
- return _profile_read_mlu(self, cmsSigCopyrightTag);
- }
- static PyObject*
- cms_profile_getattr_target(CmsProfileObject* self, void* closure)
- {
- return _profile_read_mlu(self, cmsSigCharTargetTag);
- }
- static PyObject*
- cms_profile_getattr_manufacturer(CmsProfileObject* self, void* closure)
- {
- return _profile_read_mlu(self, cmsSigDeviceMfgDescTag);
- }
- static PyObject*
- cms_profile_getattr_model(CmsProfileObject* self, void* closure)
- {
- return _profile_read_mlu(self, cmsSigDeviceModelDescTag);
- }
- static PyObject*
- cms_profile_getattr_profile_description(CmsProfileObject* self, void* closure)
- {
- return _profile_read_mlu(self, cmsSigProfileDescriptionTag);
- }
- static PyObject*
- cms_profile_getattr_screening_description(CmsProfileObject* self, void* closure)
- {
- return _profile_read_mlu(self, cmsSigScreeningDescTag);
- }
- static PyObject*
- cms_profile_getattr_viewing_condition(CmsProfileObject* self, void* closure)
- {
- return _profile_read_mlu(self, cmsSigViewingCondDescTag);
- }
- static PyObject*
- cms_profile_getattr_creation_date(CmsProfileObject* self, void* closure)
- {
- cmsBool result;
- struct tm ct;
- result = cmsGetHeaderCreationDateTime(self->profile, &ct);
- if (! result) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return PyDateTime_FromDateAndTime(1900 + ct.tm_year, ct.tm_mon, ct.tm_mday,
- ct.tm_hour, ct.tm_min, ct.tm_sec, 0);
- }
- static PyObject*
- cms_profile_getattr_version(CmsProfileObject* self, void* closure)
- {
- cmsFloat64Number version = cmsGetProfileVersion(self->profile);
- return PyFloat_FromDouble(version);
- }
- static PyObject*
- cms_profile_getattr_icc_version(CmsProfileObject* self, void* closure)
- {
- return PyInt_FromLong((long) cmsGetEncodedICCversion(self->profile));
- }
- static PyObject*
- cms_profile_getattr_attributes(CmsProfileObject* self, void* closure)
- {
- cmsUInt64Number attr;
- cmsGetHeaderAttributes(self->profile, &attr);
- /* This works just as well on Windows (LLP64), 32-bit Linux
- (ILP32) and 64-bit Linux (LP64) systems. */
- return PyLong_FromUnsignedLongLong((unsigned long long) attr);
- }
- static PyObject*
- cms_profile_getattr_header_flags(CmsProfileObject* self, void* closure)
- {
- cmsUInt32Number flags = cmsGetHeaderFlags(self->profile);
- return PyInt_FromLong(flags);
- }
- static PyObject*
- cms_profile_getattr_header_manufacturer(CmsProfileObject* self, void* closure)
- {
- return _profile_read_int_as_string(cmsGetHeaderManufacturer(self->profile));
- }
- static PyObject*
- cms_profile_getattr_header_model(CmsProfileObject* self, void* closure)
- {
- return _profile_read_int_as_string(cmsGetHeaderModel(self->profile));
- }
- static PyObject*
- cms_profile_getattr_device_class(CmsProfileObject* self, void* closure)
- {
- return _profile_read_int_as_string(cmsGetDeviceClass(self->profile));
- }
- /* Duplicate of pcs, but uninterpreted. */
- static PyObject*
- cms_profile_getattr_connection_space(CmsProfileObject* self, void* closure)
- {
- return _profile_read_int_as_string(cmsGetPCS(self->profile));
- }
- /* Duplicate of color_space, but uninterpreted. */
- static PyObject*
- cms_profile_getattr_xcolor_space(CmsProfileObject* self, void* closure)
- {
- return _profile_read_int_as_string(cmsGetColorSpace(self->profile));
- }
- static PyObject*
- cms_profile_getattr_profile_id(CmsProfileObject* self, void* closure)
- {
- cmsUInt8Number id[16];
- cmsGetHeaderProfileID(self->profile, id);
- return PyBytes_FromStringAndSize((char *) id, 16);
- }
- static PyObject*
- cms_profile_getattr_is_matrix_shaper(CmsProfileObject* self, void* closure)
- {
- return PyBool_FromLong((long) cmsIsMatrixShaper(self->profile));
- }
- static PyObject*
- cms_profile_getattr_technology(CmsProfileObject* self, void* closure)
- {
- return _profile_read_signature(self, cmsSigTechnologyTag);
- }
- static PyObject*
- cms_profile_getattr_colorimetric_intent(CmsProfileObject* self, void* closure)
- {
- return _profile_read_signature(self, cmsSigColorimetricIntentImageStateTag);
- }
- static PyObject*
- cms_profile_getattr_perceptual_rendering_intent_gamut(CmsProfileObject* self, void* closure)
- {
- return _profile_read_signature(self, cmsSigPerceptualRenderingIntentGamutTag);
- }
- static PyObject*
- cms_profile_getattr_saturation_rendering_intent_gamut(CmsProfileObject* self, void* closure)
- {
- return _profile_read_signature(self, cmsSigSaturationRenderingIntentGamutTag);
- }
- static PyObject*
- cms_profile_getattr_red_colorant(CmsProfileObject* self, void* closure)
- {
- if (!cmsIsMatrixShaper(self->profile)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return _profile_read_ciexyz(self, cmsSigRedColorantTag, 0);
- }
- static PyObject*
- cms_profile_getattr_green_colorant(CmsProfileObject* self, void* closure)
- {
- if (!cmsIsMatrixShaper(self->profile)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return _profile_read_ciexyz(self, cmsSigGreenColorantTag, 0);
- }
- static PyObject*
- cms_profile_getattr_blue_colorant(CmsProfileObject* self, void* closure)
- {
- if (!cmsIsMatrixShaper(self->profile)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return _profile_read_ciexyz(self, cmsSigBlueColorantTag, 0);
- }
- static PyObject*
- cms_profile_getattr_media_white_point_temperature(CmsProfileObject *self, void* closure)
- {
- cmsCIEXYZ* XYZ;
- cmsCIExyY xyY;
- cmsFloat64Number tempK;
- cmsTagSignature info = cmsSigMediaWhitePointTag;
- cmsBool result;
- if (!cmsIsTag(self->profile, info)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- XYZ = (cmsCIEXYZ*) cmsReadTag(self->profile, info);
- if (!XYZ) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- if (XYZ == NULL || XYZ->X == 0) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- cmsXYZ2xyY(&xyY, XYZ);
- result = cmsTempFromWhitePoint(&tempK, &xyY);
- if (!result) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return PyFloat_FromDouble(tempK);
- }
- static PyObject*
- cms_profile_getattr_media_white_point(CmsProfileObject* self, void* closure)
- {
- return _profile_read_ciexyz(self, cmsSigMediaWhitePointTag, 0);
- }
- static PyObject*
- cms_profile_getattr_media_black_point(CmsProfileObject* self, void* closure)
- {
- return _profile_read_ciexyz(self, cmsSigMediaBlackPointTag, 0);
- }
- static PyObject*
- cms_profile_getattr_luminance(CmsProfileObject* self, void* closure)
- {
- return _profile_read_ciexyz(self, cmsSigLuminanceTag, 0);
- }
- static PyObject*
- cms_profile_getattr_chromatic_adaptation(CmsProfileObject* self, void* closure)
- {
- return _profile_read_ciexyz(self, cmsSigChromaticAdaptationTag, 1);
- }
- static PyObject*
- cms_profile_getattr_chromaticity(CmsProfileObject* self, void* closure)
- {
- return _profile_read_ciexyy_triple(self, cmsSigChromaticityTag);
- }
- static PyObject*
- cms_profile_getattr_red_primary(CmsProfileObject* self, void* closure)
- {
- cmsBool result = 0;
- cmsCIEXYZTRIPLE primaries;
- if (cmsIsMatrixShaper(self->profile))
- result = _calculate_rgb_primaries(self, &primaries);
- if (! result) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return _xyz_py(&primaries.Red);
- }
- static PyObject*
- cms_profile_getattr_green_primary(CmsProfileObject* self, void* closure)
- {
- cmsBool result = 0;
- cmsCIEXYZTRIPLE primaries;
- if (cmsIsMatrixShaper(self->profile))
- result = _calculate_rgb_primaries(self, &primaries);
- if (! result) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return _xyz_py(&primaries.Green);
- }
- static PyObject*
- cms_profile_getattr_blue_primary(CmsProfileObject* self, void* closure)
- {
- cmsBool result = 0;
- cmsCIEXYZTRIPLE primaries;
- if (cmsIsMatrixShaper(self->profile))
- result = _calculate_rgb_primaries(self, &primaries);
- if (! result) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return _xyz_py(&primaries.Blue);
- }
- static PyObject*
- cms_profile_getattr_colorant_table(CmsProfileObject* self, void* closure)
- {
- return _profile_read_named_color_list(self, cmsSigColorantTableTag);
- }
- static PyObject*
- cms_profile_getattr_colorant_table_out(CmsProfileObject* self, void* closure)
- {
- return _profile_read_named_color_list(self, cmsSigColorantTableOutTag);
- }
- static PyObject*
- cms_profile_getattr_is_intent_supported (CmsProfileObject* self, void* closure)
- {
- return _is_intent_supported(self, 0);
- }
- static PyObject*
- cms_profile_getattr_is_clut (CmsProfileObject* self, void* closure)
- {
- return _is_intent_supported(self, 1);
- }
- static const char*
- _illu_map(int i)
- {
- switch(i) {
- case 0:
- return "unknown";
- case 1:
- return "D50";
- case 2:
- return "D65";
- case 3:
- return "D93";
- case 4:
- return "F2";
- case 5:
- return "D55";
- case 6:
- return "A";
- case 7:
- return "E";
- case 8:
- return "F8";
- default:
- return NULL;
- }
- }
- static PyObject*
- cms_profile_getattr_icc_measurement_condition (CmsProfileObject* self, void* closure)
- {
- cmsICCMeasurementConditions* mc;
- cmsTagSignature info = cmsSigMeasurementTag;
- const char *geo;
- if (!cmsIsTag(self->profile, info)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- mc = (cmsICCMeasurementConditions*) cmsReadTag(self->profile, info);
- if (!mc) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- if (mc->Geometry == 1)
- geo = "45/0, 0/45";
- else if (mc->Geometry == 2)
- geo = "0d, d/0";
- else
- geo = "unknown";
- return Py_BuildValue("{s:i,s:(ddd),s:s,s:d,s:s}",
- "observer", mc->Observer,
- "backing", mc->Backing.X, mc->Backing.Y, mc->Backing.Z,
- "geo", geo,
- "flare", mc->Flare,
- "illuminant_type", _illu_map(mc->IlluminantType));
- }
- static PyObject*
- cms_profile_getattr_icc_viewing_condition (CmsProfileObject* self, void* closure)
- {
- cmsICCViewingConditions* vc;
- cmsTagSignature info = cmsSigViewingConditionsTag;
- if (!cmsIsTag(self->profile, info)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- vc = (cmsICCViewingConditions*) cmsReadTag(self->profile, info);
- if (!vc) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return Py_BuildValue("{s:(ddd),s:(ddd),s:s}",
- "illuminant", vc->IlluminantXYZ.X, vc->IlluminantXYZ.Y, vc->IlluminantXYZ.Z,
- "surround", vc->SurroundXYZ.X, vc->SurroundXYZ.Y, vc->SurroundXYZ.Z,
- "illuminant_type", _illu_map(vc->IlluminantType));
- }
- static struct PyGetSetDef cms_profile_getsetters[] = {
- /* Compatibility interfaces. */
- { "product_desc", (getter) cms_profile_getattr_product_desc },
- { "product_description", (getter) cms_profile_getattr_product_description },
- { "product_manufacturer", (getter) cms_profile_getattr_product_manufacturer },
- { "product_model", (getter) cms_profile_getattr_product_model },
- { "product_copyright", (getter) cms_profile_getattr_product_copyright },
- { "pcs", (getter) cms_profile_getattr_pcs },
- { "color_space", (getter) cms_profile_getattr_color_space },
- /* New style interfaces. */
- { "rendering_intent", (getter) cms_profile_getattr_rendering_intent },
- { "creation_date", (getter) cms_profile_getattr_creation_date },
- { "copyright", (getter) cms_profile_getattr_copyright },
- { "target", (getter) cms_profile_getattr_target },
- { "manufacturer", (getter) cms_profile_getattr_manufacturer },
- { "model", (getter) cms_profile_getattr_model },
- { "profile_description", (getter) cms_profile_getattr_profile_description },
- { "screening_description", (getter) cms_profile_getattr_screening_description },
- { "viewing_condition", (getter) cms_profile_getattr_viewing_condition },
- { "version", (getter) cms_profile_getattr_version },
- { "icc_version", (getter) cms_profile_getattr_icc_version },
- { "attributes", (getter) cms_profile_getattr_attributes },
- { "header_flags", (getter) cms_profile_getattr_header_flags },
- { "header_manufacturer", (getter) cms_profile_getattr_header_manufacturer },
- { "header_model", (getter) cms_profile_getattr_header_model },
- { "device_class", (getter) cms_profile_getattr_device_class },
- { "connection_space", (getter) cms_profile_getattr_connection_space },
- /* Similar to color_space, but with full 4-letter signature (including trailing whitespace). */
- { "xcolor_space", (getter) cms_profile_getattr_xcolor_space },
- { "profile_id", (getter) cms_profile_getattr_profile_id },
- { "is_matrix_shaper", (getter) cms_profile_getattr_is_matrix_shaper },
- { "technology", (getter) cms_profile_getattr_technology },
- { "colorimetric_intent", (getter) cms_profile_getattr_colorimetric_intent },
- { "perceptual_rendering_intent_gamut", (getter) cms_profile_getattr_perceptual_rendering_intent_gamut },
- { "saturation_rendering_intent_gamut", (getter) cms_profile_getattr_saturation_rendering_intent_gamut },
- { "red_colorant", (getter) cms_profile_getattr_red_colorant },
- { "green_colorant", (getter) cms_profile_getattr_green_colorant },
- { "blue_colorant", (getter) cms_profile_getattr_blue_colorant },
- { "red_primary", (getter) cms_profile_getattr_red_primary },
- { "green_primary", (getter) cms_profile_getattr_green_primary },
- { "blue_primary", (getter) cms_profile_getattr_blue_primary },
- { "media_white_point_temperature", (getter) cms_profile_getattr_media_white_point_temperature },
- { "media_white_point", (getter) cms_profile_getattr_media_white_point },
- { "media_black_point", (getter) cms_profile_getattr_media_black_point },
- { "luminance", (getter) cms_profile_getattr_luminance },
- { "chromatic_adaptation", (getter) cms_profile_getattr_chromatic_adaptation },
- { "chromaticity", (getter) cms_profile_getattr_chromaticity },
- { "colorant_table", (getter) cms_profile_getattr_colorant_table },
- { "colorant_table_out", (getter) cms_profile_getattr_colorant_table_out },
- { "intent_supported", (getter) cms_profile_getattr_is_intent_supported },
- { "clut", (getter) cms_profile_getattr_is_clut },
- { "icc_measurement_condition", (getter) cms_profile_getattr_icc_measurement_condition },
- { "icc_viewing_condition", (getter) cms_profile_getattr_icc_viewing_condition },
- { NULL }
- };
- static PyTypeObject CmsProfile_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "PIL._imagingcms.CmsProfile", /*tp_name */
- sizeof(CmsProfileObject), 0,/*tp_basicsize, tp_itemsize */
- /* methods */
- (destructor) cms_profile_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number */
- 0, /*tp_as_sequence */
- 0, /*tp_as_mapping */
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- cms_profile_methods, /*tp_methods*/
- 0, /*tp_members*/
- cms_profile_getsetters, /*tp_getset*/
- };
- static struct PyMethodDef cms_transform_methods[] = {
- {"apply", (PyCFunction) cms_transform_apply, 1},
- {NULL, NULL} /* sentinel */
- };
- static PyObject*
- cms_transform_getattr_inputMode(CmsTransformObject* self, void* closure)
- {
- return PyUnicode_FromString(self->mode_in);
- }
- static PyObject*
- cms_transform_getattr_outputMode(CmsTransformObject* self, void* closure)
- {
- return PyUnicode_FromString(self->mode_out);
- }
- static struct PyGetSetDef cms_transform_getsetters[] = {
- { "inputMode", (getter) cms_transform_getattr_inputMode },
- { "outputMode", (getter) cms_transform_getattr_outputMode },
- { NULL }
- };
- static PyTypeObject CmsTransform_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "CmsTransform", sizeof(CmsTransformObject), 0,
- /* methods */
- (destructor) cms_transform_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number */
- 0, /*tp_as_sequence */
- 0, /*tp_as_mapping */
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- cms_transform_methods, /*tp_methods*/
- 0, /*tp_members*/
- cms_transform_getsetters, /*tp_getset*/
- };
- static int
- setup_module(PyObject* m) {
- PyObject *d;
- PyObject *v;
- d = PyModule_GetDict(m);
- CmsProfile_Type.tp_new = PyType_GenericNew;
- /* Ready object types */
- PyType_Ready(&CmsProfile_Type);
- PyType_Ready(&CmsTransform_Type);
- Py_INCREF(&CmsProfile_Type);
- PyModule_AddObject(m, "CmsProfile", (PyObject *)&CmsProfile_Type);
- d = PyModule_GetDict(m);
- v = PyUnicode_FromFormat("%d.%d", LCMS_VERSION / 100, LCMS_VERSION % 100);
- PyDict_SetItemString(d, "littlecms_version", v);
- return 0;
- }
- #if PY_VERSION_HEX >= 0x03000000
- PyMODINIT_FUNC
- PyInit__imagingcms(void) {
- PyObject* m;
- static PyModuleDef module_def = {
- PyModuleDef_HEAD_INIT,
- "_imagingcms", /* m_name */
- NULL, /* m_doc */
- -1, /* m_size */
- pyCMSdll_methods, /* m_methods */
- };
- m = PyModule_Create(&module_def);
- if (setup_module(m) < 0)
- return NULL;
- PyDateTime_IMPORT;
- return m;
- }
- #else
- PyMODINIT_FUNC
- init_imagingcms(void)
- {
- PyObject *m = Py_InitModule("_imagingcms", pyCMSdll_methods);
- setup_module(m);
- PyDateTime_IMPORT;
- }
- #endif
|