Loading transparent pixels in C from subsequent GIF frames is no longer a problem

This commit is contained in:
Andrew Murray 2021-11-29 14:10:18 +11:00
parent b383a175be
commit 6337428df1
4 changed files with 19 additions and 34 deletions

View File

@ -313,18 +313,14 @@ class GifImageFile(ImageFile.ImageFile):
pass pass
if interlace is not None: if interlace is not None:
transparency = -1 if frame == 0 and frame_transparency is not None:
if frame_transparency is not None: self.info["transparency"] = frame_transparency
if frame == 0:
self.info["transparency"] = frame_transparency
else:
transparency = frame_transparency
self.tile = [ self.tile = [
( (
"gif", "gif",
(x0, y0, x1, y1), (x0, y0, x1, y1),
self.__offset, self.__offset,
(bits, interlace, transparency), (bits, interlace),
) )
] ]
else: else:

View File

@ -433,8 +433,7 @@ PyImaging_GifDecoderNew(PyObject *self, PyObject *args) {
char *mode; char *mode;
int bits = 8; int bits = 8;
int interlace = 0; int interlace = 0;
int transparency = -1; if (!PyArg_ParseTuple(args, "s|ii", &mode, &bits, &interlace)) {
if (!PyArg_ParseTuple(args, "s|iii", &mode, &bits, &interlace, &transparency)) {
return NULL; return NULL;
} }
@ -452,7 +451,6 @@ 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

@ -30,9 +30,6 @@ 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

@ -248,33 +248,27 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t
/* 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. */
/* If we have transparency, we need to use the regular loop. */ if (i == 1) {
if (context->transparency == -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++) {
if (p[c] != context->transparency) { *out++ = p[c];
*out = p[c];
}
out++;
if (++state->x >= state->xsize) { if (++state->x >= state->xsize) {
NEWLINE(state, context); NEWLINE(state, context);
} }