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