Pillow

Форк
0
/
SgiRleDecode.c 
290 строк · 8.0 Кб
1
/*
2
 * The Python Imaging Library.
3
 * $Id$
4
 *
5
 * decoder for Sgi RLE data.
6
 *
7
 * history:
8
 * 2017-07-28 mb    fixed for images larger than 64KB
9
 * 2017-07-20 mb    created
10
 *
11
 * Copyright (c) Mickael Bonfill 2017.
12
 *
13
 * See the README file for information on usage and redistribution.
14
 */
15

16
#include "Imaging.h"
17
#include "Sgi.h"
18

19
#define SGI_HEADER_SIZE 512
20
#define RLE_COPY_FLAG 0x80
21
#define RLE_MAX_RUN 0x7f
22

23
static void
24
read4B(UINT32 *dest, UINT8 *buf) {
25
    *dest = (UINT32)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
26
}
27

28
/*
29
   SgiRleDecoding is done in a single channel row oriented set of RLE chunks.
30

31
   * The file is arranged as
32
     - SGI Header
33
     - Rle Offset Table
34
     - Rle Length Table
35
     - Scanline Data
36

37
   * Each RLE atom is c->bpc bytes wide (1 or 2)
38

39
   * Each RLE Chunk is [specifier atom] [ 1 or n data atoms ]
40

41
   * Copy Atoms are a byte with the high bit set, and the low 7 are
42
     the number of bytes to copy from the source to the
43
     destination. e.g.
44

45
         CBBBBBBBB or 0CHLHLHLHLHLHL   (B=byte, H/L = Hi low bytes)
46

47
   * Run atoms do not have the high bit set, and the low 7 bits are
48
     the number of copies of the next atom to copy to the
49
     destination. e.g.:
50

51
         RB -> BBBBB or RHL -> HLHLHLHLHL
52

53
   The upshot of this is, there is no way to determine the required
54
   length of the input buffer from reloffset and rlelength without
55
   going through the data at that scan line.
56

57
   Furthermore, there's no requirement that individual scan lines
58
   pointed to from the rleoffset table are in any sort of order or
59
   used only once, or even disjoint. There's also no requirement that
60
   all of the data in the scan line area of the image file be used
61

62
 */
63
static int
64
expandrow(UINT8 *dest, UINT8 *src, int n, int z, int xsize, UINT8 *end_of_buffer) {
65
    /*
66
     * n here is the number of rlechunks
67
     * z is the number of channels, for calculating the interleave
68
     *   offset to go to RGBA style pixels
69
     * xsize is the row width
70
     * end_of_buffer is the address of the end of the input buffer
71
     */
72

73
    UINT8 pixel, count;
74
    int x = 0;
75

76
    for (; n > 0; n--) {
77
        if (src > end_of_buffer) {
78
            return -1;
79
        }
80
        pixel = *src++;
81
        if (n == 1 && pixel != 0) {
82
            return n;
83
        }
84
        count = pixel & RLE_MAX_RUN;
85
        if (!count) {
86
            return count;
87
        }
88
        if (x + count > xsize) {
89
            return -1;
90
        }
91
        x += count;
92
        if (pixel & RLE_COPY_FLAG) {
93
            if (src + count > end_of_buffer) {
94
                return -1;
95
            }
96
            while (count--) {
97
                *dest = *src++;
98
                dest += z;
99
            }
100

101
        } else {
102
            if (src > end_of_buffer) {
103
                return -1;
104
            }
105
            pixel = *src++;
106
            while (count--) {
107
                *dest = pixel;
108
                dest += z;
109
            }
110
        }
111
    }
112
    return 0;
113
}
114

115
static int
116
expandrow2(
117
    UINT8 *dest, const UINT8 *src, int n, int z, int xsize, UINT8 *end_of_buffer
118
) {
119
    UINT8 pixel, count;
120
    int x = 0;
121

122
    for (; n > 0; n--) {
123
        if (src + 1 > end_of_buffer) {
124
            return -1;
125
        }
126
        pixel = src[1];
127
        src += 2;
128
        if (n == 1 && pixel != 0) {
129
            return n;
130
        }
131
        count = pixel & RLE_MAX_RUN;
132
        if (!count) {
133
            return count;
134
        }
135
        if (x + count > xsize) {
136
            return -1;
137
        }
138
        x += count;
139
        if (pixel & RLE_COPY_FLAG) {
140
            if (src + 2 * count > end_of_buffer) {
141
                return -1;
142
            }
143
            while (count--) {
144
                memcpy(dest, src, 2);
145
                src += 2;
146
                dest += z * 2;
147
            }
148
        } else {
149
            if (src + 2 > end_of_buffer) {
150
                return -1;
151
            }
152
            while (count--) {
153
                memcpy(dest, src, 2);
154
                dest += z * 2;
155
            }
156
            src += 2;
157
        }
158
    }
159
    return 0;
160
}
161

162
int
163
ImagingSgiRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
164
    UINT8 *ptr;
165
    SGISTATE *c;
