Bug Summary

File:_imagingcms.c
Warning:line 1531, column 13
PyObject ownership leak with reference count of 1

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name _imagingcms.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-output=html -analyzer-checker=python -analyzer-disable-checker=deadcode -analyzer-config prune-paths=true,suppress-c++-stdlib=true,suppress-null-return-paths=false,crosscheck-with-z3=true,model-path=/opt/pyrefcon/lib/pyrefcon/models/models -analyzer-config experimental-enable-naive-ctu-analysis=true,ctu-dir=/tmp/pyrefcon/Pillow/csa-scan,ctu-index-name=/tmp/pyrefcon/Pillow/csa-scan/externalDefMap.txt,ctu-invocation-list=/tmp/pyrefcon/Pillow/csa-scan/invocations.yaml,display-ctu-progress=false -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -fcoverage-compilation-dir=/tmp/pyrefcon/Pillow -resource-dir /opt/pyrefcon/lib/clang/13.0.0 -isystem /opt/pyrefcon/lib/pyrefcon/models/python3.8 -D NDEBUG -D _FORTIFY_SOURCE=2 -I /usr/include/freetype2 -I /usr/include/openjpeg-2.3 -I /tmp/pyrefcon/Pillow -I /usr/include/x86_64-linux-gnu -I /usr/include/fribidi -I /usr/include -internal-isystem /opt/pyrefcon/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-result -Wsign-compare -Wall -Wformat -Werror=format-security -Wformat -Werror=format-security -Wdate-time -fdebug-compilation-dir=/tmp/pyrefcon/Pillow -ferror-limit 19 -fwrapv -pthread -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/pyrefcon/Pillow/csa-scan/reports -x c src/_imagingcms.c

