Pillow

Форк
0
/
GifDecode.c 
285 строк · 9.4 Кб
1
/*
2
 * The Python Imaging Library.
3
 * $Id$
4
 *
5
 * a fast, suspendable GIF decoder
6
 *
7
 * history:
8
 * 95-09-03 fl Created
9
 * 95-09-05 fl Fixed sign problem on 16-bit platforms
10
 * 95-09-13 fl Added some storage shortcuts
11
 * 96-03-28 fl Revised API, integrated with PIL
12
 * 96-12-10 fl Added interlace support
13
 * 96-12-16 fl Fixed premature termination bug introduced by last fix
14
 * 97-01-05 fl Don't mess up on bogus configuration
15
 * 97-01-17 fl Don't mess up on very small, interlaced files
16
 * 99-02-07 fl Minor speedups
17
 *
18
 * Copyright (c) Secret Labs AB 1997-99.
19
 * Copyright (c) Fredrik Lundh 1995-97.
20
 *
21
 * See the README file for information on usage and redistribution.
22
 */
23

24
#include "Imaging.h"
25

26
#include <stdio.h>
27
#include <memory.h> /* memcpy() */
28

29
#include "Gif.h"
30

31
#define NEWLINE(state, context)                                        \
32
    {                                                                  \
33
        state->x = 0;                                                  \
34
        state->y += context->step;                                     \
35
        while (state->y >= state->ysize) switch (context->interlace) { \
36
                case 1:                                                \
37
                    context->repeat = state->y = 4;                    \
38
                    context->interlace = 2;                            \
39
                    break;                                             \
40
                case 2:                                                \
41
                    context->step = 4;                                 \
42
                    context->repeat = state->y = 2;                    \
43
                    context->interlace = 3;                            \
44
                    break;                                             \
45
                case 3:                                                \
46
                    context->step = 2;                                 \
47
                    context->repeat = state->y = 1;                    \
48
                    context->interlace = 0;                            \
49
                    break;                                             \
50
                default:                                               \
51
                    return -1;                                         \
52
            }                                                          \
53
        if (state->y < state->ysize) {                                 \
54
            out = im->image8[state->y + state->yoff] + state->xoff;    \
55
        }                                                              \
56
    }
57

