From 5ecec7db105ba48b20b1d6b8496d7caf49759243 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sat, 15 Feb 2014 22:41:02 -0800 Subject: [PATCH 1/7] Move image to first xsize*bands bytes, rather than including padding if stride > xsize*bands, fixes #523 --- libImaging/PcxDecode.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libImaging/PcxDecode.c b/libImaging/PcxDecode.c index 04c86cb35..af282cfe4 100644 --- a/libImaging/PcxDecode.c +++ b/libImaging/PcxDecode.c @@ -57,7 +57,16 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) } if (state->x >= state->bytes) { - + if (state->bytes % state->xsize && state->bytes > state->xsize) { + int bands = state->bytes / state->xsize; + int stride = state->bytes / bands; + int i; + for (i=1; i< bands; i++) { // note -- skipping first band + memmove(&state->buffer[i*state->xsize], + &state->buffer[i*stride], + state->xsize); + } + } /* Got a full line, unpack it */ state->shuffle((UINT8*) im->image[state->y + state->yoff] + state->xoff * im->pixelsize, state->buffer, From 05cd72f4f00a08d7f0f28ebea6c7cb7bbf375dd8 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 3 Mar 2014 20:28:34 -0800 Subject: [PATCH 2/7] mixed 4/8 tabs+spaces -> 4 spaces, additional bracing --- libImaging/PcxEncode.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/libImaging/PcxEncode.c b/libImaging/PcxEncode.c index 87d599463..8c6272d44 100644 --- a/libImaging/PcxEncode.c +++ b/libImaging/PcxEncode.c @@ -5,7 +5,7 @@ * encoder for PCX data * * history: - * 99-02-07 fl created + * 99-02-07 fl created * * Copyright (c) Fredrik Lundh 1999. * Copyright (c) Secret Labs AB 1999. @@ -30,19 +30,18 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) ptr = buf; if (!state->state) { - /* sanity check */ if (state->xsize <= 0 || state->ysize <= 0) { state->errcode = IMAGING_CODEC_END; return 0; } - state->bytes = (state->xsize*state->bits + 7) / 8; + state->bytes = (state->xsize*state->bits + 7) / 8; state->state = FETCH; } - for (;;) + for (;;) { switch (state->state) { case FETCH: @@ -68,7 +67,6 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) /* fall through */ case ENCODE: - /* compress this line */ /* when we arrive here, "count" contains the number of @@ -78,7 +76,6 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) while (state->x < state->bytes) { if (state->count == 63) { - /* this run is full; flush it */ if (bytes < 2) return ptr - buf; @@ -93,7 +90,6 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) this = state->buffer[state->x]; if (this == state->LAST) { - /* extend the current run */ state->x++; state->count++; @@ -102,14 +98,16 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) /* start a new run */ if (state->count == 1 && (state->LAST < 0xc0)) { - if (bytes < 1) + if (bytes < 1) { return ptr - buf; + } *ptr++ = state->LAST; bytes--; } else { if (state->count > 0) { - if (bytes < 2) + if (bytes < 2) { return ptr - buf; + } *ptr++ = 0xc0 | state->count; *ptr++ = state->LAST; bytes -= 2; @@ -126,14 +124,16 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) /* end of line; flush the current run */ if (state->count == 1 && (state->LAST < 0xc0)) { - if (bytes < 1) + if (bytes < 1) { return ptr - buf; + } *ptr++ = state->LAST; bytes--; } else { if (state->count > 0) { - if (bytes < 2) + if (bytes < 2) { return ptr - buf; + } *ptr++ = 0xc0 | state->count; *ptr++ = state->LAST; bytes -= 2; @@ -143,6 +143,7 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) /* read next line */ state->state = FETCH; break; - } + } } + From fe5372c867dfec8171a5737ea56b15badc7c3fe5 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 3 Mar 2014 20:29:14 -0800 Subject: [PATCH 3/7] Debug Loging --- PIL/PcxImagePlugin.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/PIL/PcxImagePlugin.py b/PIL/PcxImagePlugin.py index 42dd9be0b..d90a7cf0d 100644 --- a/PIL/PcxImagePlugin.py +++ b/PIL/PcxImagePlugin.py @@ -55,12 +55,18 @@ class PcxImageFile(ImageFile.ImageFile): bbox = i16(s,4), i16(s,6), i16(s,8)+1, i16(s,10)+1 if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]: raise SyntaxError("bad PCX image size") + if Image.DEBUG: + print ("BBox: %s %s %s %s" % bbox) + # format version = i8(s[1]) bits = i8(s[3]) planes = i8(s[65]) stride = i16(s,66) + if Image.DEBUG: + print ("PCX version %s, bits %s, planes %s, stride %s" % + (version, bits, planes, stride)) self.info["dpi"] = i16(s,12), i16(s,14) @@ -98,7 +104,9 @@ class PcxImageFile(ImageFile.ImageFile): self.size = bbox[2]-bbox[0], bbox[3]-bbox[1] bbox = (0, 0) + self.size - + if Image.DEBUG: + print ("size: %sx%s" % self.size) + self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))] # -------------------------------------------------------------------- From b0f8f498804639768ca5327cf5a45e6a7242fc6a Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 3 Mar 2014 20:43:47 -0800 Subject: [PATCH 4/7] mixed 8 ch tabs + spaces -> spaces --- encode.c | 191 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 98 insertions(+), 93 deletions(-) diff --git a/encode.c b/encode.c index 8be44d8ec..3ceb50731 100644 --- a/encode.c +++ b/encode.c @@ -33,13 +33,13 @@ #endif /* -------------------------------------------------------------------- */ -/* Common */ +/* Common */ /* -------------------------------------------------------------------- */ typedef struct { PyObject_HEAD int (*encode)(Imaging im, ImagingCodecState state, - UINT8* buffer, int bytes); + UINT8* buffer, int bytes); struct ImagingCodecStateInstance state; Imaging im; PyObject* lock; @@ -58,21 +58,21 @@ PyImaging_EncoderNew(int contextsize) encoder = PyObject_New(ImagingEncoderObject, &ImagingEncoderType); if (encoder == NULL) - return NULL; + return NULL; /* Clear the encoder state */ memset(&encoder->state, 0, sizeof(encoder->state)); /* Allocate encoder context */ if (contextsize > 0) { - context = (void*) calloc(1, contextsize); - if (!context) { - Py_DECREF(encoder); - (void) PyErr_NoMemory(); - return NULL; - } + context = (void*) calloc(1, contextsize); + if (!context) { + Py_DECREF(encoder); + (void) PyErr_NoMemory(); + return NULL; + } } else - context = 0; + context = 0; /* Initialize encoder context */ encoder->state.context = context; @@ -105,14 +105,14 @@ _encode(ImagingEncoderObject* encoder, PyObject* args) int bufsize = 16384; if (!PyArg_ParseTuple(args, "|i", &bufsize)) - return NULL; + return NULL; buf = PyBytes_FromStringAndSize(NULL, bufsize); if (!buf) - return NULL; + return NULL; status = encoder->encode(encoder->im, &encoder->state, - (UINT8*) PyBytes_AsString(buf), bufsize); + (UINT8*) PyBytes_AsString(buf), bufsize); /* adjust string length to avoid slicing in encoder */ if (_PyBytes_Resize(&buf, (status > 0) ? status : 0) < 0) @@ -138,28 +138,28 @@ _encode_to_file(ImagingEncoderObject* encoder, PyObject* args) int bufsize = 16384; if (!PyArg_ParseTuple(args, "i|i", &fh, &bufsize)) - return NULL; + return NULL; /* Allocate an encoder buffer */ buf = (UINT8*) malloc(bufsize); if (!buf) - return PyErr_NoMemory(); + return PyErr_NoMemory(); ImagingSectionEnter(&cookie); do { - /* This replaces the inner loop in the ImageFile _save - function. */ + /* This replaces the inner loop in the ImageFile _save + function. */ - status = encoder->encode(encoder->im, &encoder->state, buf, bufsize); + status = encoder->encode(encoder->im, &encoder->state, buf, bufsize); - if (status > 0) - if (write(fh, buf, status) < 0) { + if (status > 0) + if (write(fh, buf, status) < 0) { ImagingSectionLeave(&cookie); - free(buf); - return PyErr_SetFromErrno(PyExc_IOError); - } + free(buf); + return PyErr_SetFromErrno(PyExc_IOError); + } } while (encoder->state.errcode == 0); @@ -186,39 +186,39 @@ _setimage(ImagingEncoderObject* encoder, 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; encoder->im = im; state = &encoder->state; 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 > im->xsize || - state->ysize <= 0 || - state->ysize + state->yoff > im->ysize) { - PyErr_SetString(PyExc_SystemError, "tile cannot extend outside image"); - return NULL; + state->xsize + state->xoff > im->xsize || + state->ysize <= 0 || + state->ysize + state->yoff > im->ysize) { + PyErr_SetString(PyExc_SystemError, "tile cannot extend outside image"); + return NULL; } /* Allocate memory buffer (if bits field is set) */ if (state->bits > 0) { - state->bytes = (state->bits * state->xsize+7)/8; - state->buffer = (UINT8*) malloc(state->bytes); - if (!state->buffer) - return PyErr_NoMemory(); + state->bytes = (state->bits * state->xsize+7)/8; + 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 @@ -239,13 +239,13 @@ static struct PyMethodDef methods[] = { }; static PyTypeObject ImagingEncoderType = { - PyVarObject_HEAD_INIT(NULL, 0) - "ImagingEncoder", /*tp_name*/ - sizeof(ImagingEncoderObject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ + PyVarObject_HEAD_INIT(NULL, 0) + "ImagingEncoder", /*tp_name*/ + sizeof(ImagingEncoderObject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ @@ -283,9 +283,9 @@ get_packer(ImagingEncoderObject* encoder, const char* mode, pack = ImagingFindPacker(mode, rawmode, &bits); if (!pack) { - Py_DECREF(encoder); - PyErr_SetString(PyExc_SystemError, "unknown raw mode"); - return -1; + Py_DECREF(encoder); + PyErr_SetString(PyExc_SystemError, "unknown raw mode"); + return -1; } encoder->state.shuffle = pack; @@ -296,7 +296,7 @@ get_packer(ImagingEncoderObject* encoder, const char* mode, /* -------------------------------------------------------------------- */ -/* EPS */ +/* EPS */ /* -------------------------------------------------------------------- */ PyObject* @@ -306,7 +306,7 @@ PyImaging_EpsEncoderNew(PyObject* self, PyObject* args) encoder = PyImaging_EncoderNew(0); if (encoder == NULL) - return NULL; + return NULL; encoder->encode = ImagingEpsEncode; @@ -315,7 +315,7 @@ PyImaging_EpsEncoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* GIF */ +/* GIF */ /* -------------------------------------------------------------------- */ PyObject* @@ -328,14 +328,14 @@ PyImaging_GifEncoderNew(PyObject* self, PyObject* args) int bits = 8; int interlace = 0; if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &bits, &interlace)) - return NULL; + return NULL; encoder = PyImaging_EncoderNew(sizeof(GIFENCODERSTATE)); if (encoder == NULL) - return NULL; + return NULL; if (get_packer(encoder, mode, rawmode) < 0) - return NULL; + return NULL; encoder->encode = ImagingGifEncode; @@ -347,7 +347,7 @@ PyImaging_GifEncoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* PCX */ +/* PCX */ /* -------------------------------------------------------------------- */ PyObject* @@ -358,15 +358,19 @@ PyImaging_PcxEncoderNew(PyObject* self, PyObject* args) char *mode; char *rawmode; int bits = 8; - if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &bits)) - return NULL; + + if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &bits)) { + return NULL; + } encoder = PyImaging_EncoderNew(0); - if (encoder == NULL) - return NULL; + if (encoder == NULL) { + return NULL; + } - if (get_packer(encoder, mode, rawmode) < 0) - return NULL; + if (get_packer(encoder, mode, rawmode) < 0) { + return NULL; + } encoder->encode = ImagingPcxEncode; @@ -375,7 +379,7 @@ PyImaging_PcxEncoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* RAW */ +/* RAW */ /* -------------------------------------------------------------------- */ PyObject* @@ -389,14 +393,14 @@ PyImaging_RawEncoderNew(PyObject* self, PyObject* args) int ystep = 1; if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep)) - return NULL; + return NULL; encoder = PyImaging_EncoderNew(0); if (encoder == NULL) - return NULL; + return NULL; if (get_packer(encoder, mode, rawmode) < 0) - return NULL; + return NULL; encoder->encode = ImagingRawEncode; @@ -408,7 +412,7 @@ PyImaging_RawEncoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* XBM */ +/* XBM */ /* -------------------------------------------------------------------- */ PyObject* @@ -418,10 +422,10 @@ PyImaging_XbmEncoderNew(PyObject* self, PyObject* args) encoder = PyImaging_EncoderNew(0); if (encoder == NULL) - return NULL; + return NULL; if (get_packer(encoder, "1", "1;R") < 0) - return NULL; + return NULL; encoder->encode = ImagingXbmEncode; @@ -430,7 +434,7 @@ PyImaging_XbmEncoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* ZIP */ +/* ZIP */ /* -------------------------------------------------------------------- */ #ifdef HAVE_LIBZ @@ -469,16 +473,16 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args) encoder = PyImaging_EncoderNew(sizeof(ZIPSTATE)); if (encoder == NULL) - return NULL; + return NULL; if (get_packer(encoder, mode, rawmode) < 0) - return NULL; + return NULL; encoder->encode = ImagingZipEncode; if (rawmode[0] == 'P') - /* disable filtering */ - ((ZIPSTATE*)encoder->state.context)->mode = ZIP_PNG_PALETTE; + /* disable filtering */ + ((ZIPSTATE*)encoder->state.context)->mode = ZIP_PNG_PALETTE; ((ZIPSTATE*)encoder->state.context)->optimize = optimize; ((ZIPSTATE*)encoder->state.context)->compress_level = compress_level; @@ -492,7 +496,7 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args) /* -------------------------------------------------------------------- */ -/* JPEG */ +/* JPEG */ /* -------------------------------------------------------------------- */ #ifdef HAVE_LIBJPEG @@ -500,15 +504,15 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args) /* We better define this encoder 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" @@ -601,14 +605,14 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) &progressive, &smooth, &optimize, &streamtype, &xdpi, &ydpi, &subsampling, &qtables, &extra, &extra_size, &rawExif, &rawExifLen)) - return NULL; + return NULL; encoder = PyImaging_EncoderNew(sizeof(JPEGENCODERSTATE)); if (encoder == NULL) - return NULL; + return NULL; if (get_packer(encoder, mode, rawmode) < 0) - return NULL; + return NULL; qarrays = get_qtables_arrays(qtables); @@ -718,11 +722,11 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) return NULL; } - // While failes on 64 bit machines, complains that pos is an int instead of a Py_ssize_t - // while (PyDict_Next(dir, &pos, &key, &value)) { - for (pos=0;pos Date: Mon, 3 Mar 2014 23:03:00 -0800 Subject: [PATCH 5/7] Tests for issue #523 --- Tests/test_file_pcx.py | 43 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/Tests/test_file_pcx.py b/Tests/test_file_pcx.py index 73d358229..cb785ec54 100644 --- a/Tests/test_file_pcx.py +++ b/Tests/test_file_pcx.py @@ -2,29 +2,30 @@ from tester import * from PIL import Image + +def _roundtrip(im): + f = tempfile("temp.pcx") + im.save(f) + im2 = Image.open(f) + + assert_equal(im2.mode, im.mode) + assert_equal(im2.size, im.size) + assert_equal(im2.format, "PCX") + assert_image_equal(im2, im) + def test_sanity(): + for mode in ('1', 'L', 'P', 'RGB'): + _roundtrip(lena(mode)) - file = tempfile("temp.pcx") - - lena("1").save(file) - - im = Image.open(file) - im.load() - assert_equal(im.mode, "1") - assert_equal(im.size, (128, 128)) - assert_equal(im.format, "PCX") - - lena("1").save(file) - im = Image.open(file) - - lena("L").save(file) - im = Image.open(file) - - lena("P").save(file) - im = Image.open(file) - - lena("RGB").save(file) - im = Image.open(file) +def test_odd(): + # see issue #523, odd sized images should have a stride that's even. + # not that imagemagick or gimp write pcx that way. + # we were not handling properly. + for mode in ('1', 'L', 'P', 'RGB'): + # larger, odd sized images are better here to ensure that + # we handle interrupted scan lines properly. + _roundtrip(lena(mode).resize((511,511))) + def test_pil184(): # Check reading of files where xmin/xmax is not zero. From 89cb3c7e85fdd98b54f0f93fdee36806dc86993e Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 3 Mar 2014 23:03:36 -0800 Subject: [PATCH 6/7] Use even stride when saving odd sized .pcx files --- PIL/PcxImagePlugin.py | 10 +++ libImaging/PcxEncode.c | 149 ++++++++++++++++++++++++++--------------- 2 files changed, 104 insertions(+), 55 deletions(-) diff --git a/PIL/PcxImagePlugin.py b/PIL/PcxImagePlugin.py index d90a7cf0d..2496af676 100644 --- a/PIL/PcxImagePlugin.py +++ b/PIL/PcxImagePlugin.py @@ -134,6 +134,16 @@ def _save(im, fp, filename, check=0): # bytes per plane stride = (im.size[0] * bits + 7) // 8 + # stride should be even + stride = stride + (stride % 2) + # Stride needs to be kept in sync with the PcxEncode.c version. + # Ideally it should be passed in in the state, but the bytes value + # gets overwritten. + + + if Image.DEBUG: + print ("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d" % ( + im.size[0], bits, stride)) # under windows, we could determine the current screen size with # "Image.core.display_mode()[1]", but I think that's overkill... diff --git a/libImaging/PcxEncode.c b/libImaging/PcxEncode.c index 8c6272d44..c1f64a33d 100644 --- a/libImaging/PcxEncode.c +++ b/libImaging/PcxEncode.c @@ -26,6 +26,12 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) { UINT8* ptr; int this; + int bytes_per_line = 0; + int padding = 0; + int stride = 0; + int bpp = 0; + int planes = 1; + int i; ptr = buf; @@ -35,12 +41,25 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) state->errcode = IMAGING_CODEC_END; return 0; } - - state->bytes = (state->xsize*state->bits + 7) / 8; state->state = FETCH; - } + bpp = state->bits; + if (state->bits == 24){ + planes = 3; + bpp = 8; + } + + bytes_per_line = (state->xsize*bpp + 7) / 8; + /* The stride here needs to be kept in sync with the version in + PcxImagePlugin.py. If it's not, the header and the body of the + image will be out of sync and bad things will happen on decode. + */ + stride = bytes_per_line + (bytes_per_line % 2); + + padding = stride - bytes_per_line; + + for (;;) { switch (state->state) { @@ -72,74 +91,94 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) /* when we arrive here, "count" contains the number of bytes having the value of "LAST" that we've already seen */ + while (state->x < planes * bytes_per_line) { + /* If we're encoding an odd width file, and we've + got more than one plane, we need to pad each + color row with padding bytes at the end. Since + The pixels are stored RRRRRGGGGGBBBBB, so we need + to have the padding be RRRRRPGGGGGPBBBBBP. Hence + the double loop + */ + while (state->x % bytes_per_line) { - while (state->x < state->bytes) { - - if (state->count == 63) { - /* this run is full; flush it */ - if (bytes < 2) - return ptr - buf; - *ptr++ = 0xff; - *ptr++ = state->LAST; - bytes -= 2; - - state->count = 0; - - } - - this = state->buffer[state->x]; - - if (this == state->LAST) { - /* extend the current run */ - state->x++; - state->count++; - - } else { - - /* start a new run */ - if (state->count == 1 && (state->LAST < 0xc0)) { - if (bytes < 1) { + if (state->count == 63) { + /* this run is full; flush it */ + if (bytes < 2) return ptr - buf; - } + *ptr++ = 0xff; *ptr++ = state->LAST; - bytes--; + bytes -= 2; + + state->count = 0; + + } + + this = state->buffer[state->x]; + + if (this == state->LAST) { + /* extend the current run */ + state->x++; + state->count++; + } else { - if (state->count > 0) { - if (bytes < 2) { + /* start a new run */ + if (state->count == 1 && (state->LAST < 0xc0)) { + if (bytes < 1) { return ptr - buf; } - *ptr++ = 0xc0 | state->count; *ptr++ = state->LAST; - bytes -= 2; + bytes--; + } else { + if (state->count > 0) { + if (bytes < 2) { + return ptr - buf; + } + *ptr++ = 0xc0 | state->count; + *ptr++ = state->LAST; + bytes -= 2; + } } + + state->LAST = this; + state->count = 1; + + state->x++; + } - - state->LAST = this; - state->count = 1; - - state->x++; - } - } - /* end of line; flush the current run */ - if (state->count == 1 && (state->LAST < 0xc0)) { - if (bytes < 1) { - return ptr - buf; - } - *ptr++ = state->LAST; - bytes--; - } else { - if (state->count > 0) { - if (bytes < 2) { + /* end of line; flush the current run */ + if (state->count == 1 && (state->LAST < 0xc0)) { + if (bytes < 1 + padding) { return ptr - buf; } - *ptr++ = 0xc0 | state->count; *ptr++ = state->LAST; - bytes -= 2; + bytes--; + } else { + if (state->count > 0) { + if (bytes < 2 + padding) { + return ptr - buf; + } + *ptr++ = 0xc0 | state->count; + *ptr++ = state->LAST; + bytes -= 2; + } + } + if (bytes < padding) { + return ptr - buf; + } + /* add the padding */ + for (i=0;ix < planes * bytes_per_line) { + state->count = 1; + state->LAST = state->buffer[state->x]; + state->x++; } } - /* read next line */ state->state = FETCH; break; From ad5609d2001ef3486420ebd1964938c1de3ded9c Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 3 Mar 2014 23:09:35 -0800 Subject: [PATCH 7/7] updated changes --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index ae917acb1..b3838b562 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.4.0 (2014-04-01 est.) ------------------ +- Fixed opening and saving odd sized .pcx files + [wiredfool] + - Fixed DOS with invalid palette size or invalid image size in BMP file [wiredfool]