diff --git a/PIL/ImageFile.py b/PIL/ImageFile.py index b08f14b90..28c60c8b3 100644 --- a/PIL/ImageFile.py +++ b/PIL/ImageFile.py @@ -209,6 +209,10 @@ class ImageFile(Image.Image): if not s: # truncated jpeg self.tile = [] + # JpegDecode needs to clean things up here either way + # If we don't destroy the decompressor, we have a memory leak. + d.cleanup() + if LOAD_TRUNCATED_IMAGES: break else: diff --git a/decode.c b/decode.c index 41557d687..29d417ed0 100644 --- a/decode.c +++ b/decode.c @@ -41,13 +41,14 @@ /* -------------------------------------------------------------------- */ -/* Common */ +/* Common */ /* -------------------------------------------------------------------- */ typedef struct { PyObject_HEAD int (*decode)(Imaging im, ImagingCodecState state, - UINT8* buffer, int bytes); + UINT8* buffer, int bytes); + int (*cleanup)(ImagingCodecState state); struct ImagingCodecStateInstance state; Imaging im; PyObject* lock; @@ -66,21 +67,21 @@ PyImaging_DecoderNew(int contextsize) decoder = PyObject_New(ImagingDecoderObject, &ImagingDecoderType); if (decoder == NULL) - return NULL; + return NULL; /* Clear the decoder state */ memset(&decoder->state, 0, sizeof(decoder->state)); /* Allocate decoder context */ if (contextsize > 0) { - context = (void*) calloc(1, contextsize); - if (!context) { - Py_DECREF(decoder); - (void) PyErr_NoMemory(); - return NULL; - } + context = (void*) calloc(1, contextsize); + if (!context) { + Py_DECREF(decoder); + (void) PyErr_NoMemory(); + return NULL; + } } else - context = 0; + context = 0; /* Initialize decoder context */ decoder->state.context = context; @@ -88,6 +89,9 @@ PyImaging_DecoderNew(int contextsize) /* Target image */ decoder->lock = NULL; decoder->im = NULL; + + /* Initialize the cleanup function pointer */ + decoder->cleanup = NULL; return decoder; } @@ -108,13 +112,27 @@ _decode(ImagingDecoderObject* decoder, PyObject* args) int bufsize, status; if (!PyArg_ParseTuple(args, PY_ARG_BYTES_LENGTH, &buffer, &bufsize)) - return NULL; + return NULL; status = decoder->decode(decoder->im, &decoder->state, buffer, bufsize); return Py_BuildValue("ii", status, decoder->state.errcode); } +static PyObject* +_decode_cleanup(ImagingDecoderObject* decoder, PyObject* args) +{ + int status = 0; + + if (decoder->cleanup){ + status = decoder->cleanup(&decoder->state); + } + + return Py_BuildValue("i", status); +} + + + extern Imaging PyImaging_AsImaging(PyObject *op); static PyObject* @@ -129,10 +147,10 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args) /* FIXME: should publish the ImagingType descriptor */ if (!PyArg_ParseTuple(args, "O|(iiii)", &op, &x0, &y0, &x1, &y1)) - return NULL; + return NULL; im = PyImaging_AsImaging(op); if (!im) - return NULL; + return NULL; decoder->im = im; @@ -140,30 +158,30 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args) /* Setup decoding tile extent */ if (x0 == 0 && x1 == 0) { - state->xsize = im->xsize; - state->ysize = im->ysize; + state->xsize = im->xsize; + state->ysize = im->ysize; } else { - state->xoff = x0; - state->yoff = y0; - state->xsize = x1 - x0; - state->ysize = y1 - y0; + state->xoff = x0; + state->yoff = y0; + state->xsize = x1 - x0; + state->ysize = y1 - y0; } if (state->xsize <= 0 || - state->xsize + state->xoff > (int) im->xsize || - state->ysize <= 0 || - state->ysize + state->yoff > (int) im->ysize) { - PyErr_SetString(PyExc_ValueError, "tile cannot extend outside image"); - return NULL; + state->xsize + state->xoff > (int) im->xsize || + state->ysize <= 0 || + state->ysize + state->yoff > (int) im->ysize) { + PyErr_SetString(PyExc_ValueError, "tile cannot extend outside image"); + return NULL; } /* Allocate memory buffer (if bits field is set) */ if (state->bits > 0) { if (!state->bytes) state->bytes = (state->bits * state->xsize+7)/8; - state->buffer = (UINT8*) malloc(state->bytes); - if (!state->buffer) - return PyErr_NoMemory(); + state->buffer = (UINT8*) malloc(state->bytes); + if (!state->buffer) + return PyErr_NoMemory(); } /* Keep a reference to the image object, to make sure it doesn't @@ -178,18 +196,19 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args) static struct PyMethodDef methods[] = { {"decode", (PyCFunction)_decode, 1}, + {"cleanup", (PyCFunction)_decode_cleanup, 1}, {"setimage", (PyCFunction)_setimage, 1}, {NULL, NULL} /* sentinel */ }; static PyTypeObject ImagingDecoderType = { - PyVarObject_HEAD_INIT(NULL, 0) - "ImagingDecoder", /*tp_name*/ - sizeof(ImagingDecoderObject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ + PyVarObject_HEAD_INIT(NULL, 0) + "ImagingDecoder", /*tp_name*/ + sizeof(ImagingDecoderObject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ @@ -227,9 +246,9 @@ get_unpacker(ImagingDecoderObject* decoder, const char* mode, unpack = ImagingFindUnpacker(mode, rawmode, &bits); if (!unpack) { - Py_DECREF(decoder); - PyErr_SetString(PyExc_ValueError, "unknown raw mode"); - return -1; + Py_DECREF(decoder); + PyErr_SetString(PyExc_ValueError, "unknown raw mode"); + return -1; } decoder->state.shuffle = unpack; @@ -240,7 +259,7 @@ get_unpacker(ImagingDecoderObject* decoder, const char* mode, /* -------------------------------------------------------------------- */ -/* BIT (packed fields) */ +/* BIT (packed fields) */ /* -------------------------------------------------------------------- */ PyObject* @@ -256,16 +275,16 @@ PyImaging_BitDecoderNew(PyObject* self, PyObject* args) int ystep = 1; if (!PyArg_ParseTuple(args, "s|iiiii", &mode, &bits, &pad, &fill, &sign, &ystep)) - return NULL; + return NULL; if (strcmp(mode, "F") != 0) { - PyErr_SetString(PyExc_ValueError, "bad image mode"); + PyErr_SetString(PyExc_ValueError, "bad image mode"); return NULL; } decoder = PyImaging_DecoderNew(sizeof(BITSTATE)); if (decoder == NULL) - return NULL; + return NULL; decoder->decode = ImagingBitDecode; @@ -281,7 +300,7 @@ PyImaging_BitDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* FLI */ +/* FLI */ /* -------------------------------------------------------------------- */ PyObject* @@ -291,7 +310,7 @@ PyImaging_FliDecoderNew(PyObject* self, PyObject* args) decoder = PyImaging_DecoderNew(0); if (decoder == NULL) - return NULL; + return NULL; decoder->decode = ImagingFliDecode; @@ -300,7 +319,7 @@ PyImaging_FliDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* GIF */ +/* GIF */ /* -------------------------------------------------------------------- */ PyObject* @@ -312,16 +331,16 @@ PyImaging_GifDecoderNew(PyObject* self, PyObject* args) int bits = 8; int interlace = 0; if (!PyArg_ParseTuple(args, "s|ii", &mode, &bits, &interlace)) - return NULL; + return NULL; if (strcmp(mode, "L") != 0 && strcmp(mode, "P") != 0) { - PyErr_SetString(PyExc_ValueError, "bad image mode"); + PyErr_SetString(PyExc_ValueError, "bad image mode"); return NULL; } decoder = PyImaging_DecoderNew(sizeof(GIFDECODERSTATE)); if (decoder == NULL) - return NULL; + return NULL; decoder->decode = ImagingGifDecode; @@ -333,7 +352,7 @@ PyImaging_GifDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* HEX */ +/* HEX */ /* -------------------------------------------------------------------- */ PyObject* @@ -344,14 +363,14 @@ PyImaging_HexDecoderNew(PyObject* self, PyObject* args) char* mode; char* rawmode; if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) - return NULL; + return NULL; decoder = PyImaging_DecoderNew(0); if (decoder == NULL) - return NULL; + return NULL; if (get_unpacker(decoder, mode, rawmode) < 0) - return NULL; + return NULL; decoder->decode = ImagingHexDecode; @@ -360,7 +379,7 @@ PyImaging_HexDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* LZW */ +/* LZW */ /* -------------------------------------------------------------------- */ PyObject* @@ -372,14 +391,14 @@ PyImaging_TiffLzwDecoderNew(PyObject* self, PyObject* args) char* rawmode; int filter = 0; if (!PyArg_ParseTuple(args, "ss|i", &mode, &rawmode, &filter)) - return NULL; + return NULL; decoder = PyImaging_DecoderNew(sizeof(LZWSTATE)); if (decoder == NULL) - return NULL; + return NULL; if (get_unpacker(decoder, mode, rawmode) < 0) - return NULL; + return NULL; decoder->decode = ImagingLzwDecode; @@ -389,7 +408,7 @@ PyImaging_TiffLzwDecoderNew(PyObject* self, PyObject* args) } /* -------------------------------------------------------------------- */ -/* LibTiff */ +/* LibTiff */ /* -------------------------------------------------------------------- */ #ifdef HAVE_LIBTIFF @@ -409,17 +428,17 @@ PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args) char* rawmode; char* compname; int compression; - int fp; + int fp; if (! PyArg_ParseTuple(args, "sssi", &mode, &rawmode, &compname, &fp)) - return NULL; + return NULL; TRACE(("new tiff decoder %s\n", compname)); - - /* UNDONE -- we can probably do almost any arbitrary compression here, - * since we're effective passing in the whole file in one shot and - * getting back the data row by row. V2 maybe - */ + + /* UNDONE -- we can probably do almost any arbitrary compression here, + * since we're effective passing in the whole file in one shot and + * getting back the data row by row. V2 maybe + */ if (strcasecmp(compname, "tiff_ccitt") == 0) { compression = COMPRESSION_CCITTRLE; @@ -459,7 +478,7 @@ PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args) #endif /* -------------------------------------------------------------------- */ -/* MSP */ +/* MSP */ /* -------------------------------------------------------------------- */ PyObject* @@ -469,10 +488,10 @@ PyImaging_MspDecoderNew(PyObject* self, PyObject* args) decoder = PyImaging_DecoderNew(0); if (decoder == NULL) - return NULL; + return NULL; if (get_unpacker(decoder, "1", "1") < 0) - return NULL; + return NULL; decoder->decode = ImagingMspDecode; @@ -481,7 +500,7 @@ PyImaging_MspDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* PackBits */ +/* PackBits */ /* -------------------------------------------------------------------- */ PyObject* @@ -492,14 +511,14 @@ PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args) char* mode; char* rawmode; if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) - return NULL; + return NULL; decoder = PyImaging_DecoderNew(0); if (decoder == NULL) - return NULL; + return NULL; if (get_unpacker(decoder, mode, rawmode) < 0) - return NULL; + return NULL; decoder->decode = ImagingPackbitsDecode; @@ -508,7 +527,7 @@ PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* PCD */ +/* PCD */ /* -------------------------------------------------------------------- */ PyObject* @@ -518,11 +537,11 @@ PyImaging_PcdDecoderNew(PyObject* self, PyObject* args) decoder = PyImaging_DecoderNew(0); if (decoder == NULL) - return NULL; + return NULL; /* Unpack from PhotoYCC to RGB */ if (get_unpacker(decoder, "RGB", "YCC;P") < 0) - return NULL; + return NULL; decoder->decode = ImagingPcdDecode; @@ -531,7 +550,7 @@ PyImaging_PcdDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* PCX */ +/* PCX */ /* -------------------------------------------------------------------- */ PyObject* @@ -543,14 +562,14 @@ PyImaging_PcxDecoderNew(PyObject* self, PyObject* args) char* rawmode; int stride; if (!PyArg_ParseTuple(args, "ssi", &mode, &rawmode, &stride)) - return NULL; + return NULL; decoder = PyImaging_DecoderNew(0); if (decoder == NULL) - return NULL; + return NULL; if (get_unpacker(decoder, mode, rawmode) < 0) - return NULL; + return NULL; decoder->state.bytes = stride; @@ -561,7 +580,7 @@ PyImaging_PcxDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* RAW */ +/* RAW */ /* -------------------------------------------------------------------- */ PyObject* @@ -574,14 +593,14 @@ PyImaging_RawDecoderNew(PyObject* self, PyObject* args) int stride = 0; int ystep = 1; if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep)) - return NULL; + return NULL; decoder = PyImaging_DecoderNew(sizeof(RAWSTATE)); if (decoder == NULL) - return NULL; + return NULL; if (get_unpacker(decoder, mode, rawmode) < 0) - return NULL; + return NULL; decoder->decode = ImagingRawDecode; @@ -594,7 +613,7 @@ PyImaging_RawDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* SUN RLE */ +/* SUN RLE */ /* -------------------------------------------------------------------- */ PyObject* @@ -605,14 +624,14 @@ PyImaging_SunRleDecoderNew(PyObject* self, PyObject* args) char* mode; char* rawmode; if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) - return NULL; + return NULL; decoder = PyImaging_DecoderNew(0); if (decoder == NULL) - return NULL; + return NULL; if (get_unpacker(decoder, mode, rawmode) < 0) - return NULL; + return NULL; decoder->decode = ImagingSunRleDecode; @@ -621,7 +640,7 @@ PyImaging_SunRleDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* TGA RLE */ +/* TGA RLE */ /* -------------------------------------------------------------------- */ PyObject* @@ -634,14 +653,14 @@ PyImaging_TgaRleDecoderNew(PyObject* self, PyObject* args) int ystep = 1; int depth = 8; if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &depth)) - return NULL; + return NULL; decoder = PyImaging_DecoderNew(0); if (decoder == NULL) - return NULL; + return NULL; if (get_unpacker(decoder, mode, rawmode) < 0) - return NULL; + return NULL; decoder->decode = ImagingTgaRleDecode; @@ -653,7 +672,7 @@ PyImaging_TgaRleDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* XBM */ +/* XBM */ /* -------------------------------------------------------------------- */ PyObject* @@ -663,10 +682,10 @@ PyImaging_XbmDecoderNew(PyObject* self, PyObject* args) decoder = PyImaging_DecoderNew(0); if (decoder == NULL) - return NULL; + return NULL; if (get_unpacker(decoder, "1", "1;R") < 0) - return NULL; + return NULL; decoder->decode = ImagingXbmDecode; @@ -675,7 +694,7 @@ PyImaging_XbmDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* ZIP */ +/* ZIP */ /* -------------------------------------------------------------------- */ #ifdef HAVE_LIBZ @@ -691,14 +710,14 @@ PyImaging_ZipDecoderNew(PyObject* self, PyObject* args) char* rawmode; int interlaced = 0; if (!PyArg_ParseTuple(args, "ss|i", &mode, &rawmode, &interlaced)) - return NULL; + return NULL; decoder = PyImaging_DecoderNew(sizeof(ZIPSTATE)); if (decoder == NULL) - return NULL; + return NULL; if (get_unpacker(decoder, mode, rawmode) < 0) - return NULL; + return NULL; decoder->decode = ImagingZipDecode; @@ -710,7 +729,7 @@ PyImaging_ZipDecoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* JPEG */ +/* JPEG */ /* -------------------------------------------------------------------- */ #ifdef HAVE_LIBJPEG @@ -718,15 +737,15 @@ PyImaging_ZipDecoderNew(PyObject* self, PyObject* args) /* We better define this decoder last in this file, so the following undef's won't mess things up for the Imaging library proper. */ -#undef HAVE_PROTOTYPES -#undef HAVE_STDDEF_H -#undef HAVE_STDLIB_H -#undef UINT8 -#undef UINT16 -#undef UINT32 -#undef INT8 -#undef INT16 -#undef INT32 +#undef HAVE_PROTOTYPES +#undef HAVE_STDDEF_H +#undef HAVE_STDLIB_H +#undef UINT8 +#undef UINT16 +#undef UINT32 +#undef INT8 +#undef INT16 +#undef INT32 #include "Jpeg.h" @@ -742,19 +761,20 @@ PyImaging_JpegDecoderNew(PyObject* self, PyObject* args) int draft = 0; if (!PyArg_ParseTuple(args, "ssz|ii", &mode, &rawmode, &jpegmode, &scale, &draft)) - return NULL; + return NULL; if (!jpegmode) - jpegmode = ""; + jpegmode = ""; decoder = PyImaging_DecoderNew(sizeof(JPEGSTATE)); if (decoder == NULL) - return NULL; + return NULL; if (get_unpacker(decoder, mode, rawmode) < 0) - return NULL; + return NULL; decoder->decode = ImagingJpegDecode; + decoder->cleanup = ImagingJpegDecodeCleanup; strncpy(((JPEGSTATE*)decoder->state.context)->rawmode, rawmode, 8); strncpy(((JPEGSTATE*)decoder->state.context)->jpegmode, jpegmode, 8); diff --git a/libImaging/Imaging.h b/libImaging/Imaging.h index cf94dae0b..ddcec14c9 100644 --- a/libImaging/Imaging.h +++ b/libImaging/Imaging.h @@ -417,6 +417,8 @@ extern int ImagingHexDecode(Imaging im, ImagingCodecState state, #ifdef HAVE_LIBJPEG extern int ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buffer, int bytes); +extern int ImagingJpegDecodeCleanup(ImagingCodecState state); + extern int ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int bytes); #endif diff --git a/libImaging/JpegDecode.c b/libImaging/JpegDecode.c index 11b2767ba..57544f7ad 100644 --- a/libImaging/JpegDecode.c +++ b/libImaging/JpegDecode.c @@ -24,7 +24,7 @@ #include "Imaging.h" -#ifdef HAVE_LIBJPEG +#ifdef HAVE_LIBJPEG #undef HAVE_PROTOTYPES #undef HAVE_STDLIB_H @@ -39,7 +39,7 @@ /* -------------------------------------------------------------------- */ -/* Suspending input handler */ +/* Suspending input handler */ /* -------------------------------------------------------------------- */ METHODDEF(void) @@ -61,16 +61,16 @@ skip_input_data(j_decompress_ptr cinfo, long num_bytes) JPEGSOURCE* source = (JPEGSOURCE*) cinfo->src; if (num_bytes > (long) source->pub.bytes_in_buffer) { - /* We need to skip more data than we have in the buffer. - This will force the JPEG library to suspend decoding. */ - source->skip = num_bytes - source->pub.bytes_in_buffer; - source->pub.next_input_byte += source->pub.bytes_in_buffer; - source->pub.bytes_in_buffer = 0; + /* We need to skip more data than we have in the buffer. + This will force the JPEG library to suspend decoding. */ + source->skip = num_bytes - source->pub.bytes_in_buffer; + source->pub.next_input_byte += source->pub.bytes_in_buffer; + source->pub.bytes_in_buffer = 0; } else { - /* Skip portion of the buffer */ - source->pub.bytes_in_buffer -= num_bytes; - source->pub.next_input_byte += num_bytes; - source->skip = 0; + /* Skip portion of the buffer */ + source->pub.bytes_in_buffer -= num_bytes; + source->pub.next_input_byte += num_bytes; + source->skip = 0; } } @@ -93,7 +93,7 @@ jpeg_buffer_src(j_decompress_ptr cinfo, JPEGSOURCE* source) /* -------------------------------------------------------------------- */ -/* Error handler */ +/* Error handler */ /* -------------------------------------------------------------------- */ METHODDEF(void) @@ -111,7 +111,7 @@ output(j_common_ptr cinfo) } /* -------------------------------------------------------------------- */ -/* Decoder */ +/* Decoder */ /* -------------------------------------------------------------------- */ int @@ -121,23 +121,23 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) int ok; if (setjmp(context->error.setjmp_buffer)) { - /* JPEG error handler */ - jpeg_destroy_decompress(&context->cinfo); - state->errcode = IMAGING_CODEC_BROKEN; - return -1; + /* JPEG error handler */ + jpeg_destroy_decompress(&context->cinfo); + state->errcode = IMAGING_CODEC_BROKEN; + return -1; } if (!state->state) { - /* Setup decompression context */ - context->cinfo.err = jpeg_std_error(&context->error.pub); - context->error.pub.error_exit = error; - context->error.pub.output_message = output; - jpeg_create_decompress(&context->cinfo); - jpeg_buffer_src(&context->cinfo, &context->source); + /* Setup decompression context */ + context->cinfo.err = jpeg_std_error(&context->error.pub); + context->error.pub.error_exit = error; + context->error.pub.output_message = output; + jpeg_create_decompress(&context->cinfo); + jpeg_buffer_src(&context->cinfo, &context->source); - /* Ready to decode */ - state->state = 1; + /* Ready to decode */ + state->state = 1; } @@ -146,115 +146,115 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) context->source.pub.bytes_in_buffer = bytes; if (context->source.skip > 0) { - skip_input_data(&context->cinfo, context->source.skip); - if (context->source.skip > 0) - return context->source.pub.next_input_byte - buf; + skip_input_data(&context->cinfo, context->source.skip); + if (context->source.skip > 0) + return context->source.pub.next_input_byte - buf; } switch (state->state) { case 1: - /* Read JPEG header, until we find an image body. */ - do { - - /* Note that we cannot return unless we have decoded - as much data as possible. */ - ok = jpeg_read_header(&context->cinfo, FALSE); + /* Read JPEG header, until we find an image body. */ + do { + + /* Note that we cannot return unless we have decoded + as much data as possible. */ + ok = jpeg_read_header(&context->cinfo, FALSE); - } while (ok == JPEG_HEADER_TABLES_ONLY); + } while (ok == JPEG_HEADER_TABLES_ONLY); - if (ok == JPEG_SUSPENDED) - break; + if (ok == JPEG_SUSPENDED) + break; - /* Decoder settings */ + /* Decoder settings */ - /* jpegmode indicates whats in the file; if not set, we'll - trust the decoder */ - if (strcmp(context->jpegmode, "L") == 0) - context->cinfo.jpeg_color_space = JCS_GRAYSCALE; - else if (strcmp(context->jpegmode, "RGB") == 0) - context->cinfo.jpeg_color_space = JCS_RGB; - else if (strcmp(context->jpegmode, "CMYK") == 0) - context->cinfo.jpeg_color_space = JCS_CMYK; - else if (strcmp(context->jpegmode, "YCbCr") == 0) - context->cinfo.jpeg_color_space = JCS_YCbCr; - else if (strcmp(context->jpegmode, "YCbCrK") == 0) { - context->cinfo.jpeg_color_space = JCS_YCCK; - } + /* jpegmode indicates whats in the file; if not set, we'll + trust the decoder */ + if (strcmp(context->jpegmode, "L") == 0) + context->cinfo.jpeg_color_space = JCS_GRAYSCALE; + else if (strcmp(context->jpegmode, "RGB") == 0) + context->cinfo.jpeg_color_space = JCS_RGB; + else if (strcmp(context->jpegmode, "CMYK") == 0) + context->cinfo.jpeg_color_space = JCS_CMYK; + else if (strcmp(context->jpegmode, "YCbCr") == 0) + context->cinfo.jpeg_color_space = JCS_YCbCr; + else if (strcmp(context->jpegmode, "YCbCrK") == 0) { + context->cinfo.jpeg_color_space = JCS_YCCK; + } - /* rawmode indicates what we want from the decoder. if not - set, conversions are disabled */ - if (strcmp(context->rawmode, "L") == 0) - context->cinfo.out_color_space = JCS_GRAYSCALE; - else if (strcmp(context->rawmode, "RGB") == 0) - context->cinfo.out_color_space = JCS_RGB; - else if (strcmp(context->rawmode, "CMYK") == 0 || + /* rawmode indicates what we want from the decoder. if not + set, conversions are disabled */ + if (strcmp(context->rawmode, "L") == 0) + context->cinfo.out_color_space = JCS_GRAYSCALE; + else if (strcmp(context->rawmode, "RGB") == 0) + context->cinfo.out_color_space = JCS_RGB; + else if (strcmp(context->rawmode, "CMYK") == 0 || strcmp(context->rawmode, "CMYK;I") == 0) - context->cinfo.out_color_space = JCS_CMYK; - else if (strcmp(context->rawmode, "YCbCr") == 0) - context->cinfo.out_color_space = JCS_YCbCr; - else if (strcmp(context->rawmode, "YCbCrK") == 0) - context->cinfo.out_color_space = JCS_YCCK; - else { - /* Disable decoder conversions */ - context->cinfo.jpeg_color_space = JCS_UNKNOWN; - context->cinfo.out_color_space = JCS_UNKNOWN; - } + context->cinfo.out_color_space = JCS_CMYK; + else if (strcmp(context->rawmode, "YCbCr") == 0) + context->cinfo.out_color_space = JCS_YCbCr; + else if (strcmp(context->rawmode, "YCbCrK") == 0) + context->cinfo.out_color_space = JCS_YCCK; + else { + /* Disable decoder conversions */ + context->cinfo.jpeg_color_space = JCS_UNKNOWN; + context->cinfo.out_color_space = JCS_UNKNOWN; + } - if (context->scale > 1) { - context->cinfo.scale_num = 1; - context->cinfo.scale_denom = context->scale; - } - if (context->draft) { - context->cinfo.do_fancy_upsampling = FALSE; - context->cinfo.dct_method = JDCT_FASTEST; - } + if (context->scale > 1) { + context->cinfo.scale_num = 1; + context->cinfo.scale_denom = context->scale; + } + if (context->draft) { + context->cinfo.do_fancy_upsampling = FALSE; + context->cinfo.dct_method = JDCT_FASTEST; + } state->state++; - /* fall through */ + /* fall through */ case 2: /* Set things up for decompression (this processes the entire file if necessary to return data line by line) */ - if (!jpeg_start_decompress(&context->cinfo)) + if (!jpeg_start_decompress(&context->cinfo)) break; - state->state++; - /* fall through */ + state->state++; + /* fall through */ case 3: - /* Decompress a single line of data */ - ok = 1; - while (state->y < state->ysize) { - ok = jpeg_read_scanlines(&context->cinfo, &state->buffer, 1); - if (ok != 1) - break; - state->shuffle((UINT8*) im->image[state->y + state->yoff] + - state->xoff * im->pixelsize, state->buffer, - state->xsize); - state->y++; - } - if (ok != 1) - break; - state->state++; - /* fall through */ + /* Decompress a single line of data */ + ok = 1; + while (state->y < state->ysize) { + ok = jpeg_read_scanlines(&context->cinfo, &state->buffer, 1); + if (ok != 1) + break; + state->shuffle((UINT8*) im->image[state->y + state->yoff] + + state->xoff * im->pixelsize, state->buffer, + state->xsize); + state->y++; + } + if (ok != 1) + break; + state->state++; + /* fall through */ case 4: - /* Finish decompression */ - if (!jpeg_finish_decompress(&context->cinfo)) { + /* Finish decompression */ + if (!jpeg_finish_decompress(&context->cinfo)) { /* FIXME: add strictness mode test */ if (state->y < state->ysize) break; } - /* Clean up */ - jpeg_destroy_decompress(&context->cinfo); - /* if (jerr.pub.num_warnings) return BROKEN; */ - return -1; + /* Clean up */ + jpeg_destroy_decompress(&context->cinfo); + /* if (jerr.pub.num_warnings) return BROKEN; */ + return -1; } @@ -263,5 +263,20 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) } +/* -------------------------------------------------------------------- */ +/* Cleanup */ +/* -------------------------------------------------------------------- */ + +int ImagingJpegDecodeCleanup(ImagingCodecState state){ + /* called to fee the decompression engine when the decode terminates + due to a corrupt or truncated image + */ + JPEGSTATE* context = (JPEGSTATE*) state->context; + + /* Clean up */ + jpeg_destroy_decompress(&context->cinfo); + return -1; +} + #endif