Pillow

Форк
0
/
FliDecode.c 
269 строк · 9.6 Кб
1
/*
2
 * The Python Imaging Library.
3
 * $Id$
4
 *
5
 * decoder for Autodesk Animator FLI/FLC animations
6
 *
7
 * history:
8
 * 97-01-03 fl Created
9
 * 97-01-17 fl Added SS2 support (FLC)
10
 *
11
 * Copyright (c) Fredrik Lundh 1997.
12
 * Copyright (c) Secret Labs AB 1997.
13
 *
14
 * See the README file for information on usage and redistribution.
15
 */
16

17
#include "Imaging.h"
18

19
#define I16(ptr) ((ptr)[0] + ((ptr)[1] << 8))
20

21
#define I32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24))
22

23
#define ERR_IF_DATA_OOB(offset)                 \
24
    if ((data + (offset)) > ptr + bytes) {      \
25
        state->errcode = IMAGING_CODEC_OVERRUN; \
26
        return -1;                              \
27
    }
28

29
int
30
ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
31
    UINT8 *ptr;
32
    int framesize;
33
    int c, chunks, advance;
34
    int l, lines;
35
    int i, j, x = 0, y, ymax;
36

37
    /* If not even the chunk size is present, we'd better leave */
38

39
    if (bytes < 4) {
40
        return 0;
41
    }
42

43
    /* We don't decode anything unless we have a full chunk in the
44
       input buffer */
45

46
    ptr = buf;
47

48
    framesize = I32(ptr);
49
    // there can be one pad byte in the framesize
50
    if (bytes + (bytes % 2) < framesize) {
51
        return 0;
52
    }
53

54
    /* Make sure this is a frame chunk.  The Python driver takes
55
       case of other chunk types. */
56

57
    if (bytes < 8) {
58
        state->errcode = IMAGING_CODEC_OVERRUN;
59
        return -1;
60
    }
61
    if (I16(ptr + 4) != 0xF1FA) {
62
        state->errcode = IMAGING_CODEC_UNKNOWN;
63
        return -1;
64
    }
65

66
    chunks = I16(ptr + 6);
67
    ptr += 16;
68
    bytes -= 16;
69

70
    /* Process subchunks */
