GIF: Support transparency in the native decoder.

Allow the transparency index to be passed to the native decoder.  If not
-1, pixels with this index will be left at their previous value.

This only adds the decoder support and isn't active yet.
This commit is contained in:
Glenn Maynard 2018-10-23 22:33:57 -05:00 committed by Andrew Murray
parent e44f567780
commit 35c6ebd750
4 changed files with 28 additions and 19 deletions

View File

@ -247,7 +247,7 @@ class GifImageFile(ImageFile.ImageFile):
self.tile = [("gif", self.tile = [("gif",
(x0, y0, x1, y1), (x0, y0, x1, y1),
self.__offset, self.__offset,
(bits, interlace))] (bits, interlace, -1))]
break break
else: else:

View File

@ -435,7 +435,8 @@ PyImaging_GifDecoderNew(PyObject* self, PyObject* args)
char* mode; char* mode;
int bits = 8; int bits = 8;
int interlace = 0; int interlace = 0;
if (!PyArg_ParseTuple(args, "s|ii", &mode, &bits, &interlace)) int transparency = -1;
if (!PyArg_ParseTuple(args, "s|iii", &mode, &bits, &interlace, &transparency))
return NULL; return NULL;
if (strcmp(mode, "L") != 0 && strcmp(mode, "P") != 0) { if (strcmp(mode, "L") != 0 && strcmp(mode, "P") != 0) {
@ -451,6 +452,7 @@ PyImaging_GifDecoderNew(PyObject* self, PyObject* args)
((GIFDECODERSTATE*)decoder->state.context)->bits = bits; ((GIFDECODERSTATE*)decoder->state.context)->bits = bits;
((GIFDECODERSTATE*)decoder->state.context)->interlace = interlace; ((GIFDECODERSTATE*)decoder->state.context)->interlace = interlace;
((GIFDECODERSTATE*)decoder->state.context)->transparency = transparency;
return (PyObject*) decoder; return (PyObject*) decoder;
} }

View File

@ -33,6 +33,9 @@ typedef struct {
*/ */
int interlace; int interlace;
/* The transparent palette index, or -1 for no transparency. */
int transparency;
/* PRIVATE CONTEXT (set by decoder) */ /* PRIVATE CONTEXT (set by decoder) */
/* Interlace parameters */ /* Interlace parameters */

View File

@ -264,29 +264,33 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, int bytes)
/* To squeeze some extra pixels out of this loop, we test for /* To squeeze some extra pixels out of this loop, we test for
some common cases and handle them separately. */ some common cases and handle them separately. */
/* FIXME: should we handle the transparency index in here??? */ /* If we have transparency, we need to use the regular loop. */
if(context->transparency == -1)
if (i == 1) { {
if (state->x < state->xsize-1) { if (i == 1) {
/* Single pixel, not at the end of the line. */ if (state->x < state->xsize-1) {
*out++ = p[0]; /* Single pixel, not at the end of the line. */
state->x++; *out++ = p[0];
state->x++;
continue;
}
} else if (state->x + i <= state->xsize) {
/* This string fits into current line. */
memcpy(out, p, i);
out += i;
state->x += i;
if (state->x == state->xsize) {
NEWLINE(state, context);
}
continue; continue;
} }
} else if (state->x + i <= state->xsize) {
/* This string fits into current line. */
memcpy(out, p, i);
out += i;
state->x += i;
if (state->x == state->xsize) {
NEWLINE(state, context);
}
continue;
} }
/* No shortcut, copy pixel by pixel */ /* No shortcut, copy pixel by pixel */
for (c = 0; c < i; c++) { for (c = 0; c < i; c++) {
*out++ = p[c]; if(p[c] != context->transparency)
*out = p[c];
out++;
if (++state->x >= state->xsize) { if (++state->x >= state->xsize) {
NEWLINE(state, context); NEWLINE(state, context);
} }