From 29b1c81a9e059152bd9c4fb899e165d7ae598258 Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 2 Oct 2014 10:31:30 +0300 Subject: [PATCH 1/3] Created with ImageMagick: convert tests\images\hopper.jpg -colorspace Gray -colors 16 -depth 4 tests\images\hopper_gray_4bpp.tif --- Tests/images/hopper_gray_4bpp.tif | Bin 0 -> 8414 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/images/hopper_gray_4bpp.tif diff --git a/Tests/images/hopper_gray_4bpp.tif b/Tests/images/hopper_gray_4bpp.tif new file mode 100644 index 0000000000000000000000000000000000000000..7d23958a7e56fbcdb50586748c78b8cac9e9f663 GIT binary patch literal 8414 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 N6076?^t1K({{fcVst5o8 literal 0 HcmV?d00001 From 552a9a28a04eabc241d2a3a4b5c920834a52de62 Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 2 Oct 2014 10:43:22 +0300 Subject: [PATCH 2/3] Support and test for 4-bit greyscale TIFF --- PIL/TiffImagePlugin.py | 5 +++-- Tests/test_file_tiff.py | 11 +++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 50648288e..90babb9b3 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -149,6 +149,7 @@ OPEN_INFO = { (II, 0, 1, 2, (8,), ()): ("L", "L;IR"), (II, 0, 3, 1, (32,), ()): ("F", "F;32F"), (II, 1, 1, 1, (1,), ()): ("1", "1"), + (II, 1, 1, 1, (4,), ()): ("L", "L;4"), (II, 1, 1, 2, (1,), ()): ("1", "1;R"), (II, 1, 1, 1, (8,), ()): ("L", "L"), (II, 1, 1, 1, (8, 8), (2,)): ("LA", "LA"), @@ -660,7 +661,7 @@ class TiffImageFile(ImageFile.ImageFile): raise EOFError("no more images in TIFF file") if Image.DEBUG: print("Seeking to frame %s, on frame %s, __next %s, location: %s"% - (frame, self.__frame, self.__next, self.fp.tell())) + (frame, self.__frame, self.__next, self.fp.tell())) # reset python3 buffered io handle in case fp # was passed to libtiff, invalidating the buffer self.fp.tell() @@ -671,7 +672,7 @@ class TiffImageFile(ImageFile.ImageFile): self.__next = self.tag.next self.__frame += 1 self._setup() - + def _tell(self): return self.__frame diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index cf809d5d0..583e91379 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -298,6 +298,17 @@ class TestFileTiff(PillowTestCase): # Assert self.assertEqual(ret, [0, 1]) + def test_4bit(self): + # Arrange + test_file = "Tests/images/hopper_gray_4bpp.tif" + + # Act + im = Image.open(test_file) + + # Assert + self.assertEqual(im.size, (128, 128)) + self.assertEqual(im.mode, "L") + if __name__ == '__main__': unittest.main() From 8cb5688047cc71d947a7549b0b119bed37246e7c Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 2 Oct 2014 10:45:41 +0300 Subject: [PATCH 3/3] flake8 --- PIL/TiffImagePlugin.py | 8 ++++---- Tests/test_file_tiff.py | 25 +++++++++++-------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 90babb9b3..f7a0116dd 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -450,10 +450,10 @@ class ImageFileDirectory(collections.MutableMapping): if size > 4: here = fp.tell() if Image.DEBUG: - print ("Tag Location: %s" %here) + print("Tag Location: %s" % here) fp.seek(i32(ifd, 8)) if Image.DEBUG: - print ("Data Location: %s" %fp.tell()) + print("Data Location: %s" % fp.tell()) data = ImageFile._safe_read(fp, size) fp.seek(here) else: @@ -660,14 +660,14 @@ class TiffImageFile(ImageFile.ImageFile): if not self.__next: raise EOFError("no more images in TIFF file") if Image.DEBUG: - print("Seeking to frame %s, on frame %s, __next %s, location: %s"% + print("Seeking to frame %s, on frame %s, __next %s, location: %s" % (frame, self.__frame, self.__next, self.fp.tell())) # reset python3 buffered io handle in case fp # was passed to libtiff, invalidating the buffer self.fp.tell() self.fp.seek(self.__next) if Image.DEBUG: - print("Loading tags, location: %s"%self.fp.tell()) + print("Loading tags, location: %s" % self.fp.tell()) self.tag.load(self.fp) self.__next = self.tag.next self.__frame += 1 diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 583e91379..52db1c85f 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -144,28 +144,27 @@ class TestFileTiff(PillowTestCase): def test_multipage(self): # issue #862 im = Image.open('Tests/images/multipage.tiff') - # file is a multipage tiff, 10x10 green, 10x10 red, 20x20 blue + # file is a multipage tiff: 10x10 green, 10x10 red, 20x20 blue im.seek(0) - self.assertEqual(im.size, (10,10)) - self.assertEqual(im.convert('RGB').getpixel((0,0)), (0,128,0)) + self.assertEqual(im.size, (10, 10)) + self.assertEqual(im.convert('RGB').getpixel((0, 0)), (0, 128, 0)) im.seek(1) im.load() - self.assertEqual(im.size, (10,10)) - self.assertEqual(im.convert('RGB').getpixel((0,0)), (255,0,0)) + self.assertEqual(im.size, (10, 10)) + self.assertEqual(im.convert('RGB').getpixel((0, 0)), (255, 0, 0)) im.seek(2) im.load() - self.assertEqual(im.size, (20,20)) - self.assertEqual(im.convert('RGB').getpixel((0,0)), (0,0,255)) + self.assertEqual(im.size, (20, 20)) + self.assertEqual(im.convert('RGB').getpixel((0, 0)), (0, 0, 255)) def test_multipage_last_frame(self): im = Image.open('Tests/images/multipage-lastframe.tif') im.load() - self.assertEqual(im.size, (20,20)) - self.assertEqual(im.convert('RGB').getpixel((0,0)), (0,0,255)) - + self.assertEqual(im.size, (20, 20)) + self.assertEqual(im.convert('RGB').getpixel((0, 0)), (0, 0, 255)) def test___str__(self): # Arrange @@ -199,7 +198,6 @@ class TestFileTiff(PillowTestCase): def test_load_byte(self): # Arrange - from PIL import TiffImagePlugin ifd = TiffImagePlugin.ImageFileDirectory() data = b"abc" @@ -211,7 +209,6 @@ class TestFileTiff(PillowTestCase): def test_load_string(self): # Arrange - from PIL import TiffImagePlugin ifd = TiffImagePlugin.ImageFileDirectory() data = b"abc\0" @@ -223,7 +220,6 @@ class TestFileTiff(PillowTestCase): def test_load_float(self): # Arrange - from PIL import TiffImagePlugin ifd = TiffImagePlugin.ImageFileDirectory() data = b"abcdabcd" @@ -235,7 +231,6 @@ class TestFileTiff(PillowTestCase): def test_load_double(self): # Arrange - from PIL import TiffImagePlugin ifd = TiffImagePlugin.ImageFileDirectory() data = b"abcdefghabcdefgh" @@ -301,6 +296,7 @@ class TestFileTiff(PillowTestCase): def test_4bit(self): # Arrange test_file = "Tests/images/hopper_gray_4bpp.tif" + original = hopper("L") # Act im = Image.open(test_file) @@ -308,6 +304,7 @@ class TestFileTiff(PillowTestCase): # Assert self.assertEqual(im.size, (128, 128)) self.assertEqual(im.mode, "L") + self.assert_image_similar(im, original, 7.3) if __name__ == '__main__':