From 9e4c54e10f40051011cdec4342021e4c2f202809 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 1 Sep 2018 23:31:39 +1000 Subject: [PATCH 1/3] Added orientation, compression and id_section as keyword arguments --- Tests/test_file_tga.py | 84 +++++++++++++++++++++++++++++++-------- src/PIL/TgaImagePlugin.py | 20 ++++++++-- 2 files changed, 84 insertions(+), 20 deletions(-) diff --git a/Tests/test_file_tga.py b/Tests/test_file_tga.py index 226b899dc..1fcd62b88 100644 --- a/Tests/test_file_tga.py +++ b/Tests/test_file_tga.py @@ -53,10 +53,10 @@ class TestFileTga(PillowTestCase): # Generate a new test name every time so the # test will not fail with permission error # on Windows. - test_file = self.tempfile("temp.tga") + out = self.tempfile("temp.tga") - original_im.save(test_file, rle=rle) - saved_im = Image.open(test_file) + original_im.save(out, rle=rle) + saved_im = Image.open(out) if rle: self.assertEqual( saved_im.info["compression"], @@ -95,34 +95,86 @@ class TestFileTga(PillowTestCase): test_file = "Tests/images/tga_id_field.tga" im = Image.open(test_file) - test_file = self.tempfile("temp.tga") + out = self.tempfile("temp.tga") # Save - im.save(test_file) - test_im = Image.open(test_file) + im.save(out) + test_im = Image.open(out) self.assertEqual(test_im.size, (100, 100)) + self.assertEqual(test_im.info["id_section"], im.info["id_section"]) # RGBA save - im.convert("RGBA").save(test_file) - test_im = Image.open(test_file) + im.convert("RGBA").save(out) + test_im = Image.open(out) self.assertEqual(test_im.size, (100, 100)) + def test_save_id_section(self): + test_file = "Tests/images/rgb32rle.tga" + im = Image.open(test_file) + + out = self.tempfile("temp.tga") + + # Check there is no id section + im.save(out) + test_im = Image.open(out) + self.assertNotIn("id_section", test_im.info) + + # Save with custom id section + im.save(out, id_section=b"Test content") + test_im = Image.open(out) + self.assertEqual(test_im.info["id_section"], b"Test content") + + test_file = "Tests/images/tga_id_field.tga" + im = Image.open(test_file) + + # Save with no id section + im.save(out, id_section="") + test_im = Image.open(out) + self.assertNotIn("id_section", test_im.info) + + def test_save_orientation(self): + test_file = "Tests/images/rgb32rle.tga" + im = Image.open(test_file) + self.assertEqual(im.info["orientation"], -1) + + out = self.tempfile("temp.tga") + + im.save(out, orientation=1) + test_im = Image.open(out) + self.assertEqual(test_im.info["orientation"], 1) + def test_save_rle(self): test_file = "Tests/images/rgb32rle.tga" im = Image.open(test_file) + self.assertEqual(im.info["compression"], "tga_rle") - test_file = self.tempfile("temp.tga") + out = self.tempfile("temp.tga") # Save - im.save(test_file) - test_im = Image.open(test_file) + im.save(out) + test_im = Image.open(out) self.assertEqual(test_im.size, (199, 199)) + self.assertEqual(test_im.info["compression"], "tga_rle") + + # Save without compression + im.save(out, compression=None) + test_im = Image.open(out) + self.assertNotIn("compression", test_im.info) # RGBA save - im.convert("RGBA").save(test_file) - test_im = Image.open(test_file) + im.convert("RGBA").save(out) + test_im = Image.open(out) self.assertEqual(test_im.size, (199, 199)) + test_file = "Tests/images/tga_id_field.tga" + im = Image.open(test_file) + self.assertNotIn("compression", im.info) + + # Save with compression + im.save(out, compression="tga_rle") + test_im = Image.open(out) + self.assertEqual(test_im.info["compression"], "tga_rle") + def test_save_l_transparency(self): # There are 559 transparent pixels in la.tga. num_transparent = 559 @@ -133,10 +185,10 @@ class TestFileTga(PillowTestCase): self.assertEqual( im.getchannel("A").getcolors()[0][0], num_transparent) - test_file = self.tempfile("temp.tga") - im.save(test_file) + out = self.tempfile("temp.tga") + im.save(out) - test_im = Image.open(test_file) + test_im = Image.open(out) self.assertEqual(test_im.mode, "LA") self.assertEqual( test_im.getchannel("A").getcolors()[0][0], num_transparent) diff --git a/src/PIL/TgaImagePlugin.py b/src/PIL/TgaImagePlugin.py index 57b6ae2c8..c60cb3ef1 100644 --- a/src/PIL/TgaImagePlugin.py +++ b/src/PIL/TgaImagePlugin.py @@ -151,11 +151,19 @@ def _save(im, fp, filename): except KeyError: raise IOError("cannot write mode %s as TGA" % im.mode) - rle = im.encoderinfo.get("rle", False) - + if "rle" in im.encoderinfo: + rle = im.encoderinfo["rle"] + else: + compression = im.encoderinfo.get("compression", + im.info.get("compression")) + rle = compression == "tga_rle" if rle: imagetype += 8 + id_section = im.encoderinfo.get("id_section", + im.info.get("id_section", "")) + idlen = len(id_section) + if colormaptype: colormapfirst, colormaplength, colormapentry = 0, 256, 24 else: @@ -166,11 +174,12 @@ def _save(im, fp, filename): else: flags = 0 - orientation = im.info.get("orientation", -1) + orientation = im.encoderinfo.get("orientation", + im.info.get("orientation", -1)) if orientation > 0: flags = flags | 0x20 - fp.write(b"\000" + + fp.write(o8(idlen) + o8(colormaptype) + o8(imagetype) + o16(colormapfirst) + @@ -183,6 +192,9 @@ def _save(im, fp, filename): o8(bits) + o8(flags)) + if id_section: + fp.write(id_section) + if colormaptype: fp.write(im.im.getpalette("RGB", "BGR")) From 325ca3cede708a82ae76f294c9f8d1222d26a758 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 8 Sep 2018 08:26:32 +1000 Subject: [PATCH 2/3] Trim id_section if it is greater than 255 characters --- Tests/test_file_tga.py | 7 +++++++ src/PIL/TgaImagePlugin.py | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/Tests/test_file_tga.py b/Tests/test_file_tga.py index 1fcd62b88..77695f2d1 100644 --- a/Tests/test_file_tga.py +++ b/Tests/test_file_tga.py @@ -124,6 +124,13 @@ class TestFileTga(PillowTestCase): test_im = Image.open(out) self.assertEqual(test_im.info["id_section"], b"Test content") + # Save with custom id section greater than 255 characters + id_section = b"Test content" * 25 + self.assert_warning(UserWarning, + lambda: im.save(out, id_section=id_section)) + test_im = Image.open(out) + self.assertEqual(test_im.info["id_section"], id_section[:255]) + test_file = "Tests/images/tga_id_field.tga" im = Image.open(test_file) diff --git a/src/PIL/TgaImagePlugin.py b/src/PIL/TgaImagePlugin.py index c60cb3ef1..c622f1f5e 100644 --- a/src/PIL/TgaImagePlugin.py +++ b/src/PIL/TgaImagePlugin.py @@ -20,6 +20,8 @@ from . import Image, ImageFile, ImagePalette from ._binary import i8, i16le as i16, o8, o16le as o16 +import warnings + __version__ = "0.3" @@ -163,6 +165,10 @@ def _save(im, fp, filename): id_section = im.encoderinfo.get("id_section", im.info.get("id_section", "")) idlen = len(id_section) + if idlen > 255: + idlen = 255 + id_section = id_section[:255] + warnings.warn("id_section has been trimmed to 255 characters") if colormaptype: colormapfirst, colormaplength, colormapentry = 0, 256, 24 From a9d504e91d82a211a5ce968282e2cb8bdac65480 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 8 Sep 2018 19:02:03 +1000 Subject: [PATCH 3/3] Renamed idlen variable to id_len --- src/PIL/TgaImagePlugin.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/PIL/TgaImagePlugin.py b/src/PIL/TgaImagePlugin.py index c622f1f5e..02893e837 100644 --- a/src/PIL/TgaImagePlugin.py +++ b/src/PIL/TgaImagePlugin.py @@ -55,7 +55,7 @@ class TgaImageFile(ImageFile.ImageFile): # process header s = self.fp.read(18) - idlen = i8(s[0]) + id_len = i8(s[0]) colormaptype = i8(s[1]) imagetype = i8(s[2]) @@ -102,8 +102,8 @@ class TgaImageFile(ImageFile.ImageFile): if imagetype & 8: self.info["compression"] = "tga_rle" - if idlen: - self.info["id_section"] = self.fp.read(idlen) + if id_len: + self.info["id_section"] = self.fp.read(id_len) if colormaptype: # read palette @@ -164,9 +164,9 @@ def _save(im, fp, filename): id_section = im.encoderinfo.get("id_section", im.info.get("id_section", "")) - idlen = len(id_section) - if idlen > 255: - idlen = 255 + id_len = len(id_section) + if id_len > 255: + id_len = 255 id_section = id_section[:255] warnings.warn("id_section has been trimmed to 255 characters") @@ -185,7 +185,7 @@ def _save(im, fp, filename): if orientation > 0: flags = flags | 0x20 - fp.write(o8(idlen) + + fp.write(o8(id_len) + o8(colormaptype) + o8(imagetype) + o16(colormapfirst) +