mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-28 18:10:33 +03:00
Add uncompressed 16bits read for SGI Images
This commit is contained in:
parent
e162963064
commit
bec76fdb42
|
@ -34,9 +34,20 @@ def _accept(prefix):
|
||||||
return len(prefix) >= 2 and i16(prefix) == 474
|
return len(prefix) >= 2 and i16(prefix) == 474
|
||||||
|
|
||||||
|
|
||||||
|
MODES = {
|
||||||
|
(1, 1, 1): "L",
|
||||||
|
(1, 2, 1): "L",
|
||||||
|
(2, 1, 1): "L;16B",
|
||||||
|
(2, 2, 1): "L;16B",
|
||||||
|
(1, 3, 3): "RGB",
|
||||||
|
(2, 3, 3): "RGB;16B",
|
||||||
|
(1, 3, 4): "RGBA",
|
||||||
|
(2, 3, 4): "RGBA;16B"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Image plugin for SGI images.
|
# Image plugin for SGI images.
|
||||||
|
|
||||||
class SgiImageFile(ImageFile.ImageFile):
|
class SgiImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
format = "SGI"
|
format = "SGI"
|
||||||
|
@ -74,16 +85,17 @@ class SgiImageFile(ImageFile.ImageFile):
|
||||||
layout = bpc, dimension, zsize
|
layout = bpc, dimension, zsize
|
||||||
|
|
||||||
# determine mode from bits/zsize
|
# determine mode from bits/zsize
|
||||||
if layout == (1, 2, 1) or layout == (1, 1, 1):
|
rawmode = ""
|
||||||
self.mode = "L"
|
try:
|
||||||
elif layout == (1, 3, 3):
|
rawmode = MODES[layout]
|
||||||
self.mode = "RGB"
|
except KeyError:
|
||||||
elif layout == (1, 3, 4):
|
pass
|
||||||
self.mode = "RGBA"
|
|
||||||
else:
|
if rawmode == "":
|
||||||
raise ValueError("Unsupported SGI image mode")
|
raise ValueError("Unsupported SGI image mode")
|
||||||
|
|
||||||
self.size = xsize, ysize
|
self.size = xsize, ysize
|
||||||
|
self.mode = rawmode.split(";")[0]
|
||||||
|
|
||||||
# orientation -1 : scanlines begins at the bottom-left corner
|
# orientation -1 : scanlines begins at the bottom-left corner
|
||||||
orientation = -1
|
orientation = -1
|
||||||
|
@ -91,6 +103,10 @@ class SgiImageFile(ImageFile.ImageFile):
|
||||||
# decoder info
|
# decoder info
|
||||||
if compression == 0:
|
if compression == 0:
|
||||||
pagesize = xsize * ysize * bpc
|
pagesize = xsize * ysize * bpc
|
||||||
|
if bpc == 2:
|
||||||
|
self.tile = [("SGI16", (0, 0) + self.size,
|
||||||
|
headlen, (self.mode, 0, orientation))]
|
||||||
|
else:
|
||||||
self.tile = []
|
self.tile = []
|
||||||
offset = headlen
|
offset = headlen
|
||||||
for layer in self.mode:
|
for layer in self.mode:
|
||||||
|
@ -165,9 +181,30 @@ def _save(im, fp, filename):
|
||||||
fp.close()
|
fp.close()
|
||||||
|
|
||||||
|
|
||||||
|
class SGI16Decoder(ImageFile.PyDecoder):
|
||||||
|
_pulls_fd = False
|
||||||
|
|
||||||
|
def decode(self, buffer):
|
||||||
|
pagesize = self.state.xsize * self.state.ysize
|
||||||
|
zsize = len(self.mode)
|
||||||
|
data = bytearray(pagesize * zsize)
|
||||||
|
i = 0
|
||||||
|
for y in reversed(range(self.state.ysize)):
|
||||||
|
for x in range(self.state.xsize):
|
||||||
|
for z in range(zsize):
|
||||||
|
bi = (x + y * self.state.xsize + z * pagesize) * 2
|
||||||
|
pixel = i16(buffer, o=bi)
|
||||||
|
pixel = int(pixel // 256)
|
||||||
|
data[i] = o8(pixel)
|
||||||
|
i += 1
|
||||||
|
self.set_as_raw(bytes(data))
|
||||||
|
return -1, 0
|
||||||
|
|
||||||
#
|
#
|
||||||
# registry
|
# registry
|
||||||
|
|
||||||
|
|
||||||
|
Image.register_decoder("SGI16", SGI16Decoder)
|
||||||
Image.register_open(SgiImageFile.format, SgiImageFile, _accept)
|
Image.register_open(SgiImageFile.format, SgiImageFile, _accept)
|
||||||
Image.register_save(SgiImageFile.format, _save)
|
Image.register_save(SgiImageFile.format, _save)
|
||||||
Image.register_mime(SgiImageFile.format, "image/sgi")
|
Image.register_mime(SgiImageFile.format, "image/sgi")
|
||||||
|
|
|
@ -12,16 +12,17 @@
|
||||||
* See the README file for information on usage and redistribution.
|
* See the README file for information on usage and redistribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "Imaging.h"
|
#include "Imaging.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
|
|
||||||
static unsigned long getlong(UINT8 *buf)
|
typedef unsigned long ULONG;
|
||||||
|
|
||||||
|
static ULONG getlong(UINT8 *buf)
|
||||||
{
|
{
|
||||||
return (unsigned long)(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, unsigned long *tab)
|
static void readlongtab(UINT8** buf, int n, ULONG *tab)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
|
@ -54,10 +55,17 @@ int
|
||||||
ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||||
UINT8* buf, int bytes)
|
UINT8* buf, int bytes)
|
||||||
{
|
{
|
||||||
UINT8* ptr;
|
UINT8 *ptr, *rledata, *scanline;
|
||||||
|
ULONG *starttab, *lengthtab;
|
||||||
|
ULONG rleoffset, rlelength, prevrlelength;
|
||||||
|
int zsize, tablen, rowno, channo, x;
|
||||||
|
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
|
|
||||||
|
/* get the channels count */
|
||||||
|
zsize = im->bands;
|
||||||
|
prevrlelength = (ULONG)state->xsize;
|
||||||
|
|
||||||
if (state->state == 0) {
|
if (state->state == 0) {
|
||||||
|
|
||||||
/* check image orientation */
|
/* check image orientation */
|
||||||
|
@ -67,35 +75,35 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||||
} else
|
} else
|
||||||
state->ystep = 1;
|
state->ystep = 1;
|
||||||
|
|
||||||
state->state = 1;
|
free(state->buffer);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the channels count */
|
|
||||||
int zsize = state->bits / state->count;
|
|
||||||
|
|
||||||
/* allocate memory for the buffer used for full lines later */
|
/* allocate memory for the buffer used for full lines later */
|
||||||
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 */
|
||||||
|
rledata = (UINT8*)malloc(sizeof(UINT8) * state->xsize);
|
||||||
|
scanline = (UINT8*)malloc(sizeof(UINT8) * state->xsize);
|
||||||
|
|
||||||
|
state->state = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* get RLE offset and length tabs */
|
/* get RLE offset and length tabs */
|
||||||
unsigned long *starttab, *lengthtab;
|
tablen = state->ysize * zsize * sizeof(ULONG);
|
||||||
int tablen = state->ysize * zsize * sizeof(unsigned long);
|
|
||||||
|
|
||||||
starttab = (unsigned long *)malloc(tablen);
|
starttab = (ULONG*)malloc(tablen);
|
||||||
lengthtab = (unsigned long *)malloc(tablen);
|
lengthtab = (ULONG*)malloc(tablen);
|
||||||
|
|
||||||
readlongtab(&ptr, state->ysize * zsize, starttab);
|
readlongtab(&ptr, state->ysize * zsize, starttab);
|
||||||
readlongtab(&ptr, state->ysize * zsize, lengthtab);
|
readlongtab(&ptr, state->ysize * zsize, lengthtab);
|
||||||
|
|
||||||
/* get scanlines informations */
|
/* get scanlines informations */
|
||||||
int rowno;
|
|
||||||
for (rowno = 0; rowno < state->ysize; ++rowno) {
|
for (rowno = 0; rowno < state->ysize; ++rowno) {
|
||||||
|
|
||||||
int channo;
|
|
||||||
for (channo = 0; channo < zsize; ++channo) {
|
for (channo = 0; channo < zsize; ++channo) {
|
||||||
|
|
||||||
unsigned long rleoffset = starttab[rowno + channo * state->ysize];
|
rleoffset = starttab[rowno + channo * state->ysize];
|
||||||
|
rlelength = lengthtab[rowno + channo * state->ysize];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we also need to substract the file header and RLE tabs length
|
* we also need to substract the file header and RLE tabs length
|
||||||
|
@ -104,25 +112,21 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||||
rleoffset -= 512;
|
rleoffset -= 512;
|
||||||
rleoffset -= tablen;
|
rleoffset -= tablen;
|
||||||
|
|
||||||
unsigned long rlelength = lengthtab[rowno + channo * state->ysize];
|
if (prevrlelength != rlelength)
|
||||||
|
rledata = (UINT8*)realloc(rledata, sizeof(UINT8) * rlelength);
|
||||||
|
|
||||||
|
prevrlelength = rlelength;
|
||||||
|
|
||||||
UINT8* rledata;
|
|
||||||
rledata = (UINT8*)malloc(sizeof(UINT8) * rlelength);
|
|
||||||
memcpy(rledata, &ptr[rleoffset], rlelength * sizeof(UINT8));
|
memcpy(rledata, &ptr[rleoffset], rlelength * sizeof(UINT8));
|
||||||
UINT8* scanline;
|
|
||||||
scanline = (UINT8*)malloc(sizeof(UINT8) * state->xsize);
|
|
||||||
|
|
||||||
/* decompress raw data */
|
/* decompress raw data */
|
||||||
expandrow(scanline, rledata, 0);
|
expandrow(scanline, rledata, 0);
|
||||||
|
|
||||||
/* populate the state buffer */
|
/* populate the state buffer */
|
||||||
int x;
|
|
||||||
for (x = 0; x < state->xsize; ++x) {
|
for (x = 0; x < state->xsize; ++x) {
|
||||||
state->buffer[x * zsize + channo] = scanline[x];
|
state->buffer[x * zsize + channo] = scanline[x];
|
||||||
}
|
}
|
||||||
|
|
||||||
free(rledata);
|
|
||||||
free(scanline);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unpack the full line stored in the state buffer */
|
/* Unpack the full line stored in the state buffer */
|
||||||
|
@ -133,8 +137,10 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||||
state->y += state->ystep;
|
state->y += state->ystep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(rledata);
|
||||||
|
free(scanline);
|
||||||
free(starttab);
|
free(starttab);
|
||||||
free(lengthtab);
|
free(lengthtab);
|
||||||
|
|
||||||
return -1;
|
return -1; /* end of file (errcode=0) */
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user