From 35c6ebd750d99248cc478bd9b6f57cfa8c28bab6 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Tue, 23 Oct 2018 22:33:57 -0500 Subject: [PATCH] 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. --- src/PIL/GifImagePlugin.py | 2 +- src/decode.c | 4 +++- src/libImaging/Gif.h | 3 +++ src/libImaging/GifDecode.c | 38 +++++++++++++++++++++----------------- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 2ebd8b248..6821bca3b 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -247,7 +247,7 @@ class GifImageFile(ImageFile.ImageFile): self.tile = [("gif", (x0, y0, x1, y1), self.__offset, - (bits, interlace))] + (bits, interlace, -1))] break else: diff --git a/src/decode.c b/src/decode.c index be1b503e6..50d725eb0 100644 --- a/src/decode.c +++ b/src/decode.c @@ -435,7 +435,8 @@ PyImaging_GifDecoderNew(PyObject* self, PyObject* args) char* mode; int bits = 8; 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; 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)->interlace = interlace; + ((GIFDECODERSTATE*)decoder->state.context)->transparency = transparency; return (PyObject*) decoder; } diff --git a/src/libImaging/Gif.h b/src/libImaging/Gif.h index 2cb95efd2..0a6e8557d 100644 --- a/src/libImaging/Gif.h +++ b/src/libImaging/Gif.h @@ -33,6 +33,9 @@ typedef struct { */ int interlace; + /* The transparent palette index, or -1 for no transparency. */ + int transparency; + /* PRIVATE CONTEXT (set by decoder) */ /* Interlace parameters */ diff --git a/src/libImaging/GifDecode.c b/src/libImaging/GifDecode.c index 58cf54400..16d5483b7 100644 --- a/src/libImaging/GifDecode.c +++ b/src/libImaging/GifDecode.c @@ -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 some common cases and handle them separately. */ - /* FIXME: should we handle the transparency index in here??? */ - - if (i == 1) { - if (state->x < state->xsize-1) { - /* Single pixel, not at the end of the line. */ - *out++ = p[0]; - state->x++; + /* If we have transparency, we need to use the regular loop. */ + if(context->transparency == -1) + { + if (i == 1) { + if (state->x < state->xsize-1) { + /* Single pixel, not at the end of the line. */ + *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; } - } 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 */ for (c = 0; c < i; c++) { - *out++ = p[c]; + if(p[c] != context->transparency) + *out = p[c]; + out++; if (++state->x >= state->xsize) { NEWLINE(state, context); }