166
    int err = 0;
167
    int status;
168

169
    /* size check */
170
    if (im->xsize > INT_MAX / im->bands || im->ysize > INT_MAX / im->bands) {
171
        state->errcode = IMAGING_CODEC_MEMORY;
172
        return -1;
173
    }
174

175
    /* Get all data from File descriptor */
176
    c = (SGISTATE *)state->context;
177
    _imaging_seek_pyFd(state->fd, 0L, SEEK_END);
178
    c->bufsize = _imaging_tell_pyFd(state->fd);
179
    c->bufsize -= SGI_HEADER_SIZE;
180

181
    c->tablen = im->bands * im->ysize;
182
    /* below, we populate the starttab and lentab into the bufsize,
183
       each with 4 bytes per element of tablen
184
       Check here before we allocate any memory
185
    */
186
    if (c->bufsize < 8 * c->tablen) {
187
        state->errcode = IMAGING_CODEC_OVERRUN;
188
        return -1;
189
    }
190

191
    ptr = malloc(sizeof(UINT8) * c->bufsize);
192
    if (!ptr) {
193
        state->errcode = IMAGING_CODEC_MEMORY;
194
        return -1;
195
    }
196
    _imaging_seek_pyFd(state->fd, SGI_HEADER_SIZE, SEEK_SET);
197
    if (_imaging_read_pyFd(state->fd, (char *)ptr, c->bufsize) != c->bufsize) {
198
        state->errcode = IMAGING_CODEC_UNKNOWN;
199
        return -1;
200
    }
201

202
    /* decoder initialization */
203
    state->count = 0;
204
    state->y = 0;
205
    if (state->ystep < 0) {
206
        state->y = im->ysize - 1;
207
    } else {
208
        state->ystep = 1;
209
    }
210

211
    /* Allocate memory for RLE tables and rows */
212
    free(state->buffer);
213
    state->buffer = NULL;
214
    /* malloc overflow check above */
215
    state->buffer = calloc(im->xsize * im->bands, sizeof(UINT8) * 2);
216
    c->starttab = calloc(c->tablen, sizeof(UINT32));
217
    c->lengthtab = calloc(c->tablen, sizeof(UINT32));
218
    if (!state->buffer || !c->starttab || !c->lengthtab) {
219
        err = IMAGING_CODEC_MEMORY;
220
        goto sgi_finish_decode;
221
    }
222
    /* populate offsets table */
223
    for (c->tabindex = 0, c->bufindex = 0; c->tabindex < c->tablen;
224
         c->tabindex++, c->bufindex += 4) {
225
        read4B(&c->starttab[c->tabindex], &ptr[c->bufindex]);
226
    }
227
    /* populate lengths table */
228
    for (c->tabindex = 0, c->bufindex = c->tablen * sizeof(UINT32);
229
         c->tabindex < c->tablen;
230
         c->tabindex++, c->bufindex += 4) {
231
        read4B(&c->lengthtab[c->tabindex], &ptr[c->bufindex]);
232
    }
233

234
    /* read compressed rows */
235
    for (c->rowno = 0; c->rowno < im->ysize; c->rowno++, state->y += state->ystep) {
236
        for (c->channo = 0; c->channo < im->bands; c->channo++) {
237
            c->rleoffset = c->starttab[c->rowno + c->channo * im->ysize];
238
            c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize];
239

240
            // Check for underflow of rleoffset-SGI_HEADER_SIZE
241
            if (c->rleoffset < SGI_HEADER_SIZE) {
242
                state->errcode = IMAGING_CODEC_OVERRUN;
243
                goto sgi_finish_decode;
244
            }
245

246
            c->rleoffset -= SGI_HEADER_SIZE;
247

248
            /* row decompression */
249
            if (c->bpc == 1) {
250
                status = expandrow(
251
                    &state->buffer[c->channo],
252
                    &ptr[c->rleoffset],
253
                    c->rlelength,
254
                    im->bands,
255
                    im->xsize,
256
                    &ptr[c->bufsize - 1]
257
                );
258
            } else {
259
                status = expandrow2(
260
                    &state->buffer[c->channo * 2],
261
                    &ptr[c->rleoffset],
262
                    c->rlelength,
263
                    im->bands,
264
                    im->xsize,
265
                    &ptr[c->bufsize - 1]
266
                );
267
            }
268
            if (status == -1) {
269
                state->errcode = IMAGING_CODEC_OVERRUN;
270
                goto sgi_finish_decode;
271
            } else if (status == 1) {
272
                goto sgi_finish_decode;
273
            }
274
        }
275

276
        /* store decompressed data in image */
277
        state->shuffle((UINT8 *)im->image[state->y], state->buffer, im->xsize);
278
    }
279

280
sgi_finish_decode:;
281

282
    free(c->starttab);
283
    free(c->lengthtab);
284
    free(ptr);
285
    if (err != 0) {
286
        state->errcode = err;
287
        return -1;
288
    }
289
    return 0;
290
}
291

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

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

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

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