mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +03:00
Preserve auxiliary channels during CMS transform.
This commit is contained in:
parent
fa56b3d255
commit
4a1ad8986f
101
_imagingcms.c
101
_imagingcms.c
|
@ -291,6 +291,97 @@ findLCMStype(char* PILmode)
|
|||
}
|
||||
}
|
||||
|
||||
#define Cms_Min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
static int
|
||||
pyCMSgetAuxChannelChannel (cmsUInt32Number format, int auxChannelNdx)
|
||||
{
|
||||
int numColors = T_CHANNELS(format);
|
||||
int numExtras = T_EXTRA(format);
|
||||
|
||||
if (T_SWAPFIRST(format) && T_DOSWAP(format)) {
|
||||
// reverse order, before anything but last extra is shifted last
|
||||
if (auxChannelNdx == numExtras - 1)
|
||||
return numColors + numExtras - 1;
|
||||
else
|
||||
return numExtras - 2 - auxChannelNdx;
|
||||
}
|
||||
else if (T_SWAPFIRST(format)) {
|
||||
// in order, after color channels, but last extra is shifted to first
|
||||
if (auxChannelNdx == numExtras - 1)
|
||||
return 0;
|
||||
else
|
||||
return numColors + 1 + auxChannelNdx;
|
||||
}
|
||||
else if (T_DOSWAP(format)) {
|
||||
// reverse order, before anything
|
||||
return numExtras - 1 - auxChannelNdx;
|
||||
}
|
||||
else {
|
||||
// in order, after color channels
|
||||
return numColors + auxChannelNdx;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pyCMScopyAux (cmsHTRANSFORM hTransform, Imaging imDst, const Imaging imSrc)
|
||||
{
|
||||
cmsUInt32Number dstLCMSFormat;
|
||||
cmsUInt32Number srcLCMSFormat;
|
||||
int numSrcExtras;
|
||||
int numDstExtras;
|
||||
int numExtras;
|
||||
int ySize;
|
||||
int xSize;
|
||||
int channelSize;
|
||||
int srcChunkSize;
|
||||
int dstChunkSize;
|
||||
int e;
|
||||
|
||||
// trivially copied
|
||||
if (imDst == imSrc)
|
||||
return;
|
||||
|
||||
dstLCMSFormat = cmsGetTransformOutputFormat(hTransform);
|
||||
srcLCMSFormat = cmsGetTransformInputFormat(hTransform);
|
||||
|
||||
// currently, all Pillow formats are chunky formats, but check it anyway
|
||||
if (T_PLANAR(dstLCMSFormat) || T_PLANAR(srcLCMSFormat))
|
||||
return;
|
||||
|
||||
// copy only if channel format is identical, except OPTIMIZED is ignored as it
|
||||
// does not affect the aux channel
|
||||
if (T_FLOAT(dstLCMSFormat) != T_FLOAT(srcLCMSFormat)
|
||||
|| T_FLAVOR(dstLCMSFormat) != T_FLAVOR(srcLCMSFormat)
|
||||
|| T_ENDIAN16(dstLCMSFormat) != T_ENDIAN16(srcLCMSFormat)
|
||||
|| T_BYTES(dstLCMSFormat) != T_BYTES(srcLCMSFormat))
|
||||
return;
|
||||
|
||||
numSrcExtras = T_EXTRA(srcLCMSFormat);
|
||||
numDstExtras = T_EXTRA(dstLCMSFormat);
|
||||
numExtras = Cms_Min(numSrcExtras, numDstExtras);
|
||||
ySize = Cms_Min(imSrc->ysize, imDst->ysize);
|
||||
xSize = Cms_Min(imSrc->xsize, imDst->xsize);
|
||||
channelSize = T_BYTES(dstLCMSFormat);
|
||||
srcChunkSize = (T_CHANNELS(srcLCMSFormat) + T_EXTRA(srcLCMSFormat)) * channelSize;
|
||||
dstChunkSize = (T_CHANNELS(dstLCMSFormat) + T_EXTRA(dstLCMSFormat)) * channelSize;
|
||||
|
||||
for (e = 0; e < numExtras; ++e) {
|
||||
int y;
|
||||
int dstChannel = pyCMSgetAuxChannelChannel(dstLCMSFormat, e);
|
||||
int srcChannel = pyCMSgetAuxChannelChannel(srcLCMSFormat, e);
|
||||
|
||||
for (y = 0; y < ySize; y++) {
|
||||
int x;
|
||||
char* pDstExtras = imDst->image[y] + dstChannel * channelSize;
|
||||
const char* pSrcExtras = imSrc->image[y] + srcChannel * channelSize;
|
||||
|
||||
for (x = 0; x < xSize; x++)
|
||||
memcpy(pDstExtras + x * dstChunkSize, pSrcExtras + x * srcChunkSize, channelSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
pyCMSdoTransform(Imaging im, Imaging imOut, cmsHTRANSFORM hTransform)
|
||||
{
|
||||
|
@ -301,9 +392,19 @@ pyCMSdoTransform(Imaging im, Imaging imOut, cmsHTRANSFORM hTransform)
|
|||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
||||
// transform color channels only
|
||||
for (i = 0; i < im->ysize; i++)
|
||||
cmsDoTransform(hTransform, im->image[i], imOut->image[i], im->xsize);
|
||||
|
||||
// lcms by default does nothing to the auxiliary channels leaving those
|
||||
// unchanged. To do "the right thing" here, i.e. maintain identical results
|
||||
// with and without inPlace, we replicate those channels to the output.
|
||||
//
|
||||
// As of lcms 2.8, a new cmsFLAGS_COPY_ALPHA flag is introduced which would
|
||||
// do the same thing automagically. Unfortunately, lcms2.8 is not yet widely
|
||||
// enough available on all platforms, so we polyfill it here for now.
|
||||
pyCMScopyAux(hTransform, imOut, im);
|
||||
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue
Block a user