58
int
59
ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes) {
60
    UINT8 *p;
61
    UINT8 *out;
62
    int c, i;
63
    int thiscode;
64
    GIFDECODERSTATE *context = (GIFDECODERSTATE *)state->context;
65

66
    UINT8 *ptr = buffer;
67

68
    if (!state->state) {
69
        /* Initialise state */
70
        if (context->bits < 0 || context->bits > 12) {
71
            state->errcode = IMAGING_CODEC_CONFIG;
72
            return -1;
73
        }
74

75
        /* Clear code */
76
        context->clear = 1 << context->bits;
77

78
        /* End code */
79
        context->end = context->clear + 1;
80

81
        /* Interlace */
82
        if (context->interlace) {
83
            context->interlace = 1;
84
            context->step = context->repeat = 8;
85
        } else {
86
            context->step = 1;
87
        }
88

89
        state->state = 1;
90
    }
91

92
    out = im->image8[state->y + state->yoff] + state->xoff + state->x;
93

94
    for (;;) {
95
        if (state->state == 1) {
96
            /* First free entry in table */
97
            context->next = context->clear + 2;
98

99
            /* Initial code size */
100
            context->codesize = context->bits + 1;
101
            context->codemask = (1 << context->codesize) - 1;
102

103
            /* Buffer pointer.  We fill the buffer from right, which
104
               allows us to return all of it in one operation. */
105
            context->bufferindex = GIFBUFFER;
106

107
            state->state = 2;
108
        }
109

110
        if (context->bufferindex < GIFBUFFER) {
111
            /* Return whole buffer in one chunk */
112
            i = GIFBUFFER - context->bufferindex;
113
            p = &context->buffer[context->bufferindex];
114

115
            context->bufferindex = GIFBUFFER;
116

117
        } else {
118
            /* Get current symbol */
119

120
            while (context->bitcount < context->codesize) {
121
                if (context->blocksize > 0) {
122
                    /* Read next byte */
123
                    c = *ptr++;
124
                    bytes--;
125

126
                    context->blocksize--;
127

128
                    /* New bits are shifted in from the left. */
129
                    context->bitbuffer |= (INT32)c << context->bitcount;
130
                    context->bitcount += 8;
131

132
                } else {
133
                    /* New GIF block */
134

135
                    /* We don't start decoding unless we have a full block */
136
                    if (bytes < 1) {
137
                        return ptr - buffer;
138
                    }
139
                    c = *ptr;
140
                    if (bytes < c + 1) {
141
                        return ptr - buffer;
142
                    }
143

144
                    context->blocksize = c;
145

146
                    ptr++;
147
                    bytes--;
148
                }
149
            }
150

151
            /* Extract current symbol from bit buffer. */
152
            c = (int)context->bitbuffer & context->codemask;
153

154
            /* Adjust buffer */
155
            context->bitbuffer >>= context->codesize;
156
            context->bitcount -= context->codesize;
157

158
            /* If c is less than "clear", it's a data byte.  Otherwise,
159
               it's either clear/end or a code symbol which should be
160
               expanded. */
161

162
            if (c == context->clear) {
163
                if (state->state != 2) {
164
                    state->state = 1;
165
                }
166
                continue;
167
            }
168

169
            if (c == context->end) {
170
                break;
171
            }
172

173
            i = 1;
174
            p = &context->lastdata;
175

176
            if (state->state == 2) {
177
                /* First valid symbol after clear; use as is */
178
                if (c > context->clear) {
179
                    state->errcode = IMAGING_CODEC_BROKEN;
180
                    return -1;
181
                }
182

183
                context->lastdata = context->lastcode = c;
184
                state->state = 3;
185

186
            } else {
187
                thiscode = c;
188

189
                if (c > context->next) {
190
                    state->errcode = IMAGING_CODEC_BROKEN;
191
                    return -1;
192
                }
193

194
                if (c == context->next) {
195
                    /* c == next is allowed. not sure why. */
196

197
                    if (context->bufferindex <= 0) {
198
                        state->errcode = IMAGING_CODEC_BROKEN;
199
                        return -1;
200
                    }
201

202
                    context->buffer[--context->bufferindex] = context->lastdata;
203

204
                    c = context->lastcode;
205
                }
206

207
                while (c >= context->clear) {
208
                    /* Copy data string to buffer (beginning from right) */
209

210
                    if (context->bufferindex <= 0 || c >= GIFTABLE) {
211
                        state->errcode = IMAGING_CODEC_BROKEN;
212
                        return -1;
213
                    }
214

215
                    context->buffer[--context->bufferindex] = context->data[c];
216

217
                    c = context->link[c];
218
                }
219

220
                context->lastdata = c;
221

222
                if (context->next < GIFTABLE) {
223
                    /* We'll only add this symbol if we have room
224
                       for it (take the advice, Netscape!) */
225
                    context->data[context->next] = c;
226
                    context->link[context->next] = context->lastcode;
227

228
                    if (context->next == context->codemask &&
229
                        context->codesize < GIFBITS) {
230
                        /* Expand code size */
231
                        context->codesize++;
232
                        context->codemask = (1 << context->codesize) - 1;
233
                    }
234

235
                    context->next++;
236
                }
237

238
                context->lastcode = thiscode;
239
            }
240
        }
241

242
        /* Copy the bytes into the image */
243
        if (state->y >= state->ysize) {
244
            state->errcode = IMAGING_CODEC_OVERRUN;
245
            return -1;
246
        }
247

248
        /* To squeeze some extra pixels out of this loop, we test for
249
           some common cases and handle them separately. */
250

251
        /* This cannot be used if there is transparency */
252
        if (context->transparency == -1) {
253
            if (i == 1) {
254
                if (state->x < state->xsize - 1) {
255
                    /* Single pixel, not at the end of the line. */
256
                    *out++ = p[0];
257
                    state->x++;
258
                    continue;
259
                }
260
            } else if (state->x + i <= state->xsize) {
261
                /* This string fits into current line. */
262
                memcpy(out, p, i);
263
                out += i;
264
                state->x += i;
265
                if (state->x == state->xsize) {
266
                    NEWLINE(state, context);
267
                }
268
                continue;
269
            }
270
        }
271

272
        /* No shortcut, copy pixel by pixel */
273
        for (c = 0; c < i; c++) {
274
            if (p[c] != context->transparency) {
275
                *out = p[c];
276
            }
277
            out++;
278
            if (++state->x >= state->xsize) {
279
                NEWLINE(state, context);
280
            }
281
        }
282
    }
283

284
    return ptr - buffer;
285
}
286

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.