mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-30 20:06:17 +03:00
Avoid memory reallocation and support Y orientation in 16bits uncompressed read
This commit is contained in:
parent
bec76fdb42
commit
f833cd7f38
|
@ -116,7 +116,7 @@ class SgiImageFile(ImageFile.ImageFile):
|
||||||
offset += pagesize
|
offset += pagesize
|
||||||
elif compression == 1:
|
elif compression == 1:
|
||||||
self.tile = [("sgi_rle", (0, 0) + self.size,
|
self.tile = [("sgi_rle", (0, 0) + self.size,
|
||||||
headlen, (self.mode, orientation, bpc * 8))]
|
headlen, (rawmode, orientation, bpc))]
|
||||||
|
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
|
@ -185,18 +185,24 @@ class SGI16Decoder(ImageFile.PyDecoder):
|
||||||
_pulls_fd = False
|
_pulls_fd = False
|
||||||
|
|
||||||
def decode(self, buffer):
|
def decode(self, buffer):
|
||||||
|
rawmode, stride, orientation = self.args
|
||||||
pagesize = self.state.xsize * self.state.ysize
|
pagesize = self.state.xsize * self.state.ysize
|
||||||
zsize = len(self.mode)
|
zsize = len(self.mode)
|
||||||
data = bytearray(pagesize * zsize)
|
data = bytearray(pagesize * zsize)
|
||||||
i = 0
|
i = 0
|
||||||
for y in reversed(range(self.state.ysize)):
|
y = 0
|
||||||
|
if orientation < 0:
|
||||||
|
y = self.state.ysize - 1
|
||||||
|
while y >= 0 and y < self.state.ysize:
|
||||||
for x in range(self.state.xsize):
|
for x in range(self.state.xsize):
|
||||||
for z in range(zsize):
|
for z in range(zsize):
|
||||||
bi = (x + y * self.state.xsize + z * pagesize) * 2
|
bi = (x + y * self.state.xsize +
|
||||||
|
y * stride + z * pagesize) * 2
|
||||||
pixel = i16(buffer, o=bi)
|
pixel = i16(buffer, o=bi)
|
||||||
pixel = int(pixel // 256)
|
pixel = int(pixel // 256)
|
||||||
data[i] = o8(pixel)
|
data[i] = o8(pixel)
|
||||||
i += 1
|
i += 1
|
||||||
|
y += orientation
|
||||||
self.set_as_raw(bytes(data))
|
self.set_as_raw(bytes(data))
|
||||||
return -1, 0
|
return -1, 0
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include "Imaging.h"
|
#include "Imaging.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
|
|
||||||
|
#define SGI_HEAD_LEN 512
|
||||||
|
|
||||||
typedef unsigned long ULONG;
|
typedef unsigned long ULONG;
|
||||||
|
|
||||||
static ULONG getlong(UINT8 *buf)
|
static ULONG getlong(UINT8 *buf)
|
||||||
|
@ -22,20 +24,12 @@ static ULONG getlong(UINT8 *buf)
|
||||||
return (ULONG)(buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
|
return (ULONG)(buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void readlongtab(UINT8** buf, int n, ULONG *tab)
|
static void expandrow(UINT8* optr,UINT8* iptr, int ooffset, int ioffset)
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
tab[i] = getlong(*buf);
|
|
||||||
*buf += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void expandrow(UINT8* optr,UINT8* iptr, int z)
|
|
||||||
{
|
{
|
||||||
UINT8 pixel, count;
|
UINT8 pixel, count;
|
||||||
|
|
||||||
optr += z;
|
optr += ooffset;
|
||||||
|
iptr += ioffset;
|
||||||
while(1) {
|
while(1) {
|
||||||
pixel = *iptr++;
|
pixel = *iptr++;
|
||||||
if ( !(count = (pixel & 0x7f)) )
|
if ( !(count = (pixel & 0x7f)) )
|
||||||
|
@ -55,25 +49,31 @@ int
|
||||||
ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||||
UINT8* buf, int bytes)
|
UINT8* buf, int bytes)
|
||||||
{
|
{
|
||||||
UINT8 *ptr, *rledata, *scanline;
|
UINT8 *ptr, *scanline;
|
||||||
ULONG *starttab, *lengthtab;
|
ULONG *starttab, *lengthtab;
|
||||||
ULONG rleoffset, rlelength, prevrlelength;
|
ULONG rleoffset, rlelength;
|
||||||
int zsize, tablen, rowno, channo, x;
|
int zsize, tablen, rowno, channo, bpc;
|
||||||
|
|
||||||
|
/* "working copy" of buffer pointer */
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
|
|
||||||
/* get the channels count */
|
/* get the channels count */
|
||||||
zsize = im->bands;
|
zsize = im->bands;
|
||||||
prevrlelength = (ULONG)state->xsize;
|
|
||||||
|
|
||||||
|
/* get bytes channel per pixel */
|
||||||
|
bpc = state->count;
|
||||||
|
|
||||||
|
/* initialization */
|
||||||
if (state->state == 0) {
|
if (state->state == 0) {
|
||||||
|
|
||||||
/* check image orientation */
|
/* check image orientation */
|
||||||
if (state->ystep < 0) {
|
if (state->ystep < 0) {
|
||||||
state->y = state->ysize-1;
|
state->y = state->ysize-1;
|
||||||
state->ystep = -1;
|
state->ystep = -1;
|
||||||
} else
|
} else {
|
||||||
state->ystep = 1;
|
state->ystep = 1;
|
||||||
|
state->y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
free(state->buffer);
|
free(state->buffer);
|
||||||
|
|
||||||
|
@ -81,21 +81,25 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||||
state->buffer = (UINT8*)malloc(sizeof(UINT8) * state->xsize * zsize);
|
state->buffer = (UINT8*)malloc(sizeof(UINT8) * state->xsize * zsize);
|
||||||
|
|
||||||
/* allocate memory for compressed and uncompressed rows */
|
/* allocate memory for compressed and uncompressed rows */
|
||||||
rledata = (UINT8*)malloc(sizeof(UINT8) * state->xsize);
|
|
||||||
scanline = (UINT8*)malloc(sizeof(UINT8) * state->xsize);
|
scanline = (UINT8*)malloc(sizeof(UINT8) * state->xsize);
|
||||||
|
|
||||||
state->state = 1;
|
/* allocate memory for rle tabs */
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get RLE offset and length tabs */
|
|
||||||
tablen = state->ysize * zsize * sizeof(ULONG);
|
tablen = state->ysize * zsize * sizeof(ULONG);
|
||||||
|
|
||||||
starttab = (ULONG*)malloc(tablen);
|
starttab = (ULONG*)malloc(tablen);
|
||||||
lengthtab = (ULONG*)malloc(tablen);
|
lengthtab = (ULONG*)malloc(tablen);
|
||||||
|
|
||||||
readlongtab(&ptr, state->ysize * zsize, starttab);
|
state->state = 1;
|
||||||
readlongtab(&ptr, state->ysize * zsize, lengthtab);
|
}
|
||||||
|
|
||||||
|
/* get RLE offset and length tabs */
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < state->ysize * zsize; i++) {
|
||||||
|
starttab[i] = getlong(&ptr[i * 4]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < state->ysize * zsize; i++) {
|
||||||
|
lengthtab[i] = getlong(&ptr[tablen + i * 4]);
|
||||||
|
}
|
||||||
|
|
||||||
/* get scanlines informations */
|
/* get scanlines informations */
|
||||||
for (rowno = 0; rowno < state->ysize; ++rowno) {
|
for (rowno = 0; rowno < state->ysize; ++rowno) {
|
||||||
|
@ -109,22 +113,14 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||||
* we also need to substract the file header and RLE tabs length
|
* we also need to substract the file header and RLE tabs length
|
||||||
* from the offset
|
* from the offset
|
||||||
*/
|
*/
|
||||||
rleoffset -= 512;
|
rleoffset -= SGI_HEAD_LEN;
|
||||||
rleoffset -= tablen;
|
|
||||||
|
|
||||||
if (prevrlelength != rlelength)
|
|
||||||
rledata = (UINT8*)realloc(rledata, sizeof(UINT8) * rlelength);
|
|
||||||
|
|
||||||
prevrlelength = rlelength;
|
|
||||||
|
|
||||||
memcpy(rledata, &ptr[rleoffset], rlelength * sizeof(UINT8));
|
|
||||||
|
|
||||||
/* decompress raw data */
|
/* decompress raw data */
|
||||||
expandrow(scanline, rledata, 0);
|
expandrow(scanline, ptr, 0, rleoffset);
|
||||||
|
|
||||||
/* populate the state buffer */
|
/* populate the state buffer */
|
||||||
for (x = 0; x < state->xsize; ++x) {
|
for (state->x = 0; state->x < sizeof(*scanline) * state->xsize; state->x += 1) {
|
||||||
state->buffer[x * zsize + channo] = scanline[x];
|
state->buffer[state->x * zsize + channo] = (UINT8)(scanline[state->x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -137,7 +133,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||||
state->y += state->ystep;
|
state->y += state->ystep;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(rledata);
|
|
||||||
free(scanline);
|
free(scanline);
|
||||||
free(starttab);
|
free(starttab);
|
||||||
free(lengthtab);
|
free(lengthtab);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user