71
    for (c = 0; c < chunks; c++) {
72
        UINT8 *data;
73
        if (bytes < 10) {
74
            state->errcode = IMAGING_CODEC_OVERRUN;
75
            return -1;
76
        }
77
        data = ptr + 6;
78
        switch (I16(ptr + 4)) {
79
            case 4:
80
            case 11:
81
                /* FLI COLOR chunk */
82
                break; /* ignored; handled by Python code */
83
            case 7:
84
                /* FLI SS2 chunk (word delta) */
85
                /* OOB ok, we've got 4 bytes min on entry */
86
                lines = I16(data);
87
                data += 2;
88
                for (l = y = 0; l < lines && y < state->ysize; l++, y++) {
89
                    UINT8 *local_buf = (UINT8 *)im->image[y];
90
                    int p, packets;
91
                    ERR_IF_DATA_OOB(2)
92
                    packets = I16(data);
93
                    data += 2;
94
                    while (packets & 0x8000) {
95
                        /* flag word */
96
                        if (packets & 0x4000) {
97
                            y += 65536 - packets; /* skip lines */
98
                            if (y >= state->ysize) {
99
                                state->errcode = IMAGING_CODEC_OVERRUN;
100
                                return -1;
101
                            }
102
                            local_buf = (UINT8 *)im->image[y];
103
                        } else {
104
                            /* store last byte (used if line width is odd) */
105
                            local_buf[state->xsize - 1] = (UINT8)packets;
106
                        }
107
                        ERR_IF_DATA_OOB(2)
108
                        packets = I16(data);
109
                        data += 2;
110
                    }
111
                    for (p = x = 0; p < packets; p++) {
112
                        ERR_IF_DATA_OOB(2)
113
                        x += data[0]; /* pixel skip */
114
                        if (data[1] >= 128) {
115
                            ERR_IF_DATA_OOB(4)
116
                            i = 256 - data[1]; /* run */
117
                            if (x + i + i > state->xsize) {
118
                                break;
119
                            }
120
                            for (j = 0; j < i; j++) {
121
                                local_buf[x++] = data[2];
122
                                local_buf[x++] = data[3];
123
                            }
124
                            data += 2 + 2;
125
                        } else {
126
                            i = 2 * (int)data[1]; /* chunk */
127
                            if (x + i > state->xsize) {
128
                                break;
129
                            }
130
                            ERR_IF_DATA_OOB(2 + i)
131
                            memcpy(local_buf + x, data + 2, i);
132
                            data += 2 + i;
133
                            x += i;
134
                        }
135
                    }
136
                    if (p < packets) {
137
                        break; /* didn't process all packets */
138
                    }
139
                }
140
                if (l < lines) {
141
                    /* didn't process all lines */
142
                    state->errcode = IMAGING_CODEC_OVERRUN;
143
                    return -1;
144
                }
145
                break;
146
            case 12:
147
                /* FLI LC chunk (byte delta) */
148
                /* OOB Check ok, we have 4 bytes min here */
149
                y = I16(data);
150
                ymax = y + I16(data + 2);
151
                data += 4;
152
                for (; y < ymax && y < state->ysize; y++) {
153
                    UINT8 *out = (UINT8 *)im->image[y];
154
                    ERR_IF_DATA_OOB(1)
155
                    int p, packets = *data++;
156
                    for (p = x = 0; p < packets; p++, x += i) {
157
                        ERR_IF_DATA_OOB(2)
158
                        x += data[0]; /* skip pixels */
159
                        if (data[1] & 0x80) {
160
                            i = 256 - data[1]; /* run */
161
                            if (x + i > state->xsize) {
162
                                break;
163
                            }
164
                            ERR_IF_DATA_OOB(3)
165
                            memset(out + x, data[2], i);
166
                            data += 3;
167
                        } else {
168
                            i = data[1]; /* chunk */
169
                            if (x + i > state->xsize) {
170
                                break;
171
                            }
172
                            ERR_IF_DATA_OOB(2 + i)
173
                            memcpy(out + x, data + 2, i);
174
                            data += i + 2;
175
                        }
176
                    }
177
                    if (p < packets) {
178
                        break; /* didn't process all packets */
179
                    }
180
                }
181
                if (y < ymax) {
182
                    /* didn't process all lines */
183
                    state->errcode = IMAGING_CODEC_OVERRUN;
184
                    return -1;
185
                }
186
                break;
187
            case 13:
188
                /* FLI BLACK chunk */
189
                for (y = 0; y < state->ysize; y++) {
190
                    memset(im->image[y], 0, state->xsize);
191
                }
192
                break;
193
            case 15:
194
                /* FLI BRUN chunk */
195
                /* OOB, ok, we've got 4 bytes min on entry */
196
                for (y = 0; y < state->ysize; y++) {
197
                    UINT8 *out = (UINT8 *)im->image[y];
198
                    data += 1; /* ignore packetcount byte */
199
                    for (x = 0; x < state->xsize; x += i) {
200
                        ERR_IF_DATA_OOB(2)
201
                        if (data[0] & 0x80) {
202
                            i = 256 - data[0];
203
                            if (x + i > state->xsize) {
204
                                break; /* safety first */
205
                            }
206
                            ERR_IF_DATA_OOB(i + 1)
207
                            memcpy(out + x, data + 1, i);
208
                            data += i + 1;
209
                        } else {
210
                            i = data[0];
211
                            if (x + i > state->xsize) {
212
                                break; /* safety first */
213
                            }
214
                            memset(out + x, data[1], i);
215
                            data += 2;
216
                        }
217
                    }
218
                    if (x != state->xsize) {
219
                        /* didn't unpack whole line */
220
                        state->errcode = IMAGING_CODEC_OVERRUN;
221
                        return -1;
222
                    }
223
                }
224
                break;
225
            case 16:
226
                /* COPY chunk */
227
                if (INT32_MAX / state->xsize < state->ysize) {
228
                    /* Integer overflow, bail */
229
                    state->errcode = IMAGING_CODEC_OVERRUN;
230
                    return -1;
231
                }
232
                /* Note, have to check Data + size, not just ptr + size) */
233
                if (data + (state->xsize * state->ysize) > ptr + bytes) {
234
                    // not enough data for frame
235
                    // UNDONE Unclear that we're actually going to leave the buffer at
236
                    // the right place.
237
                    return ptr - buf; /* bytes consumed */
238
                }
239
                for (y = 0; y < state->ysize; y++) {
240
                    UINT8 *local_buf = (UINT8 *)im->image[y];
241
                    memcpy(local_buf, data, state->xsize);
242
                    data += state->xsize;
243
                }
244
                break;
245
            case 18:
246
                /* PSTAMP chunk */
247
                break; /* ignored */
248
            default:
249
                /* unknown chunk */
250
                /* printf("unknown FLI/FLC chunk: %d\n", I16(ptr+4)); */
251
                state->errcode = IMAGING_CODEC_UNKNOWN;
252
                return -1;
253
        }
254
        advance = I32(ptr);
255
        if (advance == 0) {
256
            // If there's no advance, we're in an infinite loop
257
            state->errcode = IMAGING_CODEC_BROKEN;
258
            return -1;
259
        }
260
        if (advance < 0 || advance > bytes) {
261
            state->errcode = IMAGING_CODEC_OVERRUN;
262
            return -1;
263
        }
264
        ptr += advance;
265
        bytes -= advance;
266
    }
267

268
    return -1; /* end of frame */
269
}
270

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

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

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

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