diff --git a/Tests/images/hopper16.rgb b/Tests/images/hopper16.rgb new file mode 100755 index 000000000..c3c7fb735 Binary files /dev/null and b/Tests/images/hopper16.rgb differ diff --git a/Tests/images/tv.rgb b/Tests/images/tv.rgb new file mode 100755 index 000000000..dcb2a99a2 Binary files /dev/null and b/Tests/images/tv.rgb differ diff --git a/Tests/images/tv16.sgi b/Tests/images/tv16.sgi new file mode 100755 index 000000000..432f03280 Binary files /dev/null and b/Tests/images/tv16.sgi differ diff --git a/Tests/test_file_sgi.py b/Tests/test_file_sgi.py index f2e3cfc62..c7a4c1945 100644 --- a/Tests/test_file_sgi.py +++ b/Tests/test_file_sgi.py @@ -13,6 +13,12 @@ class TestFileSgi(PillowTestCase): im = Image.open(test_file) self.assert_image_equal(im, hopper()) + def test_rgb16(self): + test_file = "Tests/images/hopper16.rgb" + + im = Image.open(test_file) + self.assert_image_equal(im, hopper()) + def test_l(self): # Created with ImageMagick # convert hopper.ppm -monochrome -compress None sgi:hopper.bw @@ -39,6 +45,13 @@ class TestFileSgi(PillowTestCase): target = Image.open('Tests/images/hopper.rgb') self.assert_image_equal(im, target) + def test_rle16(self): + test_file = "Tests/images/tv16.sgi" + + im = Image.open(test_file) + target = Image.open('Tests/images/tv.rgb') + self.assert_image_equal(im, target) + def test_invalid_file(self): invalid_file = "Tests/images/flower.jpg" diff --git a/libImaging/SgiRleDecode.c b/libImaging/SgiRleDecode.c index 0d195d41e..133f30196 100644 --- a/libImaging/SgiRleDecode.c +++ b/libImaging/SgiRleDecode.c @@ -15,12 +15,8 @@ #include "Imaging.h" #include "Sgi.h" -#include -#include -#include #define SGI_HEADER_SIZE 512 -#define SGI_MAGIC 0x01DA #define RLE_COPY_FLAG 0x80 #define RLE_MAX_RUN 0x7f @@ -63,10 +59,11 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z) static int expandrow2(UINT16* dest, UINT16* src, int n, int z) { UINT8 pixel, count; - + + for (;n > 0; n--) { - pixel = ((UINT8*)src)[0]; + pixel = ((UINT8*)src)[1]; ++src; if (n == 1 && pixel != 0) return n; @@ -101,34 +98,41 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, UINT8 *ptr; SGISTATE *context; - context = (SGISTATE*)state->context; + /* Get all data from File descriptor */ _imaging_seek_pyFd(state->fd, 0L, SEEK_END); bufsize = _imaging_tell_pyFd(state->fd); bufsize -= SGI_HEADER_SIZE; ptr = malloc(sizeof(UINT8) * bufsize); - state->count = 0; _imaging_seek_pyFd(state->fd, SGI_HEADER_SIZE, SEEK_SET); _imaging_read_pyFd(state->fd, ptr, bufsize); + /* decoder initialization */ + state->count = 0; + context = (SGISTATE*)state->context; state->y = 0; if (state->ystep < 0) state->y = im->ysize - 1; else state->ystep = 1; + /* Allocate memory for RLE tables and rows */ + free(state->buffer); + state->buffer = malloc(sizeof(UINT8) * 2 * im->xsize * im->bands); tablen = im->bands * im->ysize; starttab = calloc(tablen, sizeof(uint32_t)); lengthtab = calloc(tablen, sizeof(uint32_t)); + /* populate offsets table */ for (i = 0, j = 0; i < tablen; i++, j+=4) read4B(&starttab[i], &ptr[j]); + /* populate lengths table */ for (i = 0, j = tablen * sizeof(uint32_t); i < tablen; i++, j+=4) read4B(&lengthtab[i], &ptr[j]); state->count += tablen * sizeof(uint32_t) * 2; - + /* read compressed rows */ for (rowno = 0; rowno < im->ysize; rowno++, state->y += state->ystep) { for (channo = 0; channo < im->bands; channo++) @@ -137,18 +141,20 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, rlelength = lengthtab[rowno + channo * im->ysize]; rleoffset -= SGI_HEADER_SIZE; + /* row decompression */ if (context->bpc ==1) { if(expandrow(&state->buffer[channo], &ptr[rleoffset], rlelength, im->bands)) goto sgi_finish_decode; } else { - if(expandrow2((UINT16*)&state->buffer[channo], (UINT16*)&ptr[rleoffset], rlelength, im->bands)) + if(expandrow2((UINT16*)&state->buffer[channo * 2], (UINT16*)&ptr[rleoffset], rlelength, im->bands)) goto sgi_finish_decode; } state->count += rlelength; } + /* store decompressed data in image */ state->shuffle((UINT8*)im->image[state->y], state->buffer, im->xsize); }