File: | _imagingcms.c |
Warning: | line 1531, column 13 PyObject ownership leak with reference count of 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * pyCMS | |||
3 | * a Python / PIL interface to the littleCMS ICC Color Management System | |||
4 | * Copyright (C) 2002-2003 Kevin Cazabon | |||
5 | * kevin@cazabon.com | |||
6 | * http://www.cazabon.com | |||
7 | * Adapted/reworked for PIL by Fredrik Lundh | |||
8 | * Copyright (c) 2009 Fredrik Lundh | |||
9 | * Updated to LCMS2 | |||
10 | * Copyright (c) 2013 Eric Soroos | |||
11 | * | |||
12 | * pyCMS home page: http://www.cazabon.com/pyCMS | |||
13 | * littleCMS home page: http://www.littlecms.com | |||
14 | * (littleCMS is Copyright (C) 1998-2001 Marti Maria) | |||
15 | * | |||
16 | * Originally released under LGPL. Graciously donated to PIL in | |||
17 | * March 2009, for distribution under the standard PIL license | |||
18 | */ | |||
19 | ||||
20 | #define COPYRIGHTINFO"pyCMS\na Python / PIL interface to the littleCMS ICC Color Management System\nCopyright (C) 2002-2003 Kevin Cazabon\nkevin@cazabon.com\nhttp://www.cazabon.com\n" \ | |||
21 | "\ | |||
22 | pyCMS\n\ | |||
23 | a Python / PIL interface to the littleCMS ICC Color Management System\n\ | |||
24 | Copyright (C) 2002-2003 Kevin Cazabon\n\ | |||
25 | kevin@cazabon.com\n\ | |||
26 | http://www.cazabon.com\n\ | |||
27 | " | |||
28 | ||||
29 | #define PY_SSIZE_T_CLEAN | |||
30 | #include "Python.h" // Include before wchar.h so _GNU_SOURCE is set | |||
31 | #include "wchar.h" | |||
32 | #include "datetime.h" | |||
33 | ||||
34 | #include "lcms2.h" | |||
35 | #include "libImaging/Imaging.h" | |||
36 | ||||
37 | #define PYCMSVERSION"1.0.0 pil" "1.0.0 pil" | |||
38 | ||||
39 | /* version history */ | |||
40 | ||||
41 | /* | |||
42 | 1.0.0 pil Integrating littleCMS2 | |||
43 | 0.1.0 pil integration & refactoring | |||
44 | 0.0.2 alpha: Minor updates, added interfaces to littleCMS features, Jan 6, 2003 | |||
45 | - fixed some memory holes in how transforms/profiles were created and passed back to | |||
46 | Python due to improper destructor setup for PyCObjects | |||
47 | - added buildProofTransformFromOpenProfiles() function | |||
48 | - eliminated some code redundancy, centralizing several common tasks with internal | |||
49 | functions | |||
50 | ||||
51 | 0.0.1 alpha: First public release Dec 26, 2002 | |||
52 | ||||
53 | */ | |||
54 | ||||
55 | /* known to-do list with current version: | |||
56 | ||||
57 | Verify that PILmode->littleCMStype conversion in findLCMStype is correct for all | |||
58 | PIL modes (it probably isn't for the more obscure ones) | |||
59 | ||||
60 | Add support for creating custom RGB profiles on the fly | |||
61 | Add support for checking presence of a specific tag in a profile | |||
62 | Add support for other littleCMS features as required | |||
63 | ||||
64 | */ | |||
65 | ||||
66 | /* | |||
67 | INTENT_PERCEPTUAL 0 | |||
68 | INTENT_RELATIVE_COLORIMETRIC 1 | |||
69 | INTENT_SATURATION 2 | |||
70 | INTENT_ABSOLUTE_COLORIMETRIC 3 | |||
71 | */ | |||
72 | ||||
73 | /* -------------------------------------------------------------------- */ | |||
74 | /* wrapper classes */ | |||
75 | ||||
76 | /* a profile represents the ICC characteristics for a specific device */ | |||
77 | ||||
78 | typedef struct { | |||
79 | PyObject_HEADPyObject ob_base; cmsHPROFILE profile; | |||
80 | } CmsProfileObject; | |||
81 | ||||
82 | static PyTypeObject CmsProfile_Type; | |||
83 | ||||
84 | #define CmsProfile_Check(op)((((PyObject*)(op))->ob_type) == &CmsProfile_Type) (Py_TYPE(op)(((PyObject*)(op))->ob_type) == &CmsProfile_Type) | |||
85 | ||||
86 | static PyObject * | |||
87 | cms_profile_new(cmsHPROFILE profile) { | |||
88 | CmsProfileObject *self; | |||
89 | ||||
90 | self = PyObject_New(CmsProfileObject, &CmsProfile_Type)( (CmsProfileObject *) _PyObject_New(&CmsProfile_Type) ); | |||
91 | if (!self) { | |||
92 | return NULL((void*)0); | |||
93 | } | |||
94 | ||||
95 | self->profile = profile; | |||
96 | ||||
97 | return (PyObject *)self; | |||
98 | } | |||
99 | ||||
100 | static PyObject * | |||
101 | cms_profile_open(PyObject *self, PyObject *args) { | |||
102 | cmsHPROFILE hProfile; | |||
103 | ||||
104 | char *sProfile; | |||
105 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "s:profile_open", &sProfile)) { | |||
106 | return NULL((void*)0); | |||
107 | } | |||
108 | ||||
109 | hProfile = cmsOpenProfileFromFile(sProfile, "r"); | |||
110 | if (!hProfile) { | |||
111 | PyErr_SetString(PyExc_OSError, "cannot open profile file"); | |||
112 | return NULL((void*)0); | |||
113 | } | |||
114 | ||||
115 | return cms_profile_new(hProfile); | |||
116 | } | |||
117 | ||||
118 | static PyObject * | |||
119 | cms_profile_fromstring(PyObject *self, PyObject *args) { | |||
120 | cmsHPROFILE hProfile; | |||
121 | ||||
122 | char *pProfile; | |||
123 | Py_ssize_t nProfile; | |||
124 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "y#:profile_frombytes", &pProfile, &nProfile)) { | |||
125 | return NULL((void*)0); | |||
126 | } | |||
127 | ||||
128 | hProfile = cmsOpenProfileFromMem(pProfile, nProfile); | |||
129 | if (!hProfile) { | |||
130 | PyErr_SetString(PyExc_OSError, "cannot open profile from string"); | |||
131 | return NULL((void*)0); | |||
132 | } | |||
133 | ||||
134 | return cms_profile_new(hProfile); | |||
135 | } | |||
136 | ||||
137 | static PyObject * | |||
138 | cms_profile_tobytes(PyObject *self, PyObject *args) { | |||
139 | char *pProfile = NULL((void*)0); | |||
140 | cmsUInt32Number nProfile; | |||
141 | PyObject *CmsProfile; | |||
142 | ||||
143 | cmsHPROFILE *profile; | |||
144 | ||||
145 | PyObject *ret; | |||
146 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "O", &CmsProfile)) { | |||
147 | return NULL((void*)0); | |||
148 | } | |||
149 | ||||
150 | profile = ((CmsProfileObject *)CmsProfile)->profile; | |||
151 | ||||
152 | if (!cmsSaveProfileToMem(profile, pProfile, &nProfile)) { | |||
153 | PyErr_SetString(PyExc_OSError, "Could not determine profile size"); | |||
154 | return NULL((void*)0); | |||
155 | } | |||
156 | ||||
157 | pProfile = (char *)malloc(nProfile); | |||
158 | if (!pProfile) { | |||
159 | PyErr_SetString(PyExc_OSError, "Out of Memory"); | |||
160 | return NULL((void*)0); | |||
161 | } | |||
162 | ||||
163 | if (!cmsSaveProfileToMem(profile, pProfile, &nProfile)) { | |||
164 | PyErr_SetString(PyExc_OSError, "Could not get profile"); | |||
165 | free(pProfile); | |||
166 | return NULL((void*)0); | |||
167 | } | |||
168 | ||||
169 | ret = PyBytes_FromStringAndSize(pProfile, (Py_ssize_t)nProfile); | |||
170 | ||||
171 | free(pProfile); | |||
172 | return ret; | |||
173 | } | |||
174 | ||||
175 | static void | |||
176 | cms_profile_dealloc(CmsProfileObject *self) { | |||
177 | (void)cmsCloseProfile(self->profile); | |||
178 | PyObject_DelPyObject_Free(self); | |||
179 | } | |||
180 | ||||
181 | /* a transform represents the mapping between two profiles */ | |||
182 | ||||
183 | typedef struct { | |||
184 | PyObject_HEADPyObject ob_base; char mode_in[8]; | |||
185 | char mode_out[8]; | |||
186 | cmsHTRANSFORM transform; | |||
187 | } CmsTransformObject; | |||
188 | ||||
189 | static PyTypeObject CmsTransform_Type; | |||
190 | ||||
191 | #define CmsTransform_Check(op)((((PyObject*)(op))->ob_type) == &CmsTransform_Type) (Py_TYPE(op)(((PyObject*)(op))->ob_type) == &CmsTransform_Type) | |||
192 | ||||
193 | static PyObject * | |||
194 | cms_transform_new(cmsHTRANSFORM transform, char *mode_in, char *mode_out) { | |||
195 | CmsTransformObject *self; | |||
196 | ||||
197 | self = PyObject_New(CmsTransformObject, &CmsTransform_Type)( (CmsTransformObject *) _PyObject_New(&CmsTransform_Type ) ); | |||
198 | if (!self) { | |||
199 | return NULL((void*)0); | |||
200 | } | |||
201 | ||||
202 | self->transform = transform; | |||
203 | ||||
204 | strcpy(self->mode_in, mode_in); | |||
205 | strcpy(self->mode_out, mode_out); | |||
206 | ||||
207 | return (PyObject *)self; | |||
208 | } | |||
209 | ||||
210 | static void | |||
211 | cms_transform_dealloc(CmsTransformObject *self) { | |||
212 | cmsDeleteTransform(self->transform); | |||
213 | PyObject_DelPyObject_Free(self); | |||
214 | } | |||
215 | ||||
216 | /* -------------------------------------------------------------------- */ | |||
217 | /* internal functions */ | |||
218 | ||||
219 | static cmsUInt32Number | |||
220 | findLCMStype(char *PILmode) { | |||
221 | if (strcmp(PILmode, "RGB") == 0) { | |||
222 | return TYPE_RGBA_8(((4) << 16)|((1) << 7)|((3) << 3)|(1)); | |||
223 | } else if (strcmp(PILmode, "RGBA") == 0) { | |||
224 | return TYPE_RGBA_8(((4) << 16)|((1) << 7)|((3) << 3)|(1)); | |||
225 | } else if (strcmp(PILmode, "RGBX") == 0) { | |||
226 | return TYPE_RGBA_8(((4) << 16)|((1) << 7)|((3) << 3)|(1)); | |||
227 | } else if (strcmp(PILmode, "RGBA;16B") == 0) { | |||
228 | return TYPE_RGBA_16(((4) << 16)|((1) << 7)|((3) << 3)|(2)); | |||
229 | } else if (strcmp(PILmode, "CMYK") == 0) { | |||
230 | return TYPE_CMYK_8(((6) << 16)|((4) << 3)|(1)); | |||
231 | } else if (strcmp(PILmode, "L") == 0) { | |||
232 | return TYPE_GRAY_8(((3) << 16)|((1) << 3)|(1)); | |||
233 | } else if (strcmp(PILmode, "L;16") == 0) { | |||
234 | return TYPE_GRAY_16(((3) << 16)|((1) << 3)|(2)); | |||
235 | } else if (strcmp(PILmode, "L;16B") == 0) { | |||
236 | return TYPE_GRAY_16_SE(((3) << 16)|((1) << 3)|(2)|((1) << 11)); | |||
237 | } else if (strcmp(PILmode, "YCCA") == 0) { | |||
238 | return TYPE_YCbCr_8(((7) << 16)|((3) << 3)|(1)); | |||
239 | } else if (strcmp(PILmode, "YCC") == 0) { | |||
240 | return TYPE_YCbCr_8(((7) << 16)|((3) << 3)|(1)); | |||
241 | } else if (strcmp(PILmode, "LAB") == 0) { | |||
242 | // LabX equivalent like ALab, but not reversed -- no #define in lcms2 | |||
243 | return (COLORSPACE_SH(PT_LabV2)((30) << 16) | CHANNELS_SH(3)((3) << 3) | BYTES_SH(1)(1) | EXTRA_SH(1)((1) << 7)); | |||
244 | } | |||
245 | ||||
246 | else { | |||
247 | /* take a wild guess... but you probably should fail instead. */ | |||
248 | return TYPE_GRAY_8(((3) << 16)|((1) << 3)|(1)); /* so there's no buffer overrun... */ | |||
249 | } | |||
250 | } | |||
251 | ||||
252 | #define Cms_Min(a, b)((a) < (b) ? (a) : (b)) ((a) < (b) ? (a) : (b)) | |||
253 | ||||
254 | static int | |||
255 | pyCMSgetAuxChannelChannel(cmsUInt32Number format, int auxChannelNdx) { | |||
256 | int numColors = T_CHANNELS(format)(((format)>>3)&15); | |||
257 | int numExtras = T_EXTRA(format)(((format)>>7)&7); | |||
258 | ||||
259 | if (T_SWAPFIRST(format)(((format)>>14)&1) && T_DOSWAP(format)(((format)>>10)&1)) { | |||
260 | // reverse order, before anything but last extra is shifted last | |||
261 | if (auxChannelNdx == numExtras - 1) { | |||
262 | return numColors + numExtras - 1; | |||
263 | } else { | |||
264 | return numExtras - 2 - auxChannelNdx; | |||
265 | } | |||
266 | } else if (T_SWAPFIRST(format)(((format)>>14)&1)) { | |||
267 | // in order, after color channels, but last extra is shifted to first | |||
268 | if (auxChannelNdx == numExtras - 1) { | |||
269 | return 0; | |||
270 | } else { | |||
271 | return numColors + 1 + auxChannelNdx; | |||
272 | } | |||
273 | } else if (T_DOSWAP(format)(((format)>>10)&1)) { | |||
274 | // reverse order, before anything | |||
275 | return numExtras - 1 - auxChannelNdx; | |||
276 | } else { | |||
277 | // in order, after color channels | |||
278 | return numColors + auxChannelNdx; | |||
279 | } | |||
280 | } | |||
281 | ||||
282 | static void | |||
283 | pyCMScopyAux(cmsHTRANSFORM hTransform, Imaging imDst, const Imaging imSrc) { | |||
284 | cmsUInt32Number dstLCMSFormat; | |||
285 | cmsUInt32Number srcLCMSFormat; | |||
286 | int numSrcExtras; | |||
287 | int numDstExtras; | |||
288 | int numExtras; | |||
289 | int ySize; | |||
290 | int xSize; | |||
291 | int channelSize; | |||
292 | int srcChunkSize; | |||
293 | int dstChunkSize; | |||
294 | int e; | |||
295 | ||||
296 | // trivially copied | |||
297 | if (imDst == imSrc) { | |||
298 | return; | |||
299 | } | |||
300 | ||||
301 | dstLCMSFormat = cmsGetTransformOutputFormat(hTransform); | |||
302 | srcLCMSFormat = cmsGetTransformInputFormat(hTransform); | |||
303 | ||||
304 | // currently, all Pillow formats are chunky formats, but check it anyway | |||
305 | if (T_PLANAR(dstLCMSFormat)(((dstLCMSFormat)>>12)&1) || T_PLANAR(srcLCMSFormat)(((srcLCMSFormat)>>12)&1)) { | |||
306 | return; | |||
307 | } | |||
308 | ||||
309 | // copy only if channel format is identical, except OPTIMIZED is ignored as it | |||
310 | // does not affect the aux channel | |||
311 | if (T_FLOAT(dstLCMSFormat)(((dstLCMSFormat)>>22)&1) != T_FLOAT(srcLCMSFormat)(((srcLCMSFormat)>>22)&1) || | |||
312 | T_FLAVOR(dstLCMSFormat)(((dstLCMSFormat)>>13)&1) != T_FLAVOR(srcLCMSFormat)(((srcLCMSFormat)>>13)&1) || | |||
313 | T_ENDIAN16(dstLCMSFormat)(((dstLCMSFormat)>>11)&1) != T_ENDIAN16(srcLCMSFormat)(((srcLCMSFormat)>>11)&1) || | |||
314 | T_BYTES(dstLCMSFormat)((dstLCMSFormat)&7) != T_BYTES(srcLCMSFormat)((srcLCMSFormat)&7)) { | |||
315 | return; | |||
316 | } | |||
317 | ||||
318 | numSrcExtras = T_EXTRA(srcLCMSFormat)(((srcLCMSFormat)>>7)&7); | |||
319 | numDstExtras = T_EXTRA(dstLCMSFormat)(((dstLCMSFormat)>>7)&7); | |||
320 | numExtras = Cms_Min(numSrcExtras, numDstExtras)((numSrcExtras) < (numDstExtras) ? (numSrcExtras) : (numDstExtras )); | |||
321 | ySize = Cms_Min(imSrc->ysize, imDst->ysize)((imSrc->ysize) < (imDst->ysize) ? (imSrc->ysize) : (imDst->ysize)); | |||
322 | xSize = Cms_Min(imSrc->xsize, imDst->xsize)((imSrc->xsize) < (imDst->xsize) ? (imSrc->xsize) : (imDst->xsize)); | |||
323 | channelSize = T_BYTES(dstLCMSFormat)((dstLCMSFormat)&7); | |||
324 | srcChunkSize = (T_CHANNELS(srcLCMSFormat)(((srcLCMSFormat)>>3)&15) + T_EXTRA(srcLCMSFormat)(((srcLCMSFormat)>>7)&7)) * channelSize; | |||
325 | dstChunkSize = (T_CHANNELS(dstLCMSFormat)(((dstLCMSFormat)>>3)&15) + T_EXTRA(dstLCMSFormat)(((dstLCMSFormat)>>7)&7)) * channelSize; | |||
326 | ||||
327 | for (e = 0; e < numExtras; ++e) { | |||
328 | int y; | |||
329 | int dstChannel = pyCMSgetAuxChannelChannel(dstLCMSFormat, e); | |||
330 | int srcChannel = pyCMSgetAuxChannelChannel(srcLCMSFormat, e); | |||
331 | ||||
332 | for (y = 0; y < ySize; y++) { | |||
333 | int x; | |||
334 | char *pDstExtras = imDst->image[y] + dstChannel * channelSize; | |||
335 | const char *pSrcExtras = imSrc->image[y] + srcChannel * channelSize; | |||
336 | ||||
337 | for (x = 0; x < xSize; x++) { | |||
338 | memcpy( | |||
339 | pDstExtras + x * dstChunkSize, | |||
340 | pSrcExtras + x * srcChunkSize, | |||
341 | channelSize); | |||
342 | } | |||
343 | } | |||
344 | } | |||
345 | } | |||
346 | ||||
347 | static int | |||
348 | pyCMSdoTransform(Imaging im, Imaging imOut, cmsHTRANSFORM hTransform) { | |||
349 | int i; | |||
350 | ||||
351 | if (im->xsize > imOut->xsize || im->ysize > imOut->ysize) { | |||
352 | return -1; | |||
353 | } | |||
354 | ||||
355 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
356 | ||||
357 | // transform color channels only | |||
358 | for (i = 0; i < im->ysize; i++) { | |||
359 | cmsDoTransform(hTransform, im->image[i], imOut->image[i], im->xsize); | |||
360 | } | |||
361 | ||||
362 | // lcms by default does nothing to the auxiliary channels leaving those | |||
363 | // unchanged. To do "the right thing" here, i.e. maintain identical results | |||
364 | // with and without inPlace, we replicate those channels to the output. | |||
365 | // | |||
366 | // As of lcms 2.8, a new cmsFLAGS_COPY_ALPHA flag is introduced which would | |||
367 | // do the same thing automagically. Unfortunately, lcms2.8 is not yet widely | |||
368 | // enough available on all platforms, so we polyfill it here for now. | |||
369 | pyCMScopyAux(hTransform, imOut, im); | |||
370 | ||||
371 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
372 | ||||
373 | return 0; | |||
374 | } | |||
375 | ||||
376 | static cmsHTRANSFORM | |||
377 | _buildTransform( | |||
378 | cmsHPROFILE hInputProfile, | |||
379 | cmsHPROFILE hOutputProfile, | |||
380 | char *sInMode, | |||
381 | char *sOutMode, | |||
382 | int iRenderingIntent, | |||
383 | cmsUInt32Number cmsFLAGS) { | |||
384 | cmsHTRANSFORM hTransform; | |||
385 | ||||
386 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
387 | ||||
388 | /* create the transform */ | |||
389 | hTransform = cmsCreateTransform( | |||
390 | hInputProfile, | |||
391 | findLCMStype(sInMode), | |||
392 | hOutputProfile, | |||
393 | findLCMStype(sOutMode), | |||
394 | iRenderingIntent, | |||
395 | cmsFLAGS); | |||
396 | ||||
397 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
398 | ||||
399 | if (!hTransform) { | |||
400 | PyErr_SetString(PyExc_ValueError, "cannot build transform"); | |||
401 | } | |||
402 | ||||
403 | return hTransform; /* if NULL, an exception is set */ | |||
404 | } | |||
405 | ||||
406 | static cmsHTRANSFORM | |||
407 | _buildProofTransform( | |||
408 | cmsHPROFILE hInputProfile, | |||
409 | cmsHPROFILE hOutputProfile, | |||
410 | cmsHPROFILE hProofProfile, | |||
411 | char *sInMode, | |||
412 | char *sOutMode, | |||
413 | int iRenderingIntent, | |||
414 | int iProofIntent, | |||
415 | cmsUInt32Number cmsFLAGS) { | |||
416 | cmsHTRANSFORM hTransform; | |||
417 | ||||
418 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | |||
419 | ||||
420 | /* create the transform */ | |||
421 | hTransform = cmsCreateProofingTransform( | |||
422 | hInputProfile, | |||
423 | findLCMStype(sInMode), | |||
424 | hOutputProfile, | |||
425 | findLCMStype(sOutMode), | |||
426 | hProofProfile, | |||
427 | iRenderingIntent, | |||
428 | iProofIntent, | |||
429 | cmsFLAGS); | |||
430 | ||||
431 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | |||
432 | ||||
433 | if (!hTransform) { | |||
434 | PyErr_SetString(PyExc_ValueError, "cannot build proof transform"); | |||
435 | } | |||
436 | ||||
437 | return hTransform; /* if NULL, an exception is set */ | |||
438 | } | |||
439 | ||||
440 | /* -------------------------------------------------------------------- */ | |||
441 | /* Python callable functions */ | |||
442 | ||||
443 | static PyObject * | |||
444 | buildTransform(PyObject *self, PyObject *args) { | |||
445 | CmsProfileObject *pInputProfile; | |||
446 | CmsProfileObject *pOutputProfile; | |||
447 | char *sInMode; | |||
448 | char *sOutMode; | |||
449 | int iRenderingIntent = 0; | |||
450 | int cmsFLAGS = 0; | |||
451 | ||||
452 | cmsHTRANSFORM transform = NULL((void*)0); | |||
453 | ||||
454 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT( | |||
455 | args, | |||
456 | "O!O!ss|ii:buildTransform", | |||
457 | &CmsProfile_Type, | |||
458 | &pInputProfile, | |||
459 | &CmsProfile_Type, | |||
460 | &pOutputProfile, | |||
461 | &sInMode, | |||
462 | &sOutMode, | |||
463 | &iRenderingIntent, | |||
464 | &cmsFLAGS)) { | |||
465 | return NULL((void*)0); | |||
466 | } | |||
467 | ||||
468 | transform = _buildTransform( | |||
469 | pInputProfile->profile, | |||
470 | pOutputProfile->profile, | |||
471 | sInMode, | |||
472 | sOutMode, | |||
473 | iRenderingIntent, | |||
474 | cmsFLAGS); | |||
475 | ||||
476 | if (!transform) { | |||
477 | return NULL((void*)0); | |||
478 | } | |||
479 | ||||
480 | return cms_transform_new(transform, sInMode, sOutMode); | |||
481 | } | |||
482 | ||||
483 | static PyObject * | |||
484 | buildProofTransform(PyObject *self, PyObject *args) { | |||
485 | CmsProfileObject *pInputProfile; | |||
486 | CmsProfileObject *pOutputProfile; | |||
487 | CmsProfileObject *pProofProfile; | |||
488 | char *sInMode; | |||
489 | char *sOutMode; | |||
490 | int iRenderingIntent = 0; | |||
491 | int iProofIntent = 0; | |||
492 | int cmsFLAGS = 0; | |||
493 | ||||
494 | cmsHTRANSFORM transform = NULL((void*)0); | |||
495 | ||||
496 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT( | |||
497 | args, | |||
498 | "O!O!O!ss|iii:buildProofTransform", | |||
499 | &CmsProfile_Type, | |||
500 | &pInputProfile, | |||
501 | &CmsProfile_Type, | |||
502 | &pOutputProfile, | |||
503 | &CmsProfile_Type, | |||
504 | &pProofProfile, | |||
505 | &sInMode, | |||
506 | &sOutMode, | |||
507 | &iRenderingIntent, | |||
508 | &iProofIntent, | |||
509 | &cmsFLAGS)) { | |||
510 | return NULL((void*)0); | |||
511 | } | |||
512 | ||||
513 | transform = _buildProofTransform( | |||
514 | pInputProfile->profile, | |||
515 | pOutputProfile->profile, | |||
516 | pProofProfile->profile, | |||
517 | sInMode, | |||
518 | sOutMode, | |||
519 | iRenderingIntent, | |||
520 | iProofIntent, | |||
521 | cmsFLAGS); | |||
522 | ||||
523 | if (!transform) { | |||
524 | return NULL((void*)0); | |||
525 | } | |||
526 | ||||
527 | return cms_transform_new(transform, sInMode, sOutMode); | |||
528 | } | |||
529 | ||||
530 | static PyObject * | |||
531 | cms_transform_apply(CmsTransformObject *self, PyObject *args) { | |||
532 | Py_ssize_t idIn; | |||
533 | Py_ssize_t idOut; | |||
534 | Imaging im; | |||
535 | Imaging imOut; | |||
536 | ||||
537 | int result; | |||
538 | ||||
539 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "nn:apply", &idIn, &idOut)) { | |||
540 | return NULL((void*)0); | |||
541 | } | |||
542 | ||||
543 | im = (Imaging)idIn; | |||
544 | imOut = (Imaging)idOut; | |||
545 | ||||
546 | result = pyCMSdoTransform(im, imOut, self->transform); | |||
547 | ||||
548 | return Py_BuildValue_Py_BuildValue_SizeT("i", result); | |||
549 | } | |||
550 | ||||
551 | /* -------------------------------------------------------------------- */ | |||
552 | /* Python-Callable On-The-Fly profile creation functions */ | |||
553 | ||||
554 | static PyObject * | |||
555 | createProfile(PyObject *self, PyObject *args) { | |||
556 | char *sColorSpace; | |||
557 | cmsHPROFILE hProfile; | |||
558 | cmsFloat64Number dColorTemp = 0.0; | |||
559 | cmsCIExyY whitePoint; | |||
560 | cmsBool result; | |||
561 | ||||
562 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "s|d:createProfile", &sColorSpace, &dColorTemp)) { | |||
563 | return NULL((void*)0); | |||
564 | } | |||
565 | ||||
566 | if (strcmp(sColorSpace, "LAB") == 0) { | |||
567 | if (dColorTemp > 0.0) { | |||
568 | result = cmsWhitePointFromTemp(&whitePoint, dColorTemp); | |||
569 | if (!result) { | |||
570 | PyErr_SetString( | |||
571 | PyExc_ValueError, | |||
572 | "ERROR: Could not calculate white point from color temperature " | |||
573 | "provided, must be float in degrees Kelvin"); | |||
574 | return NULL((void*)0); | |||
575 | } | |||
576 | hProfile = cmsCreateLab2Profile(&whitePoint); | |||
577 | } else { | |||
578 | hProfile = cmsCreateLab2Profile(NULL((void*)0)); | |||
579 | } | |||
580 | } else if (strcmp(sColorSpace, "XYZ") == 0) { | |||
581 | hProfile = cmsCreateXYZProfile(); | |||
582 | } else if (strcmp(sColorSpace, "sRGB") == 0) { | |||
583 | hProfile = cmsCreate_sRGBProfile(); | |||
584 | } else { | |||
585 | hProfile = NULL((void*)0); | |||
586 | } | |||
587 | ||||
588 | if (!hProfile) { | |||
589 | PyErr_SetString(PyExc_ValueError, "failed to create requested color space"); | |||
590 | return NULL((void*)0); | |||
591 | } | |||
592 | ||||
593 | return cms_profile_new(hProfile); | |||
594 | } | |||
595 | ||||
596 | /* -------------------------------------------------------------------- */ | |||
597 | /* profile methods */ | |||
598 | ||||
599 | static PyObject * | |||
600 | cms_profile_is_intent_supported(CmsProfileObject *self, PyObject *args) { | |||
601 | cmsBool result; | |||
602 | ||||
603 | int intent; | |||
604 | int direction; | |||
605 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "ii:is_intent_supported", &intent, &direction)) { | |||
606 | return NULL((void*)0); | |||
607 | } | |||
608 | ||||
609 | result = cmsIsIntentSupported(self->profile, intent, direction); | |||
610 | ||||
611 | /* printf("cmsIsIntentSupported(%p, %d, %d) => %d\n", self->profile, intent, | |||
612 | * direction, result); */ | |||
613 | ||||
614 | return PyLong_FromLong(result != 0); | |||
615 | } | |||
616 | ||||
617 | #ifdef _WIN32 | |||
618 | ||||
619 | #ifdef _WIN64 | |||
620 | #define F_HANDLE "K" | |||
621 | #else | |||
622 | #define F_HANDLE "k" | |||
623 | #endif | |||
624 | ||||
625 | static PyObject * | |||
626 | cms_get_display_profile_win32(PyObject *self, PyObject *args) { | |||
627 | char filename[MAX_PATH]; | |||
628 | cmsUInt32Number filename_size; | |||
629 | BOOL ok; | |||
630 | ||||
631 | HANDLE handle = 0; | |||
632 | int is_dc = 0; | |||
633 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT( | |||
634 | args, "|" F_HANDLE "i:get_display_profile", &handle, &is_dc)) { | |||
635 | return NULL((void*)0); | |||
636 | } | |||
637 | ||||
638 | filename_size = sizeof(filename); | |||
639 | ||||
640 | if (is_dc) { | |||
641 | ok = GetICMProfile((HDC)handle, &filename_size, filename); | |||
642 | } else { | |||
643 | HDC dc = GetDC((HWND)handle); | |||
644 | ok = GetICMProfile(dc, &filename_size, filename); | |||
645 | ReleaseDC((HWND)handle, dc); | |||
646 | } | |||
647 | ||||
648 | if (ok) { | |||
649 | return PyUnicode_FromStringAndSize(filename, filename_size - 1); | |||
650 | } | |||
651 | ||||
652 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
653 | return Py_None(&_Py_NoneStruct); | |||
654 | } | |||
655 | #endif | |||
656 | ||||
657 | /* -------------------------------------------------------------------- */ | |||
658 | /* Helper functions. */ | |||
659 | ||||
660 | static PyObject * | |||
661 | _profile_read_mlu(CmsProfileObject *self, cmsTagSignature info) { | |||
662 | PyObject *uni; | |||
663 | char *lc = "en"; | |||
664 | char *cc = cmsNoCountry"\0\0"; | |||
665 | cmsMLU *mlu; | |||
666 | cmsUInt32Number len; | |||
667 | wchar_t *buf; | |||
668 | ||||
669 | if (!cmsIsTag(self->profile, info)) { | |||
670 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
671 | return Py_None(&_Py_NoneStruct); | |||
672 | } | |||
673 | ||||
674 | mlu = cmsReadTag(self->profile, info); | |||
675 | if (!mlu) { | |||
676 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
677 | return Py_None(&_Py_NoneStruct); | |||
678 | } | |||
679 | ||||
680 | len = cmsMLUgetWide(mlu, lc, cc, NULL((void*)0), 0); | |||
681 | if (len == 0) { | |||
682 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
683 | return Py_None(&_Py_NoneStruct); | |||
684 | } | |||
685 | ||||
686 | buf = malloc(len); | |||
687 | if (!buf) { | |||
688 | PyErr_SetString(PyExc_OSError, "Out of Memory"); | |||
689 | return NULL((void*)0); | |||
690 | } | |||
691 | /* Just in case the next call fails. */ | |||
692 | buf[0] = '\0'; | |||
693 | ||||
694 | cmsMLUgetWide(mlu, lc, cc, buf, len); | |||
695 | // buf contains additional junk after \0 | |||
696 | uni = PyUnicode_FromWideChar(buf, wcslen(buf)); | |||
697 | free(buf); | |||
698 | ||||
699 | return uni; | |||
700 | } | |||
701 | ||||
702 | static PyObject * | |||
703 | _profile_read_int_as_string(cmsUInt32Number nr) { | |||
704 | PyObject *ret; | |||
705 | char buf[5]; | |||
706 | buf[0] = (char)((nr >> 24) & 0xff); | |||
707 | buf[1] = (char)((nr >> 16) & 0xff); | |||
708 | buf[2] = (char)((nr >> 8) & 0xff); | |||
709 | buf[3] = (char)(nr & 0xff); | |||
710 | buf[4] = 0; | |||
711 | ||||
712 | ret = PyUnicode_DecodeASCII(buf, 4, NULL((void*)0)); | |||
713 | return ret; | |||
714 | } | |||
715 | ||||
716 | static PyObject * | |||
717 | _profile_read_signature(CmsProfileObject *self, cmsTagSignature info) { | |||
718 | unsigned int *sig; | |||
719 | ||||
720 | if (!cmsIsTag(self->profile, info)) { | |||
721 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
722 | return Py_None(&_Py_NoneStruct); | |||
723 | } | |||
724 | ||||
725 | sig = (unsigned int *)cmsReadTag(self->profile, info); | |||
726 | if (!sig) { | |||
727 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
728 | return Py_None(&_Py_NoneStruct); | |||
729 | } | |||
730 | ||||
731 | return _profile_read_int_as_string(*sig); | |||
732 | } | |||
733 | ||||
734 | static PyObject * | |||
735 | _xyz_py(cmsCIEXYZ *XYZ) { | |||
736 | cmsCIExyY xyY; | |||
737 | cmsXYZ2xyY(&xyY, XYZ); | |||
738 | return Py_BuildValue_Py_BuildValue_SizeT( | |||
739 | "((d,d,d),(d,d,d))", XYZ->X, XYZ->Y, XYZ->Z, xyY.x, xyY.y, xyY.Y); | |||
740 | } | |||
741 | ||||
742 | static PyObject * | |||
743 | _xyz3_py(cmsCIEXYZ *XYZ) { | |||
744 | cmsCIExyY xyY[3]; | |||
745 | cmsXYZ2xyY(&xyY[0], &XYZ[0]); | |||
746 | cmsXYZ2xyY(&xyY[1], &XYZ[1]); | |||
747 | cmsXYZ2xyY(&xyY[2], &XYZ[2]); | |||
748 | ||||
749 | return Py_BuildValue_Py_BuildValue_SizeT( | |||
750 | "(((d,d,d),(d,d,d),(d,d,d)),((d,d,d),(d,d,d),(d,d,d)))", | |||
751 | XYZ[0].X, | |||
752 | XYZ[0].Y, | |||
753 | XYZ[0].Z, | |||
754 | XYZ[1].X, | |||
755 | XYZ[1].Y, | |||
756 | XYZ[1].Z, | |||
757 | XYZ[2].X, | |||
758 | XYZ[2].Y, | |||
759 | XYZ[2].Z, | |||
760 | xyY[0].x, | |||
761 | xyY[0].y, | |||
762 | xyY[0].Y, | |||
763 | xyY[1].x, | |||
764 | xyY[1].y, | |||
765 | xyY[1].Y, | |||
766 | xyY[2].x, | |||
767 | xyY[2].y, | |||
768 | xyY[2].Y); | |||
769 | } | |||
770 | ||||
771 | static PyObject * | |||
772 | _profile_read_ciexyz(CmsProfileObject *self, cmsTagSignature info, int multi) { | |||
773 | cmsCIEXYZ *XYZ; | |||
774 | ||||
775 | if (!cmsIsTag(self->profile, info)) { | |||
776 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
777 | return Py_None(&_Py_NoneStruct); | |||
778 | } | |||
779 | ||||
780 | XYZ = (cmsCIEXYZ *)cmsReadTag(self->profile, info); | |||
781 | if (!XYZ) { | |||
782 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
783 | return Py_None(&_Py_NoneStruct); | |||
784 | } | |||
785 | if (multi) { | |||
786 | return _xyz3_py(XYZ); | |||
787 | } else { | |||
788 | return _xyz_py(XYZ); | |||
789 | } | |||
790 | } | |||
791 | ||||
792 | static PyObject * | |||
793 | _profile_read_ciexyy_triple(CmsProfileObject *self, cmsTagSignature info) { | |||
794 | cmsCIExyYTRIPLE *triple; | |||
795 | ||||
796 | if (!cmsIsTag(self->profile, info)) { | |||
797 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
798 | return Py_None(&_Py_NoneStruct); | |||
799 | } | |||
800 | ||||
801 | triple = (cmsCIExyYTRIPLE *)cmsReadTag(self->profile, info); | |||
802 | if (!triple) { | |||
803 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
804 | return Py_None(&_Py_NoneStruct); | |||
805 | } | |||
806 | ||||
807 | /* Note: lcms does all the heavy lifting and error checking (nr of | |||
808 | channels == 3). */ | |||
809 | return Py_BuildValue_Py_BuildValue_SizeT( | |||
810 | "((d,d,d),(d,d,d),(d,d,d)),", | |||
811 | triple->Red.x, | |||
812 | triple->Red.y, | |||
813 | triple->Red.Y, | |||
814 | triple->Green.x, | |||
815 | triple->Green.y, | |||
816 | triple->Green.Y, | |||
817 | triple->Blue.x, | |||
818 | triple->Blue.y, | |||
819 | triple->Blue.Y); | |||
820 | } | |||
821 | ||||
822 | static PyObject * | |||
823 | _profile_read_named_color_list(CmsProfileObject *self, cmsTagSignature info) { | |||
824 | cmsNAMEDCOLORLIST *ncl; | |||
825 | int i, n; | |||
826 | char name[cmsMAX_PATH256]; | |||
827 | PyObject *result; | |||
828 | ||||
829 | if (!cmsIsTag(self->profile, info)) { | |||
830 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
831 | return Py_None(&_Py_NoneStruct); | |||
832 | } | |||
833 | ||||
834 | ncl = (cmsNAMEDCOLORLIST *)cmsReadTag(self->profile, info); | |||
835 | if (ncl == NULL((void*)0)) { | |||
836 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
837 | return Py_None(&_Py_NoneStruct); | |||
838 | } | |||
839 | ||||
840 | n = cmsNamedColorCount(ncl); | |||
841 | result = PyList_New(n); | |||
842 | if (!result) { | |||
843 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
844 | return Py_None(&_Py_NoneStruct); | |||
845 | } | |||
846 | ||||
847 | for (i = 0; i < n; i++) { | |||
848 | PyObject *str; | |||
849 | cmsNamedColorInfo(ncl, i, name, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
850 | str = PyUnicode_FromString(name); | |||
851 | if (str == NULL((void*)0)) { | |||
852 | Py_DECREF(result)_Py_DECREF(((PyObject*)(result))); | |||
853 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
854 | return Py_None(&_Py_NoneStruct); | |||
855 | } | |||
856 | PyList_SET_ITEM(result, i, str)PyList_SetItem(result, i, str); | |||
857 | } | |||
858 | ||||
859 | return result; | |||
860 | } | |||
861 | ||||
862 | static cmsBool | |||
863 | _calculate_rgb_primaries(CmsProfileObject *self, cmsCIEXYZTRIPLE *result) { | |||
864 | double input[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; | |||
865 | cmsHPROFILE hXYZ; | |||
866 | cmsHTRANSFORM hTransform; | |||
867 | ||||
868 | /* https://littlecms2.blogspot.com/2009/07/less-is-more.html */ | |||
869 | ||||
870 | // double array of RGB values with max on each identity | |||
871 | hXYZ = cmsCreateXYZProfile(); | |||
872 | if (hXYZ == NULL((void*)0)) { | |||
873 | return 0; | |||
874 | } | |||
875 | ||||
876 | // transform from our profile to XYZ using doubles for highest precision | |||
877 | hTransform = cmsCreateTransform( | |||
878 | self->profile, | |||
879 | TYPE_RGB_DBL(((1) << 22)|((4) << 16)|((3) << 3)|(0)), | |||
880 | hXYZ, | |||
881 | TYPE_XYZ_DBL(((1) << 22)|((9) << 16)|((3) << 3)|(0)), | |||
882 | INTENT_RELATIVE_COLORIMETRIC1, | |||
883 | cmsFLAGS_NOCACHE0x0040 | cmsFLAGS_NOOPTIMIZE0x0100); | |||
884 | cmsCloseProfile(hXYZ); | |||
885 | if (hTransform == NULL((void*)0)) { | |||
886 | return 0; | |||
887 | } | |||
888 | ||||
889 | cmsDoTransform(hTransform, (void *)input, result, 3); | |||
890 | cmsDeleteTransform(hTransform); | |||
891 | return 1; | |||
892 | } | |||
893 | ||||
894 | static cmsBool | |||
895 | _check_intent( | |||
896 | int clut, | |||
897 | cmsHPROFILE hProfile, | |||
898 | cmsUInt32Number Intent, | |||
899 | cmsUInt32Number UsedDirection) { | |||
900 | if (clut) { | |||
901 | return cmsIsCLUT(hProfile, Intent, UsedDirection); | |||
902 | } else { | |||
903 | return cmsIsIntentSupported(hProfile, Intent, UsedDirection); | |||
904 | } | |||
905 | } | |||
906 | ||||
907 | #define INTENTS200 200 | |||
908 | ||||
909 | static PyObject * | |||
910 | _is_intent_supported(CmsProfileObject *self, int clut) { | |||
911 | PyObject *result; | |||
912 | int n; | |||
913 | int i; | |||
914 | cmsUInt32Number intent_ids[INTENTS200]; | |||
915 | char *intent_descs[INTENTS200]; | |||
916 | ||||
917 | result = PyDict_New(); | |||
918 | if (result == NULL((void*)0)) { | |||
919 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
920 | return Py_None(&_Py_NoneStruct); | |||
921 | } | |||
922 | ||||
923 | n = cmsGetSupportedIntents(INTENTS200, intent_ids, intent_descs); | |||
924 | for (i = 0; i < n; i++) { | |||
925 | int intent = (int)intent_ids[i]; | |||
926 | PyObject *id; | |||
927 | PyObject *entry; | |||
928 | ||||
929 | /* Only valid for ICC Intents (otherwise we read invalid memory in lcms | |||
930 | * cmsio1.c). */ | |||
931 | if (!(intent == INTENT_PERCEPTUAL0 || intent == INTENT_RELATIVE_COLORIMETRIC1 || | |||
932 | intent == INTENT_SATURATION2 || intent == INTENT_ABSOLUTE_COLORIMETRIC3)) { | |||
933 | continue; | |||
934 | } | |||
935 | ||||
936 | id = PyLong_FromLong((long)intent); | |||
937 | entry = Py_BuildValue_Py_BuildValue_SizeT( | |||
938 | "(OOO)", | |||
939 | _check_intent(clut, self->profile, intent, LCMS_USED_AS_INPUT0) ? Py_True((PyObject *) &_Py_TrueStruct) | |||
940 | : Py_False((PyObject *) &_Py_FalseStruct), | |||
941 | _check_intent(clut, self->profile, intent, LCMS_USED_AS_OUTPUT1) ? Py_True((PyObject *) &_Py_TrueStruct) | |||
942 | : Py_False((PyObject *) &_Py_FalseStruct), | |||
943 | _check_intent(clut, self->profile, intent, LCMS_USED_AS_PROOF2) ? Py_True((PyObject *) &_Py_TrueStruct) | |||
944 | : Py_False((PyObject *) &_Py_FalseStruct)); | |||
945 | if (id == NULL((void*)0) || entry == NULL((void*)0)) { | |||
946 | Py_XDECREF(id)_Py_XDECREF(((PyObject*)(id))); | |||
947 | Py_XDECREF(entry)_Py_XDECREF(((PyObject*)(entry))); | |||
948 | Py_XDECREF(result)_Py_XDECREF(((PyObject*)(result))); | |||
949 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
950 | return Py_None(&_Py_NoneStruct); | |||
951 | } | |||
952 | PyDict_SetItem(result, id, entry); | |||
953 | } | |||
954 | return result; | |||
955 | } | |||
956 | ||||
957 | /* -------------------------------------------------------------------- */ | |||
958 | /* Python interface setup */ | |||
959 | ||||
960 | static PyMethodDef pyCMSdll_methods[] = { | |||
961 | ||||
962 | {"profile_open", cms_profile_open, METH_VARARGS0x0001}, | |||
963 | {"profile_frombytes", cms_profile_fromstring, METH_VARARGS0x0001}, | |||
964 | {"profile_fromstring", cms_profile_fromstring, METH_VARARGS0x0001}, | |||
965 | {"profile_tobytes", cms_profile_tobytes, METH_VARARGS0x0001}, | |||
966 | ||||
967 | /* profile and transform functions */ | |||
968 | {"buildTransform", buildTransform, METH_VARARGS0x0001}, | |||
969 | {"buildProofTransform", buildProofTransform, METH_VARARGS0x0001}, | |||
970 | {"createProfile", createProfile, METH_VARARGS0x0001}, | |||
971 | ||||
972 | /* platform specific tools */ | |||
973 | #ifdef _WIN32 | |||
974 | {"get_display_profile_win32", cms_get_display_profile_win32, METH_VARARGS0x0001}, | |||
975 | #endif | |||
976 | ||||
977 | {NULL((void*)0), NULL((void*)0)}}; | |||
978 | ||||
979 | static struct PyMethodDef cms_profile_methods[] = { | |||
980 | {"is_intent_supported", (PyCFunction)cms_profile_is_intent_supported, METH_VARARGS0x0001}, | |||
981 | {NULL((void*)0), NULL((void*)0)} /* sentinel */ | |||
982 | }; | |||
983 | ||||
984 | static PyObject * | |||
985 | cms_profile_getattr_rendering_intent(CmsProfileObject *self, void *closure) { | |||
986 | return PyLong_FromLong(cmsGetHeaderRenderingIntent(self->profile)); | |||
987 | } | |||
988 | ||||
989 | /* New-style unicode interfaces. */ | |||
990 | static PyObject * | |||
991 | cms_profile_getattr_copyright(CmsProfileObject *self, void *closure) { | |||
992 | return _profile_read_mlu(self, cmsSigCopyrightTag); | |||
993 | } | |||
994 | ||||
995 | static PyObject * | |||
996 | cms_profile_getattr_target(CmsProfileObject *self, void *closure) { | |||
997 | return _profile_read_mlu(self, cmsSigCharTargetTag); | |||
998 | } | |||
999 | ||||
1000 | static PyObject * | |||
1001 | cms_profile_getattr_manufacturer(CmsProfileObject *self, void *closure) { | |||
1002 | return _profile_read_mlu(self, cmsSigDeviceMfgDescTag); | |||
1003 | } | |||
1004 | ||||
1005 | static PyObject * | |||
1006 | cms_profile_getattr_model(CmsProfileObject *self, void *closure) { | |||
1007 | return _profile_read_mlu(self, cmsSigDeviceModelDescTag); | |||
1008 | } | |||
1009 | ||||
1010 | static PyObject * | |||
1011 | cms_profile_getattr_profile_description(CmsProfileObject *self, void *closure) { | |||
1012 | return _profile_read_mlu(self, cmsSigProfileDescriptionTag); | |||
1013 | } | |||
1014 | ||||
1015 | static PyObject * | |||
1016 | cms_profile_getattr_screening_description(CmsProfileObject *self, void *closure) { | |||
1017 | return _profile_read_mlu(self, cmsSigScreeningDescTag); | |||
1018 | } | |||
1019 | ||||
1020 | static PyObject * | |||
1021 | cms_profile_getattr_viewing_condition(CmsProfileObject *self, void *closure) { | |||
1022 | return _profile_read_mlu(self, cmsSigViewingCondDescTag); | |||
1023 | } | |||
1024 | ||||
1025 | static PyObject * | |||
1026 | cms_profile_getattr_creation_date(CmsProfileObject *self, void *closure) { | |||
1027 | cmsBool result; | |||
1028 | struct tm ct; | |||
1029 | ||||
1030 | result = cmsGetHeaderCreationDateTime(self->profile, &ct); | |||
1031 | if (!result) { | |||
1032 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1033 | return Py_None(&_Py_NoneStruct); | |||
1034 | } | |||
1035 | ||||
1036 | return PyDateTime_FromDateAndTime(PyDateTimeAPI->DateTime_FromDateAndTime(1900 + ct.tm_year, ct.tm_mon, ct.tm_mday, ct.tm_hour, ct.tm_min, ct.tm_sec, 0, ( &_Py_NoneStruct), PyDateTimeAPI->DateTimeType) | |||
1037 | 1900 + ct.tm_year, ct.tm_mon, ct.tm_mday, ct.tm_hour, ct.tm_min, ct.tm_sec, 0)PyDateTimeAPI->DateTime_FromDateAndTime(1900 + ct.tm_year, ct.tm_mon, ct.tm_mday, ct.tm_hour, ct.tm_min, ct.tm_sec, 0, ( &_Py_NoneStruct), PyDateTimeAPI->DateTimeType); | |||
1038 | } | |||
1039 | ||||
1040 | static PyObject * | |||
1041 | cms_profile_getattr_version(CmsProfileObject *self, void *closure) { | |||
1042 | cmsFloat64Number version = cmsGetProfileVersion(self->profile); | |||
1043 | return PyFloat_FromDouble(version); | |||
1044 | } | |||
1045 | ||||
1046 | static PyObject * | |||
1047 | cms_profile_getattr_icc_version(CmsProfileObject *self, void *closure) { | |||
1048 | return PyLong_FromLong((long)cmsGetEncodedICCversion(self->profile)); | |||
1049 | } | |||
1050 | ||||
1051 | static PyObject * | |||
1052 | cms_profile_getattr_attributes(CmsProfileObject *self, void *closure) { | |||
1053 | cmsUInt64Number attr; | |||
1054 | cmsGetHeaderAttributes(self->profile, &attr); | |||
1055 | /* This works just as well on Windows (LLP64), 32-bit Linux | |||
1056 | (ILP32) and 64-bit Linux (LP64) systems. */ | |||
1057 | return PyLong_FromUnsignedLongLong((unsigned long long)attr); | |||
1058 | } | |||
1059 | ||||
1060 | static PyObject * | |||
1061 | cms_profile_getattr_header_flags(CmsProfileObject *self, void *closure) { | |||
1062 | cmsUInt32Number flags = cmsGetHeaderFlags(self->profile); | |||
1063 | return PyLong_FromLong(flags); | |||
1064 | } | |||
1065 | ||||
1066 | static PyObject * | |||
1067 | cms_profile_getattr_header_manufacturer(CmsProfileObject *self, void *closure) { | |||
1068 | return _profile_read_int_as_string(cmsGetHeaderManufacturer(self->profile)); | |||
1069 | } | |||
1070 | ||||
1071 | static PyObject * | |||
1072 | cms_profile_getattr_header_model(CmsProfileObject *self, void *closure) { | |||
1073 | return _profile_read_int_as_string(cmsGetHeaderModel(self->profile)); | |||
1074 | } | |||
1075 | ||||
1076 | static PyObject * | |||
1077 | cms_profile_getattr_device_class(CmsProfileObject *self, void *closure) { | |||
1078 | return _profile_read_int_as_string(cmsGetDeviceClass(self->profile)); | |||
1079 | } | |||
1080 | ||||
1081 | static PyObject * | |||
1082 | cms_profile_getattr_connection_space(CmsProfileObject *self, void *closure) { | |||
1083 | return _profile_read_int_as_string(cmsGetPCS(self->profile)); | |||
1084 | } | |||
1085 | ||||
1086 | static PyObject * | |||
1087 | cms_profile_getattr_xcolor_space(CmsProfileObject *self, void *closure) { | |||
1088 | return _profile_read_int_as_string(cmsGetColorSpace(self->profile)); | |||
1089 | } | |||
1090 | ||||
1091 | static PyObject * | |||
1092 | cms_profile_getattr_profile_id(CmsProfileObject *self, void *closure) { | |||
1093 | cmsUInt8Number id[16]; | |||
1094 | cmsGetHeaderProfileID(self->profile, id); | |||
1095 | return PyBytes_FromStringAndSize((char *)id, 16); | |||
1096 | } | |||
1097 | ||||
1098 | static PyObject * | |||
1099 | cms_profile_getattr_is_matrix_shaper(CmsProfileObject *self, void *closure) { | |||
1100 | return PyBool_FromLong((long)cmsIsMatrixShaper(self->profile)); | |||
1101 | } | |||
1102 | ||||
1103 | static PyObject * | |||
1104 | cms_profile_getattr_technology(CmsProfileObject *self, void *closure) { | |||
1105 | return _profile_read_signature(self, cmsSigTechnologyTag); | |||
1106 | } | |||
1107 | ||||
1108 | static PyObject * | |||
1109 | cms_profile_getattr_colorimetric_intent(CmsProfileObject *self, void *closure) { | |||
1110 | return _profile_read_signature(self, cmsSigColorimetricIntentImageStateTag); | |||
1111 | } | |||
1112 | ||||
1113 | static PyObject * | |||
1114 | cms_profile_getattr_perceptual_rendering_intent_gamut( | |||
1115 | CmsProfileObject *self, void *closure) { | |||
1116 | return _profile_read_signature(self, cmsSigPerceptualRenderingIntentGamutTag); | |||
1117 | } | |||
1118 | ||||
1119 | static PyObject * | |||
1120 | cms_profile_getattr_saturation_rendering_intent_gamut( | |||
1121 | CmsProfileObject *self, void *closure) { | |||
1122 | return _profile_read_signature(self, cmsSigSaturationRenderingIntentGamutTag); | |||
1123 | } | |||
1124 | ||||
1125 | static PyObject * | |||
1126 | cms_profile_getattr_red_colorant(CmsProfileObject *self, void *closure) { | |||
1127 | if (!cmsIsMatrixShaper(self->profile)) { | |||
1128 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1129 | return Py_None(&_Py_NoneStruct); | |||
1130 | } | |||
1131 | return _profile_read_ciexyz(self, cmsSigRedColorantTag, 0); | |||
1132 | } | |||
1133 | ||||
1134 | static PyObject * | |||
1135 | cms_profile_getattr_green_colorant(CmsProfileObject *self, void *closure) { | |||
1136 | if (!cmsIsMatrixShaper(self->profile)) { | |||
1137 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1138 | return Py_None(&_Py_NoneStruct); | |||
1139 | } | |||
1140 | return _profile_read_ciexyz(self, cmsSigGreenColorantTag, 0); | |||
1141 | } | |||
1142 | ||||
1143 | static PyObject * | |||
1144 | cms_profile_getattr_blue_colorant(CmsProfileObject *self, void *closure) { | |||
1145 | if (!cmsIsMatrixShaper(self->profile)) { | |||
1146 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1147 | return Py_None(&_Py_NoneStruct); | |||
1148 | } | |||
1149 | return _profile_read_ciexyz(self, cmsSigBlueColorantTag, 0); | |||
1150 | } | |||
1151 | ||||
1152 | static PyObject * | |||
1153 | cms_profile_getattr_media_white_point_temperature( | |||
1154 | CmsProfileObject *self, void *closure) { | |||
1155 | cmsCIEXYZ *XYZ; | |||
1156 | cmsCIExyY xyY; | |||
1157 | cmsFloat64Number tempK; | |||
1158 | cmsTagSignature info = cmsSigMediaWhitePointTag; | |||
1159 | cmsBool result; | |||
1160 | ||||
1161 | if (!cmsIsTag(self->profile, info)) { | |||
1162 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1163 | return Py_None(&_Py_NoneStruct); | |||
1164 | } | |||
1165 | ||||
1166 | XYZ = (cmsCIEXYZ *)cmsReadTag(self->profile, info); | |||
1167 | if (XYZ == NULL((void*)0) || XYZ->X == 0) { | |||
1168 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1169 | return Py_None(&_Py_NoneStruct); | |||
1170 | } | |||
1171 | ||||
1172 | cmsXYZ2xyY(&xyY, XYZ); | |||
1173 | result = cmsTempFromWhitePoint(&tempK, &xyY); | |||
1174 | if (!result) { | |||
1175 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1176 | return Py_None(&_Py_NoneStruct); | |||
1177 | } | |||
1178 | return PyFloat_FromDouble(tempK); | |||
1179 | } | |||
1180 | ||||
1181 | static PyObject * | |||
1182 | cms_profile_getattr_media_white_point(CmsProfileObject *self, void *closure) { | |||
1183 | return _profile_read_ciexyz(self, cmsSigMediaWhitePointTag, 0); | |||
1184 | } | |||
1185 | ||||
1186 | static PyObject * | |||
1187 | cms_profile_getattr_media_black_point(CmsProfileObject *self, void *closure) { | |||
1188 | return _profile_read_ciexyz(self, cmsSigMediaBlackPointTag, 0); | |||
1189 | } | |||
1190 | ||||
1191 | static PyObject * | |||
1192 | cms_profile_getattr_luminance(CmsProfileObject *self, void *closure) { | |||
1193 | return _profile_read_ciexyz(self, cmsSigLuminanceTag, 0); | |||
1194 | } | |||
1195 | ||||
1196 | static PyObject * | |||
1197 | cms_profile_getattr_chromatic_adaptation(CmsProfileObject *self, void *closure) { | |||
1198 | return _profile_read_ciexyz(self, cmsSigChromaticAdaptationTag, 1); | |||
1199 | } | |||
1200 | ||||
1201 | static PyObject * | |||
1202 | cms_profile_getattr_chromaticity(CmsProfileObject *self, void *closure) { | |||
1203 | return _profile_read_ciexyy_triple(self, cmsSigChromaticityTag); | |||
1204 | } | |||
1205 | ||||
1206 | static PyObject * | |||
1207 | cms_profile_getattr_red_primary(CmsProfileObject *self, void *closure) { | |||
1208 | cmsBool result = 0; | |||
1209 | cmsCIEXYZTRIPLE primaries; | |||
1210 | ||||
1211 | if (cmsIsMatrixShaper(self->profile)) { | |||
1212 | result = _calculate_rgb_primaries(self, &primaries); | |||
1213 | } | |||
1214 | if (!result) { | |||
1215 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1216 | return Py_None(&_Py_NoneStruct); | |||
1217 | } | |||
1218 | ||||
1219 | return _xyz_py(&primaries.Red); | |||
1220 | } | |||
1221 | ||||
1222 | static PyObject * | |||
1223 | cms_profile_getattr_green_primary(CmsProfileObject *self, void *closure) { | |||
1224 | cmsBool result = 0; | |||
1225 | cmsCIEXYZTRIPLE primaries; | |||
1226 | ||||
1227 | if (cmsIsMatrixShaper(self->profile)) { | |||
1228 | result = _calculate_rgb_primaries(self, &primaries); | |||
1229 | } | |||
1230 | if (!result) { | |||
1231 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1232 | return Py_None(&_Py_NoneStruct); | |||
1233 | } | |||
1234 | ||||
1235 | return _xyz_py(&primaries.Green); | |||
1236 | } | |||
1237 | ||||
1238 | static PyObject * | |||
1239 | cms_profile_getattr_blue_primary(CmsProfileObject *self, void *closure) { | |||
1240 | cmsBool result = 0; | |||
1241 | cmsCIEXYZTRIPLE primaries; | |||
1242 | ||||
1243 | if (cmsIsMatrixShaper(self->profile)) { | |||
1244 | result = _calculate_rgb_primaries(self, &primaries); | |||
1245 | } | |||
1246 | if (!result) { | |||
1247 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1248 | return Py_None(&_Py_NoneStruct); | |||
1249 | } | |||
1250 | ||||
1251 | return _xyz_py(&primaries.Blue); | |||
1252 | } | |||
1253 | ||||
1254 | static PyObject * | |||
1255 | cms_profile_getattr_colorant_table(CmsProfileObject *self, void *closure) { | |||
1256 | return _profile_read_named_color_list(self, cmsSigColorantTableTag); | |||
1257 | } | |||
1258 | ||||
1259 | static PyObject * | |||
1260 | cms_profile_getattr_colorant_table_out(CmsProfileObject *self, void *closure) { | |||
1261 | return _profile_read_named_color_list(self, cmsSigColorantTableOutTag); | |||
1262 | } | |||
1263 | ||||
1264 | static PyObject * | |||
1265 | cms_profile_getattr_is_intent_supported(CmsProfileObject *self, void *closure) { | |||
1266 | return _is_intent_supported(self, 0); | |||
1267 | } | |||
1268 | ||||
1269 | static PyObject * | |||
1270 | cms_profile_getattr_is_clut(CmsProfileObject *self, void *closure) { | |||
1271 | return _is_intent_supported(self, 1); | |||
1272 | } | |||
1273 | ||||
1274 | static const char * | |||
1275 | _illu_map(int i) { | |||
1276 | switch (i) { | |||
1277 | case 0: | |||
1278 | return "unknown"; | |||
1279 | case 1: | |||
1280 | return "D50"; | |||
1281 | case 2: | |||
1282 | return "D65"; | |||
1283 | case 3: | |||
1284 | return "D93"; | |||
1285 | case 4: | |||
1286 | return "F2"; | |||
1287 | case 5: | |||
1288 | return "D55"; | |||
1289 | case 6: | |||
1290 | return "A"; | |||
1291 | case 7: | |||
1292 | return "E"; | |||
1293 | case 8: | |||
1294 | return "F8"; | |||
1295 | default: | |||
1296 | return NULL((void*)0); | |||
1297 | } | |||
1298 | } | |||
1299 | ||||
1300 | static PyObject * | |||
1301 | cms_profile_getattr_icc_measurement_condition(CmsProfileObject *self, void *closure) { | |||
1302 | cmsICCMeasurementConditions *mc; | |||
1303 | cmsTagSignature info = cmsSigMeasurementTag; | |||
1304 | const char *geo; | |||
1305 | ||||
1306 | if (!cmsIsTag(self->profile, info)) { | |||
1307 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1308 | return Py_None(&_Py_NoneStruct); | |||
1309 | } | |||
1310 | ||||
1311 | mc = (cmsICCMeasurementConditions *)cmsReadTag(self->profile, info); | |||
1312 | if (!mc) { | |||
1313 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1314 | return Py_None(&_Py_NoneStruct); | |||
1315 | } | |||
1316 | ||||
1317 | if (mc->Geometry == 1) { | |||
1318 | geo = "45/0, 0/45"; | |||
1319 | } else if (mc->Geometry == 2) { | |||
1320 | geo = "0d, d/0"; | |||
1321 | } else { | |||
1322 | geo = "unknown"; | |||
1323 | } | |||
1324 | ||||
1325 | return Py_BuildValue_Py_BuildValue_SizeT( | |||
1326 | "{s:i,s:(ddd),s:s,s:d,s:s}", | |||
1327 | "observer", | |||
1328 | mc->Observer, | |||
1329 | "backing", | |||
1330 | mc->Backing.X, | |||
1331 | mc->Backing.Y, | |||
1332 | mc->Backing.Z, | |||
1333 | "geo", | |||
1334 | geo, | |||
1335 | "flare", | |||
1336 | mc->Flare, | |||
1337 | "illuminant_type", | |||
1338 | _illu_map(mc->IlluminantType)); | |||
1339 | } | |||
1340 | ||||
1341 | static PyObject * | |||
1342 | cms_profile_getattr_icc_viewing_condition(CmsProfileObject *self, void *closure) { | |||
1343 | cmsICCViewingConditions *vc; | |||
1344 | cmsTagSignature info = cmsSigViewingConditionsTag; | |||
1345 | ||||
1346 | if (!cmsIsTag(self->profile, info)) { | |||
1347 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1348 | return Py_None(&_Py_NoneStruct); | |||
1349 | } | |||
1350 | ||||
1351 | vc = (cmsICCViewingConditions *)cmsReadTag(self->profile, info); | |||
1352 | if (!vc) { | |||
1353 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
1354 | return Py_None(&_Py_NoneStruct); | |||
1355 | } | |||
1356 | ||||
1357 | return Py_BuildValue_Py_BuildValue_SizeT( | |||
1358 | "{s:(ddd),s:(ddd),s:s}", | |||
1359 | "illuminant", | |||
1360 | vc->IlluminantXYZ.X, | |||
1361 | vc->IlluminantXYZ.Y, | |||
1362 | vc->IlluminantXYZ.Z, | |||
1363 | "surround", | |||
1364 | vc->SurroundXYZ.X, | |||
1365 | vc->SurroundXYZ.Y, | |||
1366 | vc->SurroundXYZ.Z, | |||
1367 | "illuminant_type", | |||
1368 | _illu_map(vc->IlluminantType)); | |||
1369 | } | |||
1370 | ||||
1371 | static struct PyGetSetDef cms_profile_getsetters[] = { | |||
1372 | /* New style interfaces. */ | |||
1373 | {"rendering_intent", (getter)cms_profile_getattr_rendering_intent}, | |||
1374 | {"creation_date", (getter)cms_profile_getattr_creation_date}, | |||
1375 | {"copyright", (getter)cms_profile_getattr_copyright}, | |||
1376 | {"target", (getter)cms_profile_getattr_target}, | |||
1377 | {"manufacturer", (getter)cms_profile_getattr_manufacturer}, | |||
1378 | {"model", (getter)cms_profile_getattr_model}, | |||
1379 | {"profile_description", (getter)cms_profile_getattr_profile_description}, | |||
1380 | {"screening_description", (getter)cms_profile_getattr_screening_description}, | |||
1381 | {"viewing_condition", (getter)cms_profile_getattr_viewing_condition}, | |||
1382 | {"version", (getter)cms_profile_getattr_version}, | |||
1383 | {"icc_version", (getter)cms_profile_getattr_icc_version}, | |||
1384 | {"attributes", (getter)cms_profile_getattr_attributes}, | |||
1385 | {"header_flags", (getter)cms_profile_getattr_header_flags}, | |||
1386 | {"header_manufacturer", (getter)cms_profile_getattr_header_manufacturer}, | |||
1387 | {"header_model", (getter)cms_profile_getattr_header_model}, | |||
1388 | {"device_class", (getter)cms_profile_getattr_device_class}, | |||
1389 | {"connection_space", (getter)cms_profile_getattr_connection_space}, | |||
1390 | {"xcolor_space", (getter)cms_profile_getattr_xcolor_space}, | |||
1391 | {"profile_id", (getter)cms_profile_getattr_profile_id}, | |||
1392 | {"is_matrix_shaper", (getter)cms_profile_getattr_is_matrix_shaper}, | |||
1393 | {"technology", (getter)cms_profile_getattr_technology}, | |||
1394 | {"colorimetric_intent", (getter)cms_profile_getattr_colorimetric_intent}, | |||
1395 | {"perceptual_rendering_intent_gamut", | |||
1396 | (getter)cms_profile_getattr_perceptual_rendering_intent_gamut}, | |||
1397 | {"saturation_rendering_intent_gamut", | |||
1398 | (getter)cms_profile_getattr_saturation_rendering_intent_gamut}, | |||
1399 | {"red_colorant", (getter)cms_profile_getattr_red_colorant}, | |||
1400 | {"green_colorant", (getter)cms_profile_getattr_green_colorant}, | |||
1401 | {"blue_colorant", (getter)cms_profile_getattr_blue_colorant}, | |||
1402 | {"red_primary", (getter)cms_profile_getattr_red_primary}, | |||
1403 | {"green_primary", (getter)cms_profile_getattr_green_primary}, | |||
1404 | {"blue_primary", (getter)cms_profile_getattr_blue_primary}, | |||
1405 | {"media_white_point_temperature", | |||
1406 | (getter)cms_profile_getattr_media_white_point_temperature}, | |||
1407 | {"media_white_point", (getter)cms_profile_getattr_media_white_point}, | |||
1408 | {"media_black_point", (getter)cms_profile_getattr_media_black_point}, | |||
1409 | {"luminance", (getter)cms_profile_getattr_luminance}, | |||
1410 | {"chromatic_adaptation", (getter)cms_profile_getattr_chromatic_adaptation}, | |||
1411 | {"chromaticity", (getter)cms_profile_getattr_chromaticity}, | |||
1412 | {"colorant_table", (getter)cms_profile_getattr_colorant_table}, | |||
1413 | {"colorant_table_out", (getter)cms_profile_getattr_colorant_table_out}, | |||
1414 | {"intent_supported", (getter)cms_profile_getattr_is_intent_supported}, | |||
1415 | {"clut", (getter)cms_profile_getattr_is_clut}, | |||
1416 | {"icc_measurement_condition", | |||
1417 | (getter)cms_profile_getattr_icc_measurement_condition}, | |||
1418 | {"icc_viewing_condition", (getter)cms_profile_getattr_icc_viewing_condition}, | |||
1419 | ||||
1420 | {NULL((void*)0)}}; | |||
1421 | ||||
1422 | static PyTypeObject CmsProfile_Type = { | |||
1423 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, "PIL._imagingcms.CmsProfile", /*tp_name */ | |||
1424 | sizeof(CmsProfileObject), | |||
1425 | 0, /*tp_basicsize, tp_itemsize */ | |||
1426 | /* methods */ | |||
1427 | (destructor)cms_profile_dealloc, /*tp_dealloc*/ | |||
1428 | 0, /*tp_print*/ | |||
1429 | 0, /*tp_getattr*/ | |||
1430 | 0, /*tp_setattr*/ | |||
1431 | 0, /*tp_compare*/ | |||
1432 | 0, /*tp_repr*/ | |||
1433 | 0, /*tp_as_number */ | |||
1434 | 0, /*tp_as_sequence */ | |||
1435 | 0, /*tp_as_mapping */ | |||
1436 | 0, /*tp_hash*/ | |||
1437 | 0, /*tp_call*/ | |||
1438 | 0, /*tp_str*/ | |||
1439 | 0, /*tp_getattro*/ | |||
1440 | 0, /*tp_setattro*/ | |||
1441 | 0, /*tp_as_buffer*/ | |||
1442 | Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0), /*tp_flags*/ | |||
1443 | 0, /*tp_doc*/ | |||
1444 | 0, /*tp_traverse*/ | |||
1445 | 0, /*tp_clear*/ | |||
1446 | 0, /*tp_richcompare*/ | |||
1447 | 0, /*tp_weaklistoffset*/ | |||
1448 | 0, /*tp_iter*/ | |||
1449 | 0, /*tp_iternext*/ | |||
1450 | cms_profile_methods, /*tp_methods*/ | |||
1451 | 0, /*tp_members*/ | |||
1452 | cms_profile_getsetters, /*tp_getset*/ | |||
1453 | }; | |||
1454 | ||||
1455 | static struct PyMethodDef cms_transform_methods[] = { | |||
1456 | {"apply", (PyCFunction)cms_transform_apply, 1}, {NULL((void*)0), NULL((void*)0)} /* sentinel */ | |||
1457 | }; | |||
1458 | ||||
1459 | static PyObject * | |||
1460 | cms_transform_getattr_inputMode(CmsTransformObject *self, void *closure) { | |||
1461 | return PyUnicode_FromString(self->mode_in); | |||
1462 | } | |||
1463 | ||||
1464 | static PyObject * | |||
1465 | cms_transform_getattr_outputMode(CmsTransformObject *self, void *closure) { | |||
1466 | return PyUnicode_FromString(self->mode_out); | |||
1467 | } | |||
1468 | ||||
1469 | static struct PyGetSetDef cms_transform_getsetters[] = { | |||
1470 | {"inputMode", (getter)cms_transform_getattr_inputMode}, | |||
1471 | {"outputMode", (getter)cms_transform_getattr_outputMode}, | |||
1472 | {NULL((void*)0)}}; | |||
1473 | ||||
1474 | static PyTypeObject CmsTransform_Type = { | |||
1475 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, "CmsTransform", | |||
1476 | sizeof(CmsTransformObject), | |||
1477 | 0, | |||
1478 | /* methods */ | |||
1479 | (destructor)cms_transform_dealloc, /*tp_dealloc*/ | |||
1480 | 0, /*tp_print*/ | |||
1481 | 0, /*tp_getattr*/ | |||
1482 | 0, /*tp_setattr*/ | |||
1483 | 0, /*tp_compare*/ | |||
1484 | 0, /*tp_repr*/ | |||
1485 | 0, /*tp_as_number */ | |||
1486 | 0, /*tp_as_sequence */ | |||
1487 | 0, /*tp_as_mapping */ | |||
1488 | 0, /*tp_hash*/ | |||
1489 | 0, /*tp_call*/ | |||
1490 | 0, /*tp_str*/ | |||
1491 | 0, /*tp_getattro*/ | |||
1492 | 0, /*tp_setattro*/ | |||
1493 | 0, /*tp_as_buffer*/ | |||
1494 | Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0), /*tp_flags*/ | |||
1495 | 0, /*tp_doc*/ | |||
1496 | 0, /*tp_traverse*/ | |||
1497 | 0, /*tp_clear*/ | |||
1498 | 0, /*tp_richcompare*/ | |||
1499 | 0, /*tp_weaklistoffset*/ | |||
1500 | 0, /*tp_iter*/ | |||
1501 | 0, /*tp_iternext*/ | |||
1502 | cms_transform_methods, /*tp_methods*/ | |||
1503 | 0, /*tp_members*/ | |||
1504 | cms_transform_getsetters, /*tp_getset*/ | |||
1505 | }; | |||
1506 | ||||
1507 | static int | |||
1508 | setup_module(PyObject *m) { | |||
1509 | PyObject *d; | |||
1510 | PyObject *v; | |||
1511 | int vn; | |||
1512 | ||||
1513 | CmsProfile_Type.tp_new = PyType_GenericNew; | |||
1514 | ||||
1515 | /* Ready object types */ | |||
1516 | PyType_Ready(&CmsProfile_Type); | |||
1517 | PyType_Ready(&CmsTransform_Type); | |||
1518 | ||||
1519 | Py_INCREF(&CmsProfile_Type)_Py_INCREF(((PyObject*)(&CmsProfile_Type))); | |||
1520 | PyModule_AddObject(m, "CmsProfile", (PyObject *)&CmsProfile_Type); | |||
1521 | ||||
1522 | d = PyModule_GetDict(m); | |||
1523 | ||||
1524 | /* this check is also in PIL.features.pilinfo() */ | |||
1525 | #if LCMS_VERSION2090 < 2070 | |||
1526 | vn = LCMS_VERSION2090; | |||
1527 | #else | |||
1528 | vn = cmsGetEncodedCMMversion(); | |||
1529 | #endif | |||
1530 | if (vn % 10) { | |||
1531 | v = PyUnicode_FromFormat("%d.%d.%d", vn / 1000, (vn / 10) % 100, vn % 10); | |||
| ||||
1532 | } else { | |||
1533 | v = PyUnicode_FromFormat("%d.%d", vn / 1000, (vn / 10) % 100); | |||
1534 | } | |||
1535 | PyDict_SetItemString(d, "littlecms_version", v); | |||
1536 | ||||
1537 | return 0; | |||
1538 | } | |||
1539 | ||||
1540 | PyMODINIT_FUNCPyObject* | |||
1541 | PyInit__imagingcms(void) { | |||
1542 | PyObject *m; | |||
1543 | ||||
1544 | static PyModuleDef module_def = { | |||
1545 | PyModuleDef_HEAD_INIT{ { 1, ((void*)0) }, ((void*)0), 0, ((void*)0), }, | |||
1546 | "_imagingcms", /* m_name */ | |||
1547 | NULL((void*)0), /* m_doc */ | |||
1548 | -1, /* m_size */ | |||
1549 | pyCMSdll_methods, /* m_methods */ | |||
1550 | }; | |||
1551 | ||||
1552 | m = PyModule_Create(&module_def)PyModule_Create2(&module_def, 1013); | |||
1553 | ||||
1554 | if (setup_module(m) < 0) { | |||
| ||||
1555 | return NULL((void*)0); | |||
1556 | } | |||
1557 | ||||
1558 | PyDateTime_IMPORTPyDateTimeAPI = (PyDateTime_CAPI *)PyCapsule_Import("datetime.datetime_CAPI" , 0); | |||
1559 | ||||
1560 | return m; | |||
1561 | } |
1 | #ifndef PyUnicode_FromFormat |
2 | struct _object; |
3 | typedef struct _object PyObject; |
4 | PyObject* clang_analyzer_PyObject_New_Reference(); |
5 | PyObject* PyUnicode_FromFormat(const char *format, ...) { |
6 | return clang_analyzer_PyObject_New_Reference(); |
7 | } |
8 | #else |
9 | #warning "API PyUnicode_FromFormat is defined as a macro." |
10 | #endif |