src/_imagingcms.c

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 "\
22pyCMS\n\
23a Python / PIL interface to the littleCMS ICC Color Management System\n\
24Copyright (C) 2002-2003 Kevin Cazabon\n\
25kevin@cazabon.com\n\
26http://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
78typedef struct {
79 PyObject_HEADPyObject ob_base; cmsHPROFILE profile;
80} CmsProfileObject;
81
82static 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
86static PyObject *
87cms_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
100static PyObject *
101cms_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
118static PyObject *
119cms_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
137static PyObject *
138cms_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
175static void
176cms_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
183typedef struct {
184 PyObject_HEADPyObject ob_base; char mode_in[8];
185 char mode_out[8];
186 cmsHTRANSFORM transform;
187} CmsTransformObject;
188
189static 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
193static PyObject *
194cms_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
210static void
211cms_transform_dealloc(CmsTransformObject *self) {
212 cmsDeleteTransform(self->transform);
213 PyObject_DelPyObject_Free(self);
214}
215
216/* -------------------------------------------------------------------- */
217/* internal functions */
218
219static cmsUInt32Number
220findLCMStype(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
254static int
255pyCMSgetAuxChannelChannel(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
282static void
283pyCMScopyAux(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
347static int
348pyCMSdoTransform(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
376static 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
406static 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
443static PyObject *
444buildTransform(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
483static PyObject *
484buildProofTransform(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
530static PyObject *
531cms_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
554static PyObject *
555createProfile(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
599static PyObject *
600cms_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
625static PyObject *
626cms_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
660static 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
702static 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
716static 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
734static 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
742static 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
771static 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
792static 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
822static 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
862static 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
894static 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
909static 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
960static 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
979static 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
984static PyObject *
985cms_profile_getattr_rendering_intent(CmsProfileObject *self, void *closure) {
986 return PyLong_FromLong(cmsGetHeaderRenderingIntent(self->profile));
987}
988
989/* New-style unicode interfaces. */
990static PyObject *
991cms_profile_getattr_copyright(CmsProfileObject *self, void *closure) {
992 return _profile_read_mlu(self, cmsSigCopyrightTag);
993}
994
995static PyObject *
996cms_profile_getattr_target(CmsProfileObject *self, void *closure) {
997 return _profile_read_mlu(self, cmsSigCharTargetTag);
998}
999
1000static PyObject *
1001cms_profile_getattr_manufacturer(CmsProfileObject *self, void *closure) {
1002 return _profile_read_mlu(self, cmsSigDeviceMfgDescTag);
1003}
1004
1005static PyObject *
1006cms_profile_getattr_model(CmsProfileObject *self, void *closure) {
1007 return _profile_read_mlu(self, cmsSigDeviceModelDescTag);
1008}
1009
1010static PyObject *
1011cms_profile_getattr_profile_description(CmsProfileObject *self, void *closure) {
1012 return _profile_read_mlu(self, cmsSigProfileDescriptionTag);
1013}
1014
1015static PyObject *
1016cms_profile_getattr_screening_description(CmsProfileObject *self, void *closure) {
1017 return _profile_read_mlu(self, cmsSigScreeningDescTag);
1018}
1019
1020static PyObject *
1021cms_profile_getattr_viewing_condition(CmsProfileObject *self, void *closure) {
1022 return _profile_read_mlu(self, cmsSigViewingCondDescTag);
1023}
1024
1025static PyObject *
1026cms_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
1040static PyObject *
1041cms_profile_getattr_version(CmsProfileObject *self, void *closure) {
1042 cmsFloat64Number version = cmsGetProfileVersion(self->profile);
1043 return PyFloat_FromDouble(version);
1044}
1045
1046static PyObject *
1047cms_profile_getattr_icc_version(CmsProfileObject *self, void *closure) {
1048 return PyLong_FromLong((long)cmsGetEncodedICCversion(self->profile));
1049}
1050
1051static PyObject *
1052cms_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
1060static PyObject *
1061cms_profile_getattr_header_flags(CmsProfileObject *self, void *closure) {
1062 cmsUInt32Number flags = cmsGetHeaderFlags(self->profile);
1063 return PyLong_FromLong(flags);
1064}
1065
1066static PyObject *
1067cms_profile_getattr_header_manufacturer(CmsProfileObject *self, void *closure) {
1068 return _profile_read_int_as_string(cmsGetHeaderManufacturer(self->profile));
1069}
1070
1071static PyObject *
1072cms_profile_getattr_header_model(CmsProfileObject *self, void *closure) {
1073 return _profile_read_int_as_string(cmsGetHeaderModel(self->profile));
1074}
1075
1076static PyObject *
1077cms_profile_getattr_device_class(CmsProfileObject *self, void *closure) {
1078 return _profile_read_int_as_string(cmsGetDeviceClass(self->profile));
1079}
1080
1081static PyObject *
1082cms_profile_getattr_connection_space(CmsProfileObject *self, void *closure) {
1083 return _profile_read_int_as_string(cmsGetPCS(self->profile));
1084}
1085
1086static PyObject *
1087cms_profile_getattr_xcolor_space(CmsProfileObject *self, void *closure) {
1088 return _profile_read_int_as_string(cmsGetColorSpace(self->profile));
1089}
1090
1091static PyObject *
1092cms_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
1098static PyObject *
1099cms_profile_getattr_is_matrix_shaper(CmsProfileObject *self, void *closure) {
1100 return PyBool_FromLong((long)cmsIsMatrixShaper(self->profile));
1101}
1102
1103static PyObject *
1104cms_profile_getattr_technology(CmsProfileObject *self, void *closure) {
1105 return _profile_read_signature(self, cmsSigTechnologyTag);
1106}
1107
1108static PyObject *
1109cms_profile_getattr_colorimetric_intent(CmsProfileObject *self, void *closure) {
1110 return _profile_read_signature(self, cmsSigColorimetricIntentImageStateTag);
1111}
1112
1113static PyObject *
1114cms_profile_getattr_perceptual_rendering_intent_gamut(
1115 CmsProfileObject *self, void *closure) {
1116 return _profile_read_signature(self, cmsSigPerceptualRenderingIntentGamutTag);
1117}
1118
1119static PyObject *
1120cms_profile_getattr_saturation_rendering_intent_gamut(
1121 CmsProfileObject *self, void *closure) {
1122 return _profile_read_signature(self, cmsSigSaturationRenderingIntentGamutTag);
1123}
1124
1125static PyObject *
1126cms_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
1134static PyObject *
1135cms_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
1143static PyObject *
1144cms_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
1152static PyObject *
1153cms_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
1181static PyObject *
1182cms_profile_getattr_media_white_point(CmsProfileObject *self, void *closure) {
1183 return _profile_read_ciexyz(self, cmsSigMediaWhitePointTag, 0);
1184}
1185
1186static PyObject *
1187cms_profile_getattr_media_black_point(CmsProfileObject *self, void *closure) {
1188 return _profile_read_ciexyz(self, cmsSigMediaBlackPointTag, 0);
1189}
1190
1191static PyObject *
1192cms_profile_getattr_luminance(CmsProfileObject *self, void *closure) {
1193 return _profile_read_ciexyz(self, cmsSigLuminanceTag, 0);
1194}
1195
1196static PyObject *
1197cms_profile_getattr_chromatic_adaptation(CmsProfileObject *self, void *closure) {
1198 return _profile_read_ciexyz(self, cmsSigChromaticAdaptationTag, 1);
1199}
1200
1201static PyObject *
1202cms_profile_getattr_chromaticity(CmsProfileObject *self, void *closure) {
1203 return _profile_read_ciexyy_triple(self, cmsSigChromaticityTag);
1204}
1205
1206static PyObject *
1207cms_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
1222static PyObject *
1223cms_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
1238static PyObject *
1239cms_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
1254static PyObject *
1255cms_profile_getattr_colorant_table(CmsProfileObject *self, void *closure) {
1256 return _profile_read_named_color_list(self, cmsSigColorantTableTag);
1257}
1258
1259static PyObject *
1260cms_profile_getattr_colorant_table_out(CmsProfileObject *self, void *closure) {
1261 return _profile_read_named_color_list(self, cmsSigColorantTableOutTag);
1262}
1263
1264static PyObject *
1265cms_profile_getattr_is_intent_supported(CmsProfileObject *self, void *closure) {
1266 return _is_intent_supported(self, 0);
1267}
1268
1269static PyObject *
1270cms_profile_getattr_is_clut(CmsProfileObject *self, void *closure) {
1271 return _is_intent_supported(self, 1);
1272}
1273
1274static 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
1300static PyObject *
1301cms_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
1341static PyObject *
1342cms_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
1371static 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
1422static 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
1455static struct PyMethodDef cms_transform_methods[] = {
1456 {"apply", (PyCFunction)cms_transform_apply, 1}, {NULL((void*)0), NULL((void*)0)} /* sentinel */
1457};
1458
1459static PyObject *
1460cms_transform_getattr_inputMode(CmsTransformObject *self, void *closure) {
1461 return PyUnicode_FromString(self->mode_in);
1462}
1463
1464static PyObject *
1465cms_transform_getattr_outputMode(CmsTransformObject *self, void *closure) {
1466 return PyUnicode_FromString(self->mode_out);
1467}
1468
1469static struct PyGetSetDef cms_transform_getsetters[] = {
1470 {"inputMode", (getter)cms_transform_getattr_inputMode},
1471 {"outputMode", (getter)cms_transform_getattr_outputMode},
1472 {NULL((void*)0)}};
1473
1474static 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
1507static int
1508setup_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) {
2
Assuming the condition is true
3
Taking true branch
1531 v = PyUnicode_FromFormat("%d.%d.%d", vn / 1000, (vn / 10) % 100, vn % 10);
4
Calling 'PyUnicode_FromFormat'
6
Returning from 'PyUnicode_FromFormat'
7
PyObject ownership leak with reference count of 1
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
1540PyMODINIT_FUNCPyObject*
1541PyInit__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) {
1
Calling 'setup_module'
1555 return NULL((void*)0);
1556 }
1557
1558 PyDateTime_IMPORTPyDateTimeAPI = (PyDateTime_CAPI *)PyCapsule_Import("datetime.datetime_CAPI"
, 0)
;
1559
1560 return m;
1561}

/opt/pyrefcon/lib/pyrefcon/models/models/PyUnicode_FromFormat.model

1#ifndef PyUnicode_FromFormat
2struct _object;
3typedef struct _object PyObject;
4PyObject* clang_analyzer_PyObject_New_Reference();
5PyObject* PyUnicode_FromFormat(const char *format, ...) {
6 return clang_analyzer_PyObject_New_Reference();
5
Setting reference count to 1
7}
8#else
9#warning "API PyUnicode_FromFormat is defined as a macro."
10#endif