20
#define COPYRIGHTINFO \
23
a Python / PIL interface to the littleCMS ICC Color Management System\n\
24
Copyright (C) 2002-2003 Kevin Cazabon\n\
26
https://www.cazabon.com\n\
29
#define PY_SSIZE_T_CLEAN
35
#include "libImaging/Imaging.h"
37
#define PYCMSVERSION "1.0.0 pil"
79
PyObject_HEAD cmsHPROFILE profile;
82
static PyTypeObject CmsProfile_Type;
84
#define CmsProfile_Check(op) (Py_TYPE(op) == &CmsProfile_Type)
87
cms_profile_new(cmsHPROFILE profile) {
88
CmsProfileObject *self;
90
self = PyObject_New(CmsProfileObject, &CmsProfile_Type);
95
self->profile = profile;
97
return (PyObject *)self;
101
cms_profile_open(PyObject *self, PyObject *args) {
102
cmsHPROFILE hProfile;
105
if (!PyArg_ParseTuple(args, "s:profile_open", &sProfile)) {
109
hProfile = cmsOpenProfileFromFile(sProfile, "r");
111
PyErr_SetString(PyExc_OSError, "cannot open profile file");
115
return cms_profile_new(hProfile);
119
cms_profile_frombytes(PyObject *self, PyObject *args) {
120
cmsHPROFILE hProfile;
124
if (!PyArg_ParseTuple(args, "y#:profile_frombytes", &pProfile, &nProfile)) {
128
hProfile = cmsOpenProfileFromMem(pProfile, nProfile);
130
PyErr_SetString(PyExc_OSError, "cannot open profile from string");
134
return cms_profile_new(hProfile);
138
cms_profile_tobytes(PyObject *self, PyObject *args) {
139
char *pProfile = NULL;
140
cmsUInt32Number nProfile;
141
PyObject *CmsProfile;
143
cmsHPROFILE *profile;
146
if (!PyArg_ParseTuple(args, "O!", &CmsProfile_Type, &CmsProfile)) {
150
profile = ((CmsProfileObject *)CmsProfile)->profile;
152
if (!cmsSaveProfileToMem(profile, pProfile, &nProfile)) {
153
PyErr_SetString(PyExc_OSError, "Could not determine profile size");
157
pProfile = (char *)malloc(nProfile);
159
PyErr_SetString(PyExc_OSError, "Out of Memory");
163
if (!cmsSaveProfileToMem(profile, pProfile, &nProfile)) {
164
PyErr_SetString(PyExc_OSError, "Could not get profile");
169
ret = PyBytes_FromStringAndSize(pProfile, (Py_ssize_t)nProfile);
176
cms_profile_dealloc(CmsProfileObject *self) {
177
(void)cmsCloseProfile(self->profile);
184
PyObject_HEAD cmsHTRANSFORM transform;
187
static PyTypeObject CmsTransform_Type;
189
#define CmsTransform_Check(op) (Py_TYPE(op) == &CmsTransform_Type)
192
cms_transform_new(cmsHTRANSFORM transform) {
193
CmsTransformObject *self;
195
self = PyObject_New(CmsTransformObject, &CmsTransform_Type);
200
self->transform = transform;
202
return (PyObject *)self;
206
cms_transform_dealloc(CmsTransformObject *self) {
207
cmsDeleteTransform(self->transform);
214
static cmsUInt32Number
215
findLCMStype(char *PILmode) {
216
if (strcmp(PILmode, "RGB") == 0 || strcmp(PILmode, "RGBA") == 0 ||
217
strcmp(PILmode, "RGBX") == 0) {
220
if (strcmp(PILmode, "RGBA;16B") == 0) {
223
if (strcmp(PILmode, "CMYK") == 0) {
226
if (strcmp(PILmode, "I;16") == 0 || strcmp(PILmode, "I;16L") == 0 ||
227
strcmp(PILmode, "L;16") == 0) {
230
if (strcmp(PILmode, "I;16B") == 0 || strcmp(PILmode, "L;16B") == 0) {
231
return TYPE_GRAY_16_SE;
233
if (strcmp(PILmode, "YCbCr") == 0 || strcmp(PILmode, "YCCA") == 0 ||
234
strcmp(PILmode, "YCC") == 0) {
237
if (strcmp(PILmode, "LAB") == 0) {
239
return (COLORSPACE_SH(PT_LabV2) | CHANNELS_SH(3) | BYTES_SH(1) | EXTRA_SH(1));
245
#define Cms_Min(a, b) ((a) < (b) ? (a) : (b))
248
pyCMSgetAuxChannelChannel(cmsUInt32Number format, int auxChannelNdx) {
249
int numColors = T_CHANNELS(format);
250
int numExtras = T_EXTRA(format);
252
if (T_SWAPFIRST(format) && T_DOSWAP(format)) {
254
if (auxChannelNdx == numExtras - 1) {
255
return numColors + numExtras - 1;
257
return numExtras - 2 - auxChannelNdx;
259
} else if (T_SWAPFIRST(format)) {
261
if (auxChannelNdx == numExtras - 1) {
264
return numColors + 1 + auxChannelNdx;
266
} else if (T_DOSWAP(format)) {
268
return numExtras - 1 - auxChannelNdx;
271
return numColors + auxChannelNdx;
276
pyCMScopyAux(cmsHTRANSFORM hTransform, Imaging imDst, const Imaging imSrc) {
277
cmsUInt32Number dstLCMSFormat;
278
cmsUInt32Number srcLCMSFormat;
290
if (imDst == imSrc) {
294
dstLCMSFormat = cmsGetTransformOutputFormat(hTransform);
295
srcLCMSFormat = cmsGetTransformInputFormat(hTransform);
298
if (T_PLANAR(dstLCMSFormat) || T_PLANAR(srcLCMSFormat)) {
304
if (T_FLOAT(dstLCMSFormat) != T_FLOAT(srcLCMSFormat) ||
305
T_FLAVOR(dstLCMSFormat) != T_FLAVOR(srcLCMSFormat) ||
306
T_ENDIAN16(dstLCMSFormat) != T_ENDIAN16(srcLCMSFormat) ||
307
T_BYTES(dstLCMSFormat) != T_BYTES(srcLCMSFormat)) {
311
numSrcExtras = T_EXTRA(srcLCMSFormat);
312
numDstExtras = T_EXTRA(dstLCMSFormat);
313
numExtras = Cms_Min(numSrcExtras, numDstExtras);
314
ySize = Cms_Min(imSrc->ysize, imDst->ysize);
315
xSize = Cms_Min(imSrc->xsize, imDst->xsize);
316
channelSize = T_BYTES(dstLCMSFormat);
317
srcChunkSize = (T_CHANNELS(srcLCMSFormat) + T_EXTRA(srcLCMSFormat)) * channelSize;
318
dstChunkSize = (T_CHANNELS(dstLCMSFormat) + T_EXTRA(dstLCMSFormat)) * channelSize;
320
for (e = 0; e < numExtras; ++e) {
322
int dstChannel = pyCMSgetAuxChannelChannel(dstLCMSFormat, e);
323
int srcChannel = pyCMSgetAuxChannelChannel(srcLCMSFormat, e);
325
for (y = 0; y < ySize; y++) {
327
char *pDstExtras = imDst->image[y] + dstChannel * channelSize;
328
const char *pSrcExtras = imSrc->image[y] + srcChannel * channelSize;
330
for (x = 0; x < xSize; x++) {
332
pDstExtras + x * dstChunkSize,
333
pSrcExtras + x * srcChunkSize,
342
pyCMSdoTransform(Imaging im, Imaging imOut, cmsHTRANSFORM hTransform) {
345
if (im->xsize > imOut->xsize || im->ysize > imOut->ysize) {
349
Py_BEGIN_ALLOW_THREADS
352
for (i = 0; i < im->ysize; i++) {
353
cmsDoTransform(hTransform, im->image[i], imOut->image[i], im->xsize);
363
pyCMScopyAux(hTransform, imOut, im);
372
cmsHPROFILE hInputProfile,
373
cmsHPROFILE hOutputProfile,
376
int iRenderingIntent,
377
cmsUInt32Number cmsFLAGS
379
cmsHTRANSFORM hTransform;
381
Py_BEGIN_ALLOW_THREADS
384
hTransform = cmsCreateTransform(
386
findLCMStype(sInMode),
388
findLCMStype(sOutMode),
393
Py_END_ALLOW_THREADS;
396
PyErr_SetString(PyExc_ValueError, "cannot build transform");
404
cmsHPROFILE hInputProfile,
405
cmsHPROFILE hOutputProfile,
406
cmsHPROFILE hProofProfile,
409
int iRenderingIntent,
411
cmsUInt32Number cmsFLAGS
413
cmsHTRANSFORM hTransform;
415
Py_BEGIN_ALLOW_THREADS
418
hTransform = cmsCreateProofingTransform(
420
findLCMStype(sInMode),
422
findLCMStype(sOutMode),
429
Py_END_ALLOW_THREADS;
432
PyErr_SetString(PyExc_ValueError, "cannot build proof transform");
442
buildTransform(PyObject *self, PyObject *args) {
443
CmsProfileObject *pInputProfile;
444
CmsProfileObject *pOutputProfile;
447
int iRenderingIntent = 0;
450
cmsHTRANSFORM transform = NULL;
452
if (!PyArg_ParseTuple(
454
"O!O!ss|ii:buildTransform",
467
transform = _buildTransform(
468
pInputProfile->profile,
469
pOutputProfile->profile,
480
return cms_transform_new(transform);
484
buildProofTransform(PyObject *self, PyObject *args) {
485
CmsProfileObject *pInputProfile;
486
CmsProfileObject *pOutputProfile;
487
CmsProfileObject *pProofProfile;
490
int iRenderingIntent = 0;
491
int iProofIntent = 0;
494
cmsHTRANSFORM transform = NULL;
496
if (!PyArg_ParseTuple(
498
"O!O!O!ss|iii:buildProofTransform",
514
transform = _buildProofTransform(
515
pInputProfile->profile,
516
pOutputProfile->profile,
517
pProofProfile->profile,
529
return cms_transform_new(transform);
533
cms_transform_apply(CmsTransformObject *self, PyObject *args) {
541
if (!PyArg_ParseTuple(args, "nn:apply", &idIn, &idOut)) {
546
imOut = (Imaging)idOut;
548
result = pyCMSdoTransform(im, imOut, self->transform);
550
return Py_BuildValue("i", result);
557
createProfile(PyObject *self, PyObject *args) {
559
cmsHPROFILE hProfile;
560
cmsFloat64Number dColorTemp = 0.0;
561
cmsCIExyY whitePoint;
564
if (!PyArg_ParseTuple(args, "s|d:createProfile", &sColorSpace, &dColorTemp)) {
568
if (strcmp(sColorSpace, "LAB") == 0) {
569
if (dColorTemp > 0.0) {
570
result = cmsWhitePointFromTemp(&whitePoint, dColorTemp);
574
"ERROR: Could not calculate white point from color temperature "
575
"provided, must be float in degrees Kelvin"
579
hProfile = cmsCreateLab2Profile(&whitePoint);
581
hProfile = cmsCreateLab2Profile(NULL);
583
} else if (strcmp(sColorSpace, "XYZ") == 0) {
584
hProfile = cmsCreateXYZProfile();
585
} else if (strcmp(sColorSpace, "sRGB") == 0) {
586
hProfile = cmsCreate_sRGBProfile();
592
PyErr_SetString(PyExc_ValueError, "failed to create requested color space");
596
return cms_profile_new(hProfile);
603
cms_profile_is_intent_supported(CmsProfileObject *self, PyObject *args) {
608
if (!PyArg_ParseTuple(args, "ii:is_intent_supported", &intent, &direction)) {
612
result = cmsIsIntentSupported(self->profile, intent, direction);
617
return PyLong_FromLong(result != 0);
629
cms_get_display_profile_win32(PyObject *self, PyObject *args) {
630
char filename[MAX_PATH];
636
if (!PyArg_ParseTuple(
637
args, "|" F_HANDLE "i:get_display_profile", &handle, &is_dc
642
filename_size = sizeof(filename);
645
ok = GetICMProfile((HDC)handle, &filename_size, filename);
647
HDC dc = GetDC((HWND)handle);
648
ok = GetICMProfile(dc, &filename_size, filename);
649
ReleaseDC((HWND)handle, dc);
653
return PyUnicode_FromStringAndSize(filename, filename_size - 1);
665
_profile_read_mlu(CmsProfileObject *self, cmsTagSignature info) {
668
char *cc = cmsNoCountry;
673
if (!cmsIsTag(self->profile, info)) {
678
mlu = cmsReadTag(self->profile, info);
684
len = cmsMLUgetWide(mlu, lc, cc, NULL, 0);
692
PyErr_SetString(PyExc_OSError, "Out of Memory");
698
cmsMLUgetWide(mlu, lc, cc, buf, len);
700
uni = PyUnicode_FromWideChar(buf, wcslen(buf));
707
_profile_read_int_as_string(cmsUInt32Number nr) {
710
buf[0] = (char)((nr >> 24) & 0xff);
711
buf[1] = (char)((nr >> 16) & 0xff);
712
buf[2] = (char)((nr >> 8) & 0xff);
713
buf[3] = (char)(nr & 0xff);
716
ret = PyUnicode_DecodeASCII(buf, 4, NULL);
721
_profile_read_signature(CmsProfileObject *self, cmsTagSignature info) {
724
if (!cmsIsTag(self->profile, info)) {
729
sig = (unsigned int *)cmsReadTag(self->profile, info);
735
return _profile_read_int_as_string(*sig);
739
_xyz_py(cmsCIEXYZ *XYZ) {
741
cmsXYZ2xyY(&xyY, XYZ);
742
return Py_BuildValue(
743
"((d,d,d),(d,d,d))", XYZ->X, XYZ->Y, XYZ->Z, xyY.x, xyY.y, xyY.Y
748
_xyz3_py(cmsCIEXYZ *XYZ) {
750
cmsXYZ2xyY(&xyY[0], &XYZ[0]);
751
cmsXYZ2xyY(&xyY[1], &XYZ[1]);
752
cmsXYZ2xyY(&xyY[2], &XYZ[2]);
754
return Py_BuildValue(
755
"(((d,d,d),(d,d,d),(d,d,d)),((d,d,d),(d,d,d),(d,d,d)))",
778
_profile_read_ciexyz(CmsProfileObject *self, cmsTagSignature info, int multi) {
781
if (!cmsIsTag(self->profile, info)) {
786
XYZ = (cmsCIEXYZ *)cmsReadTag(self->profile, info);
792
return _xyz3_py(XYZ);
799
_profile_read_ciexyy_triple(CmsProfileObject *self, cmsTagSignature info) {
800
cmsCIExyYTRIPLE *triple;
802
if (!cmsIsTag(self->profile, info)) {
807
triple = (cmsCIExyYTRIPLE *)cmsReadTag(self->profile, info);
815
return Py_BuildValue(
816
"((d,d,d),(d,d,d),(d,d,d)),",
830
_profile_read_named_color_list(CmsProfileObject *self, cmsTagSignature info) {
831
cmsNAMEDCOLORLIST *ncl;
833
char name[cmsMAX_PATH];
836
if (!cmsIsTag(self->profile, info)) {
841
ncl = (cmsNAMEDCOLORLIST *)cmsReadTag(self->profile, info);
847
n = cmsNamedColorCount(ncl);
848
result = PyList_New(n);
854
for (i = 0; i < n; i++) {
856
cmsNamedColorInfo(ncl, i, name, NULL, NULL, NULL, NULL);
857
str = PyUnicode_FromString(name);
863
PyList_SET_ITEM(result, i, str);
870
_calculate_rgb_primaries(CmsProfileObject *self, cmsCIEXYZTRIPLE *result) {
871
double input[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
873
cmsHTRANSFORM hTransform;
878
hXYZ = cmsCreateXYZProfile();
884
hTransform = cmsCreateTransform(
889
INTENT_RELATIVE_COLORIMETRIC,
890
cmsFLAGS_NOCACHE | cmsFLAGS_NOOPTIMIZE
892
cmsCloseProfile(hXYZ);
893
if (hTransform == NULL) {
897
cmsDoTransform(hTransform, (void *)input, result, 3);
898
cmsDeleteTransform(hTransform);
905
cmsHPROFILE hProfile,
906
cmsUInt32Number Intent,
907
cmsUInt32Number UsedDirection
910
return cmsIsCLUT(hProfile, Intent, UsedDirection);
912
return cmsIsIntentSupported(hProfile, Intent, UsedDirection);
919
_is_intent_supported(CmsProfileObject *self, int clut) {
923
cmsUInt32Number intent_ids[INTENTS];
924
char *intent_descs[INTENTS];
926
result = PyDict_New();
927
if (result == NULL) {
932
n = cmsGetSupportedIntents(INTENTS, intent_ids, intent_descs);
933
for (i = 0; i < n; i++) {
934
int intent = (int)intent_ids[i];
940
if (!(intent == INTENT_PERCEPTUAL || intent == INTENT_RELATIVE_COLORIMETRIC ||
941
intent == INTENT_SATURATION || intent == INTENT_ABSOLUTE_COLORIMETRIC)) {
945
id = PyLong_FromLong((long)intent);
946
entry = Py_BuildValue(
948
_check_intent(clut, self->profile, intent, LCMS_USED_AS_INPUT) ? Py_True
950
_check_intent(clut, self->profile, intent, LCMS_USED_AS_OUTPUT) ? Py_True
952
_check_intent(clut, self->profile, intent, LCMS_USED_AS_PROOF) ? Py_True
955
if (id == NULL || entry == NULL) {
962
PyDict_SetItem(result, id, entry);
972
static PyMethodDef pyCMSdll_methods[] = {
974
{"profile_open", cms_profile_open, METH_VARARGS},
975
{"profile_frombytes", cms_profile_frombytes, METH_VARARGS},
976
{"profile_tobytes", cms_profile_tobytes, METH_VARARGS},
979
{"buildTransform", buildTransform, METH_VARARGS},
980
{"buildProofTransform", buildProofTransform, METH_VARARGS},
981
{"createProfile", createProfile, METH_VARARGS},
985
{"get_display_profile_win32", cms_get_display_profile_win32, METH_VARARGS},
991
static struct PyMethodDef cms_profile_methods[] = {
992
{"is_intent_supported", (PyCFunction)cms_profile_is_intent_supported, METH_VARARGS},
997
cms_profile_getattr_rendering_intent(CmsProfileObject *self, void *closure) {
998
return PyLong_FromLong(cmsGetHeaderRenderingIntent(self->profile));
1003
cms_profile_getattr_copyright(CmsProfileObject *self, void *closure) {
1004
return _profile_read_mlu(self, cmsSigCopyrightTag);
1008
cms_profile_getattr_target(CmsProfileObject *self, void *closure) {
1009
return _profile_read_mlu(self, cmsSigCharTargetTag);
1013
cms_profile_getattr_manufacturer(CmsProfileObject *self, void *closure) {
1014
return _profile_read_mlu(self, cmsSigDeviceMfgDescTag);
1018
cms_profile_getattr_model(CmsProfileObject *self, void *closure) {
1019
return _profile_read_mlu(self, cmsSigDeviceModelDescTag);
1023
cms_profile_getattr_profile_description(CmsProfileObject *self, void *closure) {
1024
return _profile_read_mlu(self, cmsSigProfileDescriptionTag);
1028
cms_profile_getattr_screening_description(CmsProfileObject *self, void *closure) {
1029
return _profile_read_mlu(self, cmsSigScreeningDescTag);
1033
cms_profile_getattr_viewing_condition(CmsProfileObject *self, void *closure) {
1034
return _profile_read_mlu(self, cmsSigViewingCondDescTag);
1038
cms_profile_getattr_creation_date(CmsProfileObject *self, void *closure) {
1042
result = cmsGetHeaderCreationDateTime(self->profile, &ct);
1048
return PyDateTime_FromDateAndTime(
1049
1900 + ct.tm_year, ct.tm_mon, ct.tm_mday, ct.tm_hour, ct.tm_min, ct.tm_sec, 0
1054
cms_profile_getattr_version(CmsProfileObject *self, void *closure) {
1055
cmsFloat64Number version = cmsGetProfileVersion(self->profile);
1056
return PyFloat_FromDouble(version);
1060
cms_profile_getattr_icc_version(CmsProfileObject *self, void *closure) {
1061
return PyLong_FromLong((long)cmsGetEncodedICCversion(self->profile));
1065
cms_profile_getattr_attributes(CmsProfileObject *self, void *closure) {
1066
cmsUInt64Number attr;
1067
cmsGetHeaderAttributes(self->profile, &attr);
1070
return PyLong_FromUnsignedLongLong((unsigned long long)attr);
1074
cms_profile_getattr_header_flags(CmsProfileObject *self, void *closure) {
1075
cmsUInt32Number flags = cmsGetHeaderFlags(self->profile);
1076
return PyLong_FromLong(flags);
1080
cms_profile_getattr_header_manufacturer(CmsProfileObject *self, void *closure) {
1081
return _profile_read_int_as_string(cmsGetHeaderManufacturer(self->profile));
1085
cms_profile_getattr_header_model(CmsProfileObject *self, void *closure) {
1086
return _profile_read_int_as_string(cmsGetHeaderModel(self->profile));
1090
cms_profile_getattr_device_class(CmsProfileObject *self, void *closure) {
1091
return _profile_read_int_as_string(cmsGetDeviceClass(self->profile));
1095
cms_profile_getattr_connection_space(CmsProfileObject *self, void *closure) {
1096
return _profile_read_int_as_string(cmsGetPCS(self->profile));
1100
cms_profile_getattr_xcolor_space(CmsProfileObject *self, void *closure) {
1101
return _profile_read_int_as_string(cmsGetColorSpace(self->profile));
1105
cms_profile_getattr_profile_id(CmsProfileObject *self, void *closure) {
1106
cmsUInt8Number id[16];
1107
cmsGetHeaderProfileID(self->profile, id);
1108
return PyBytes_FromStringAndSize((char *)id, 16);
1112
cms_profile_getattr_is_matrix_shaper(CmsProfileObject *self, void *closure) {
1113
return PyBool_FromLong((long)cmsIsMatrixShaper(self->profile));
1117
cms_profile_getattr_technology(CmsProfileObject *self, void *closure) {
1118
return _profile_read_signature(self, cmsSigTechnologyTag);
1122
cms_profile_getattr_colorimetric_intent(CmsProfileObject *self, void *closure) {
1123
return _profile_read_signature(self, cmsSigColorimetricIntentImageStateTag);
1127
cms_profile_getattr_perceptual_rendering_intent_gamut(
1128
CmsProfileObject *self, void *closure
1130
return _profile_read_signature(self, cmsSigPerceptualRenderingIntentGamutTag);
1134
cms_profile_getattr_saturation_rendering_intent_gamut(
1135
CmsProfileObject *self, void *closure
1137
return _profile_read_signature(self, cmsSigSaturationRenderingIntentGamutTag);
1141
cms_profile_getattr_red_colorant(CmsProfileObject *self, void *closure) {
1142
if (!cmsIsMatrixShaper(self->profile)) {
1146
return _profile_read_ciexyz(self, cmsSigRedColorantTag, 0);
1150
cms_profile_getattr_green_colorant(CmsProfileObject *self, void *closure) {
1151
if (!cmsIsMatrixShaper(self->profile)) {
1155
return _profile_read_ciexyz(self, cmsSigGreenColorantTag, 0);
1159
cms_profile_getattr_blue_colorant(CmsProfileObject *self, void *closure) {
1160
if (!cmsIsMatrixShaper(self->profile)) {
1164
return _profile_read_ciexyz(self, cmsSigBlueColorantTag, 0);
1168
cms_profile_getattr_media_white_point_temperature(
1169
CmsProfileObject *self, void *closure
1173
cmsFloat64Number tempK;
1174
cmsTagSignature info = cmsSigMediaWhitePointTag;
1177
if (!cmsIsTag(self->profile, info)) {
1182
XYZ = (cmsCIEXYZ *)cmsReadTag(self->profile, info);
1183
if (XYZ == NULL || XYZ->X == 0) {
1188
cmsXYZ2xyY(&xyY, XYZ);
1189
result = cmsTempFromWhitePoint(&tempK, &xyY);
1194
return PyFloat_FromDouble(tempK);
1198
cms_profile_getattr_media_white_point(CmsProfileObject *self, void *closure) {
1199
return _profile_read_ciexyz(self, cmsSigMediaWhitePointTag, 0);
1203
cms_profile_getattr_media_black_point(CmsProfileObject *self, void *closure) {
1204
return _profile_read_ciexyz(self, cmsSigMediaBlackPointTag, 0);
1208
cms_profile_getattr_luminance(CmsProfileObject *self, void *closure) {
1209
return _profile_read_ciexyz(self, cmsSigLuminanceTag, 0);
1213
cms_profile_getattr_chromatic_adaptation(CmsProfileObject *self, void *closure) {
1214
return _profile_read_ciexyz(self, cmsSigChromaticAdaptationTag, 1);
1218
cms_profile_getattr_chromaticity(CmsProfileObject *self, void *closure) {
1219
return _profile_read_ciexyy_triple(self, cmsSigChromaticityTag);
1223
cms_profile_getattr_red_primary(CmsProfileObject *self, void *closure) {
1225
cmsCIEXYZTRIPLE primaries;
1227
if (cmsIsMatrixShaper(self->profile)) {
1228
result = _calculate_rgb_primaries(self, &primaries);
1235
return _xyz_py(&primaries.Red);
1239
cms_profile_getattr_green_primary(CmsProfileObject *self, void *closure) {
1241
cmsCIEXYZTRIPLE primaries;
1243
if (cmsIsMatrixShaper(self->profile)) {
1244
result = _calculate_rgb_primaries(self, &primaries);
1251
return _xyz_py(&primaries.Green);
1255
cms_profile_getattr_blue_primary(CmsProfileObject *self, void *closure) {
1257
cmsCIEXYZTRIPLE primaries;
1259
if (cmsIsMatrixShaper(self->profile)) {
1260
result = _calculate_rgb_primaries(self, &primaries);
1267
return _xyz_py(&primaries.Blue);
1271
cms_profile_getattr_colorant_table(CmsProfileObject *self, void *closure) {
1272
return _profile_read_named_color_list(self, cmsSigColorantTableTag);
1276
cms_profile_getattr_colorant_table_out(CmsProfileObject *self, void *closure) {
1277
return _profile_read_named_color_list(self, cmsSigColorantTableOutTag);
1281
cms_profile_getattr_is_intent_supported(CmsProfileObject *self, void *closure) {
1282
return _is_intent_supported(self, 0);
1286
cms_profile_getattr_is_clut(CmsProfileObject *self, void *closure) {
1287
return _is_intent_supported(self, 1);
1317
cms_profile_getattr_icc_measurement_condition(CmsProfileObject *self, void *closure) {
1318
cmsICCMeasurementConditions *mc;
1319
cmsTagSignature info = cmsSigMeasurementTag;
1322
if (!cmsIsTag(self->profile, info)) {
1327
mc = (cmsICCMeasurementConditions *)cmsReadTag(self->profile, info);
1333
if (mc->Geometry == 1) {
1335
} else if (mc->Geometry == 2) {
1341
return Py_BuildValue(
1342
"{s:i,s:(ddd),s:s,s:d,s:s}",
1354
_illu_map(mc->IlluminantType)
1359
cms_profile_getattr_icc_viewing_condition(CmsProfileObject *self, void *closure) {
1360
cmsICCViewingConditions *vc;
1361
cmsTagSignature info = cmsSigViewingConditionsTag;
1363
if (!cmsIsTag(self->profile, info)) {
1368
vc = (cmsICCViewingConditions *)cmsReadTag(self->profile, info);
1374
return Py_BuildValue(
1375
"{s:(ddd),s:(ddd),s:s}",
1377
vc->IlluminantXYZ.X,
1378
vc->IlluminantXYZ.Y,
1379
vc->IlluminantXYZ.Z,
1385
_illu_map(vc->IlluminantType)
1389
static struct PyGetSetDef cms_profile_getsetters[] = {
1391
{"rendering_intent", (getter)cms_profile_getattr_rendering_intent},
1392
{"creation_date", (getter)cms_profile_getattr_creation_date},
1393
{"copyright", (getter)cms_profile_getattr_copyright},
1394
{"target", (getter)cms_profile_getattr_target},
1395
{"manufacturer", (getter)cms_profile_getattr_manufacturer},
1396
{"model", (getter)cms_profile_getattr_model},
1397
{"profile_description", (getter)cms_profile_getattr_profile_description},
1398
{"screening_description", (getter)cms_profile_getattr_screening_description},
1399
{"viewing_condition", (getter)cms_profile_getattr_viewing_condition},
1400
{"version", (getter)cms_profile_getattr_version},
1401
{"icc_version", (getter)cms_profile_getattr_icc_version},
1402
{"attributes", (getter)cms_profile_getattr_attributes},
1403
{"header_flags", (getter)cms_profile_getattr_header_flags},
1404
{"header_manufacturer", (getter)cms_profile_getattr_header_manufacturer},
1405
{"header_model", (getter)cms_profile_getattr_header_model},
1406
{"device_class", (getter)cms_profile_getattr_device_class},
1407
{"connection_space", (getter)cms_profile_getattr_connection_space},
1408
{"xcolor_space", (getter)cms_profile_getattr_xcolor_space},
1409
{"profile_id", (getter)cms_profile_getattr_profile_id},
1410
{"is_matrix_shaper", (getter)cms_profile_getattr_is_matrix_shaper},
1411
{"technology", (getter)cms_profile_getattr_technology},
1412
{"colorimetric_intent", (getter)cms_profile_getattr_colorimetric_intent},
1413
{"perceptual_rendering_intent_gamut",
1414
(getter)cms_profile_getattr_perceptual_rendering_intent_gamut},
1415
{"saturation_rendering_intent_gamut",
1416
(getter)cms_profile_getattr_saturation_rendering_intent_gamut},
1417
{"red_colorant", (getter)cms_profile_getattr_red_colorant},
1418
{"green_colorant", (getter)cms_profile_getattr_green_colorant},
1419
{"blue_colorant", (getter)cms_profile_getattr_blue_colorant},
1420
{"red_primary", (getter)cms_profile_getattr_red_primary},
1421
{"green_primary", (getter)cms_profile_getattr_green_primary},
1422
{"blue_primary", (getter)cms_profile_getattr_blue_primary},
1423
{"media_white_point_temperature",
1424
(getter)cms_profile_getattr_media_white_point_temperature},
1425
{"media_white_point", (getter)cms_profile_getattr_media_white_point},
1426
{"media_black_point", (getter)cms_profile_getattr_media_black_point},
1427
{"luminance", (getter)cms_profile_getattr_luminance},
1428
{"chromatic_adaptation", (getter)cms_profile_getattr_chromatic_adaptation},
1429
{"chromaticity", (getter)cms_profile_getattr_chromaticity},
1430
{"colorant_table", (getter)cms_profile_getattr_colorant_table},
1431
{"colorant_table_out", (getter)cms_profile_getattr_colorant_table_out},
1432
{"intent_supported", (getter)cms_profile_getattr_is_intent_supported},
1433
{"clut", (getter)cms_profile_getattr_is_clut},
1434
{"icc_measurement_condition", (getter)cms_profile_getattr_icc_measurement_condition
1436
{"icc_viewing_condition", (getter)cms_profile_getattr_icc_viewing_condition},
1441
static PyTypeObject CmsProfile_Type = {
1442
PyVarObject_HEAD_INIT(NULL, 0) "PIL.ImageCms.core.CmsProfile",
1443
sizeof(CmsProfileObject),
1446
(destructor)cms_profile_dealloc,
1469
cms_profile_methods,
1471
cms_profile_getsetters,
1474
static struct PyMethodDef cms_transform_methods[] = {
1475
{"apply", (PyCFunction)cms_transform_apply, 1}, {NULL, NULL}
1478
static PyTypeObject CmsTransform_Type = {
1479
PyVarObject_HEAD_INIT(NULL, 0) "PIL.ImageCms.core.CmsTransform",
1480
sizeof(CmsTransformObject),
1483
(destructor)cms_transform_dealloc,
1506
cms_transform_methods,
1512
setup_module(PyObject *m) {
1518
PyType_Ready(&CmsProfile_Type);
1519
PyType_Ready(&CmsTransform_Type);
1521
Py_INCREF(&CmsProfile_Type);
1522
PyModule_AddObject(m, "CmsProfile", (PyObject *)&CmsProfile_Type);
1524
Py_INCREF(&CmsTransform_Type);
1525
PyModule_AddObject(m, "CmsTransform", (PyObject *)&CmsTransform_Type);
1527
d = PyModule_GetDict(m);
1530
#if LCMS_VERSION < 2070
1533
vn = cmsGetEncodedCMMversion();
1536
v = PyUnicode_FromFormat("%d.%d.%d", vn / 1000, (vn / 10) % 100, vn % 10);
1538
v = PyUnicode_FromFormat("%d.%d", vn / 1000, (vn / 10) % 100);
1540
PyDict_SetItemString(d, "littlecms_version", v ? v : Py_None);
1547
PyInit__imagingcms(void) {
1550
static PyModuleDef module_def = {
1551
PyModuleDef_HEAD_INIT,
1558
m = PyModule_Create(&module_def);
1560
if (setup_module(m) < 0) {
1566
#ifdef Py_GIL_DISABLED
1567
PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);