From 9caf8c5889215c0f96f7c0d5ec4ca20f43a8fb68 Mon Sep 17 00:00:00 2001 From: Mickael Bonfill Date: Wed, 26 Jul 2017 17:01:45 -0400 Subject: [PATCH] use UINT32 instead of ULONG --- PIL/SgiImagePlugin.py | 29 ++++++++--- libImaging/SgiRleDecode.c | 102 ++++++++++++++++++-------------------- 2 files changed, 70 insertions(+), 61 deletions(-) diff --git a/PIL/SgiImagePlugin.py b/PIL/SgiImagePlugin.py index 06077922d..27b90b11d 100644 --- a/PIL/SgiImagePlugin.py +++ b/PIL/SgiImagePlugin.py @@ -23,10 +23,11 @@ from . import Image, ImageFile -from ._binary import i8, o8, i16be as i16 +from ._binary import i8, o8, i16be as i16, o16be as o16 import struct import os + __version__ = "0.3" @@ -123,14 +124,22 @@ def _save(im, fp, filename): if im.mode != "RGB" and im.mode != "RGBA" and im.mode != "L": raise ValueError("Unsupported SGI image mode") + # Get the keyword arguments + info = im.encoderinfo + + # Byte-per-pixel precision, 1 = 8bits per pixel + bpc = info.get("bpc", 1) + + if bpc != 1 and bpc != 2: + raise ValueError("Unsupported number of bytes per pixel") + # Flip the image, since the origin of SGI file is the bottom-left corner im = im.transpose(Image.FLIP_TOP_BOTTOM) # Define the file as SGI File Format magicNumber = 474 # Run-Length Encoding Compression - Unsupported at this time rle = 0 - # Byte-per-pixel precision, 1 = 8bits per pixel - bpc = 1 + # Number of dimensions (x,y,z) dim = 3 # X Dimension = width / Y Dimension = height @@ -176,19 +185,27 @@ def _save(im, fp, filename): fp.write(struct.pack('404s', b'')) # dummy for channel in im.split(): - fp.write(channel.tobytes()) + rawchannel = channel.tobytes() + if bpc == 1: + fp.write(rawchannel) + else: + for pixel in rawchannel: + fp.write(o16(i8(pixel) * 256)) fp.close() class SGI16Decoder(ImageFile.PyDecoder): - _pulls_fd = False + _pulls_fd = True def decode(self, buffer): rawmode, stride, orientation = self.args pagesize = self.state.xsize * self.state.ysize zsize = len(self.mode) data = bytearray(pagesize * zsize) + self.fd.seek(512) + s = self.fd.read(2 * pagesize * zsize) + print(len(s)) i = 0 y = 0 if orientation < 0: @@ -198,7 +215,7 @@ class SGI16Decoder(ImageFile.PyDecoder): for z in range(zsize): bi = (x + y * self.state.xsize + y * stride + z * pagesize) * 2 - pixel = i16(buffer, o=bi) + pixel = i16(s, o=bi) pixel = int(pixel // 256) data[i] = o8(pixel) i += 1 diff --git a/libImaging/SgiRleDecode.c b/libImaging/SgiRleDecode.c index d0c01f2c5..02cb5fc16 100644 --- a/libImaging/SgiRleDecode.c +++ b/libImaging/SgiRleDecode.c @@ -5,7 +5,7 @@ * decoder for Sgi RLE data. * * history: - * 2017-07-20 mb created + * 2017-07-20 mb created * * Copyright (c) Mickael Bonfill 2017. * @@ -17,42 +17,40 @@ #define SGI_HEAD_LEN 512 -typedef unsigned long ULONG; - -static ULONG getlong(UINT8 *buf) +static UINT32 getlong(UINT8 *buf) { - return (ULONG)(buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0); + return (UINT32)(buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0); } static void expandrow(UINT8* optr,UINT8* iptr, int ooffset, int ioffset) { - UINT8 pixel, count; + UINT8 pixel, count; optr += ooffset; - iptr += ioffset; - while(1) { - pixel = *iptr++; - if ( !(count = (pixel & 0x7f)) ) - return; - if(pixel & 0x80) { - while(count--) - *optr++ = *iptr++; - } else { - pixel = *iptr++; - while(count--) - *optr++ = pixel; - } - } + iptr += ioffset; + while(1) { + pixel = *iptr++; + if ( !(count = (pixel & 0x7f)) ) + return; + if(pixel & 0x80) { + while(count--) + *optr++ = *iptr++; + } else { + pixel = *iptr++; + while(count--) + *optr++ = pixel; + } + } } int ImagingSgiRleDecode(Imaging im, ImagingCodecState state, - UINT8* buf, int bytes) + UINT8* buf, int bytes) { UINT8 *ptr, *scanline; - ULONG *starttab, *lengthtab; - ULONG rleoffset, rlelength; - int zsize, tablen, rowno, channo, bpc; + UINT32 *starttab, *lengthtab; + UINT32 rleoffset, rlelength; + int zsize, tablen, rowno, channo; /* "working copy" of buffer pointer */ ptr = buf; @@ -60,38 +58,32 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, /* get the channels count */ zsize = im->bands; - /* get bytes channel per pixel */ - bpc = state->count; - /* initialization */ if (state->state == 0) { - /* check image orientation */ - if (state->ystep < 0) { - state->y = state->ysize-1; - state->ystep = -1; - } else { + /* check image orientation */ + if (state->ystep < 0) { + state->y = state->ysize-1; + state->ystep = -1; + } else { state->ystep = 1; state->y = 0; } - free(state->buffer); - - /* allocate memory for the buffer used for full lines later */ - state->buffer = (UINT8*)malloc(sizeof(UINT8) * state->xsize * zsize); - - /* allocate memory for compressed and uncompressed rows */ - scanline = (UINT8*)malloc(sizeof(UINT8) * state->xsize); - - /* allocate memory for rle tabs */ - tablen = state->ysize * zsize * sizeof(ULONG); - - starttab = (ULONG*)malloc(tablen); - lengthtab = (ULONG*)malloc(tablen); - - state->state = 1; + state->state = 1; + } + /* allocate memory for compressed and uncompressed rows */ + scanline = (UINT8*)malloc(sizeof(UINT8) * state->xsize); + + /* allocate memory for rle tabs */ + tablen = state->ysize * zsize * sizeof(UINT32); + + starttab = (UINT32*)malloc(tablen); + lengthtab = (UINT32*)malloc(tablen); + + /* get RLE offset and length tabs */ int i; for (i = 0; i < state->ysize * zsize; i++) { @@ -104,9 +96,9 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, /* get scanlines informations */ for (rowno = 0; rowno < state->ysize; ++rowno) { - for (channo = 0; channo < zsize; ++channo) { + for (channo = 0; channo < zsize; ++channo) { - rleoffset = starttab[rowno + channo * state->ysize]; + rleoffset = starttab[rowno + channo * state->ysize]; rlelength = lengthtab[rowno + channo * state->ysize]; /* @@ -116,21 +108,21 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, rleoffset -= SGI_HEAD_LEN; /* decompress raw data */ - expandrow(scanline, ptr, 0, rleoffset); + expandrow(scanline, ptr, 0, rleoffset); /* populate the state buffer */ - for (state->x = 0; state->x < sizeof(*scanline) * state->xsize; state->x += 1) { - state->buffer[state->x * zsize + channo] = (UINT8)(scanline[state->x]); - } + for (state->x = 0; state->x < sizeof(*scanline) * state->xsize; state->x += 1) { + state->buffer[state->x * zsize + channo] = (UINT8)(scanline[state->x]); + } - } + } /* Unpack the full line stored in the state buffer */ state->shuffle((UINT8*) im->image[state->y + state->yoff] + state->xoff * im->pixelsize, state->buffer, state->xsize); - state->y += state->ystep; + state->y += state->ystep; } free(scanline);