diff --git a/Tests/images/hopper.gd b/Tests/images/hopper.gd new file mode 100644 index 000000000..82d2408f9 Binary files /dev/null and b/Tests/images/hopper.gd differ diff --git a/Tests/test_file_gd.py b/Tests/test_file_gd.py new file mode 100644 index 000000000..326b0c4b2 --- /dev/null +++ b/Tests/test_file_gd.py @@ -0,0 +1,28 @@ +from helper import unittest, PillowTestCase + +from PIL import GdImageFile + +import io + +TEST_GD_FILE = "Tests/images/hopper.gd" + + +class TestFileGd(PillowTestCase): + + def test_sanity(self): + im = GdImageFile.open(TEST_GD_FILE) + self.assertEqual(im.size, (128, 128)) + self.assertEqual(im.format, "GD") + + def test_bad_mode(self): + self.assertRaises(ValueError, + GdImageFile.open, TEST_GD_FILE, 'bad mode') + + def test_invalid_file(self): + invalid_file = "Tests/images/flower.jpg" + + self.assertRaises(IOError, GdImageFile.open, invalid_file) + + +if __name__ == '__main__': + unittest.main() diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index dd1a3d2bc..9faa4155b 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -863,9 +863,8 @@ The :py:meth:`~PIL.Image.Image.open` method sets the following GD ^^ -PIL reads uncompressed GD files. Note that this file format cannot be -automatically identified, so you must use :py:func:`PIL.GdImageFile.open` to -read such a file. +PIL reads uncompressed GD2 files. Note that you must use +:py:func:`PIL.GdImageFile.open` to read such a file. The :py:meth:`~PIL.Image.Image.open` method sets the following :py:attr:`~PIL.Image.Image.info` properties: diff --git a/src/PIL/GdImageFile.py b/src/PIL/GdImageFile.py index 09ab5ec69..2ca1e8218 100644 --- a/src/PIL/GdImageFile.py +++ b/src/PIL/GdImageFile.py @@ -24,17 +24,10 @@ from . import ImageFile, ImagePalette -from ._binary import i16be as i16 -from ._util import isPath +from ._binary import i8, i16be as i16, i32be as i32 __version__ = "0.1" -try: - import builtins -except ImportError: - import __builtin__ - builtins = __builtin__ - ## # Image plugin for the GD uncompressed format. Note that this format @@ -50,19 +43,25 @@ class GdImageFile(ImageFile.ImageFile): def _open(self): # Header - s = self.fp.read(775) + s = self.fp.read(1037) + + if not i16(s[:2]) in [65534, 65535]: + raise SyntaxError("Not a valid GD 2.x .gd file") self.mode = "L" # FIXME: "P" - self.size = i16(s[0:2]), i16(s[2:4]) + self.size = i16(s[2:4]), i16(s[4:6]) + + trueColor = i8(s[6]) + trueColorOffset = 2 if trueColor else 0 # transparency index - tindex = i16(s[5:7]) + tindex = i32(s[7+trueColorOffset:7+trueColorOffset+4]) if tindex < 256: - self.info["transparent"] = tindex + self.info["transparency"] = tindex - self.palette = ImagePalette.raw("RGB", s[7:]) + self.palette = ImagePalette.raw("XBGR", s[7+trueColorOffset+4:7+trueColorOffset+4+256*4]) - self.tile = [("raw", (0, 0)+self.size, 775, ("L", 0, -1))] + self.tile = [("raw", (0, 0)+self.size, 7+trueColorOffset+4+256*4, ("L", 0, 1))] def open(fp, mode="r"): @@ -78,13 +77,7 @@ def open(fp, mode="r"): if mode != "r": raise ValueError("bad mode") - if isPath(fp): - filename = fp - fp = builtins.open(fp, "rb") - else: - filename = "" - try: - return GdImageFile(fp, filename) + return GdImageFile(fp) except SyntaxError: raise IOError("cannot identify this image file")