Fix SunImagePlugin.

SunImagePlugin now loads all the images here:
https://samples.libav.org/image-samples/sunrast/
without LOAD_TRUNCATED_IMAGES set, verified visually.

Prior to this commit:
Could not open 32bpp.ras
Could not open 4bpp.ras
Could not open gray.ras
Could not open lena-1bit-rle.sun
Could not open lena-24bit-rle.sun
Could not open lena-8bit-raw.sun
Could not open lena-8bit-rle.sun
Could not open MARBLES.SUN
This commit is contained in:
wiredfool 2016-11-22 02:50:39 -08:00
parent 372b1abe69
commit 816c74ac81

View File

@ -38,6 +38,21 @@ class SunImageFile(ImageFile.ImageFile):
def _open(self): def _open(self):
# The Sun Raster file header is 32 bytes in length and has the following format:
# typedef struct _SunRaster
# {
# DWORD MagicNumber; /* Magic (identification) number */
# DWORD Width; /* Width of image in pixels */
# DWORD Height; /* Height of image in pixels */
# DWORD Depth; /* Number of bits per pixel */
# DWORD Length; /* Size of image data in bytes */
# DWORD Type; /* Type of raster file */
# DWORD ColorMapType; /* Type of color map */
# DWORD ColorMapLength; /* Size of the color map in bytes */
# } SUNRASTER;
# HEAD # HEAD
s = self.fp.read(32) s = self.fp.read(32)
if i32(s) != 0x59a66a95: if i32(s) != 0x59a66a95:
@ -48,10 +63,15 @@ class SunImageFile(ImageFile.ImageFile):
self.size = i32(s[4:8]), i32(s[8:12]) self.size = i32(s[4:8]), i32(s[8:12])
depth = i32(s[12:16]) depth = i32(s[12:16])
data_length = i32(s[16:20]) # unreliable, ignore.
file_type = i32(s[20:24]) file_type = i32(s[20:24])
palette_type = i32(s[24:28]) # 0: None, 1: RGB, 2: Raw/arbitrary
palette_length = i32(s[28:32])
if depth == 1: if depth == 1:
self.mode, rawmode = "1", "1;I" self.mode, rawmode = "1", "1;I"
elif depth == 4:
self.mode, rawmode = "L", "L;4"
elif depth == 8: elif depth == 8:
self.mode = rawmode = "L" self.mode = rawmode = "L"
elif depth == 24: elif depth == 24:
@ -59,17 +79,31 @@ class SunImageFile(ImageFile.ImageFile):
self.mode, rawmode = "RGB", "RGB" self.mode, rawmode = "RGB", "RGB"
else: else:
self.mode, rawmode = "RGB", "BGR" self.mode, rawmode = "RGB", "BGR"
elif depth == 32:
if file_type == 3:
self.mode, rawmode = 'RGB', 'RGBX'
else:
self.mode, rawmode = 'RGB', 'BGRX'
else: else:
raise SyntaxError("unsupported mode") raise SyntaxError("Unsupported Mode/Bit Depth")
if i32(s[24:28]) != 0:
length = i32(s[28:32])
offset = offset + length if palette_length:
self.palette = ImagePalette.raw("RGB;L", self.fp.read(length)) if palette_length > 1024:
raise SyntaxError("Unsupported Color Palette Length")
if palette_type != 1:
raise SyntaxError("Unsupported Palette Type")
offset = offset + palette_length
self.palette = ImagePalette.raw("RGB;L", self.fp.read(palette_length))
if self.mode == "L": if self.mode == "L":
self.mode = rawmode = "P" self.mode = "P"
rawmode = rawmode.replace('L', 'P')
stride = (((self.size[0] * depth + 7) // 8) + 3) & (~3) # 16 bit boundaries on stride
stride = ((self.size[0] * depth + 15) // 16) * 2
# file type: Type is the version (or flavor) of the bitmap # file type: Type is the version (or flavor) of the bitmap
# file. The following values are typically found in the Type # file. The following values are typically found in the Type