Pillow/Tests/test_imagefile.py

324 lines
9.6 KiB
Python
Raw Normal View History

2014-06-10 13:10:47 +04:00
from io import BytesIO
from PIL import EpsImagePlugin, Image, ImageFile
from .helper import PillowTestCase, fromstring, hopper, tostring, unittest
2019-03-12 02:27:43 +03:00
try:
from PIL import _webp
2019-06-13 18:54:46 +03:00
2019-03-12 02:27:43 +03:00
HAVE_WEBP = True
except ImportError:
HAVE_WEBP = False
2014-06-10 13:10:47 +04:00
codecs = dir(Image.core)
# save original block sizes
MAXBLOCK = ImageFile.MAXBLOCK
SAFEBLOCK = ImageFile.SAFEBLOCK
class TestImageFile(PillowTestCase):
2014-06-10 13:10:47 +04:00
def test_parser(self):
def roundtrip(format):
im = hopper("L").resize((1000, 1000))
2014-06-10 13:10:47 +04:00
if format in ("MSP", "XBM"):
im = im.convert("1")
2015-04-24 11:24:52 +03:00
test_file = BytesIO()
2014-06-10 13:10:47 +04:00
im.copy().save(test_file, format)
2014-06-10 13:10:47 +04:00
2015-04-24 11:24:52 +03:00
data = test_file.getvalue()
2014-06-10 13:10:47 +04:00
parser = ImageFile.Parser()
parser.feed(data)
imOut = parser.close()
2014-06-10 13:10:47 +04:00
return im, imOut
2014-06-10 13:10:47 +04:00
self.assert_image_equal(*roundtrip("BMP"))
im1, im2 = roundtrip("GIF")
2019-06-13 18:54:46 +03:00
self.assert_image_similar(im1.convert("P"), im2, 1)
2014-06-10 13:10:47 +04:00
self.assert_image_equal(*roundtrip("IM"))
self.assert_image_equal(*roundtrip("MSP"))
if "zip_encoder" in codecs:
try:
# force multiple blocks in PNG driver
ImageFile.MAXBLOCK = 8192
self.assert_image_equal(*roundtrip("PNG"))
finally:
ImageFile.MAXBLOCK = MAXBLOCK
self.assert_image_equal(*roundtrip("PPM"))
self.assert_image_equal(*roundtrip("TIFF"))
self.assert_image_equal(*roundtrip("XBM"))
self.assert_image_equal(*roundtrip("TGA"))
self.assert_image_equal(*roundtrip("PCX"))
2014-06-10 13:10:47 +04:00
if EpsImagePlugin.has_ghostscript():
im1, im2 = roundtrip("EPS")
2014-09-30 09:14:26 +04:00
# This test fails on Ubuntu 12.04, PPC (Bigendian) It
# appears to be a ghostscript 9.05 bug, since the
# ghostscript rendering is wonky and the file is identical
2015-04-24 02:26:52 +03:00
# to that written on ubuntu 12.04 x64
2014-09-30 09:14:26 +04:00
# md5sum: ba974835ff2d6f3f2fd0053a23521d4a
2014-06-10 13:10:47 +04:00
# EPS comes back in RGB:
2019-06-13 18:54:46 +03:00
self.assert_image_similar(im1, im2.convert("L"), 20)
2014-06-10 13:10:47 +04:00
if "jpeg_encoder" in codecs:
im1, im2 = roundtrip("JPEG") # lossy compression
self.assert_image(im1, im2.mode, im2.size)
2017-09-01 14:05:40 +03:00
self.assertRaises(IOError, roundtrip, "PDF")
2014-06-10 13:10:47 +04:00
def test_ico(self):
2019-06-13 18:54:46 +03:00
with open("Tests/images/python.ico", "rb") as f:
2014-06-10 13:10:47 +04:00
data = f.read()
2017-10-07 15:18:23 +03:00
with ImageFile.Parser() as p:
p.feed(data)
self.assertEqual((48, 48), p.image.size)
2014-06-10 13:10:47 +04:00
def test_safeblock(self):
if "zip_encoder" not in codecs:
self.skipTest("PNG (zlib) encoder not available")
im1 = hopper()
try:
2014-06-10 13:10:47 +04:00
ImageFile.SAFEBLOCK = 1
im2 = fromstring(tostring(im1, "PNG"))
finally:
2014-06-10 13:10:47 +04:00
ImageFile.SAFEBLOCK = SAFEBLOCK
self.assert_image_equal(im1, im2)
2015-07-03 08:03:25 +03:00
def test_raise_ioerror(self):
2017-09-01 14:05:40 +03:00
self.assertRaises(IOError, ImageFile.raise_ioerror, 1)
2015-07-03 08:03:25 +03:00
2017-05-13 19:07:05 +03:00
def test_raise_typeerror(self):
with self.assertRaises(TypeError):
parser = ImageFile.Parser()
parser.feed(1)
def test_truncated_with_errors(self):
if "zip_encoder" not in codecs:
self.skipTest("PNG (zlib) encoder not available")
im = Image.open("Tests/images/truncated_image.png")
with self.assertRaises(IOError):
im.load()
def test_truncated_without_errors(self):
if "zip_encoder" not in codecs:
self.skipTest("PNG (zlib) encoder not available")
im = Image.open("Tests/images/truncated_image.png")
ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
im.load()
finally:
ImageFile.LOAD_TRUNCATED_IMAGES = False
2014-06-10 13:10:47 +04:00
2015-09-15 20:12:16 +03:00
def test_broken_datastream_with_errors(self):
if "zip_encoder" not in codecs:
self.skipTest("PNG (zlib) encoder not available")
im = Image.open("Tests/images/broken_data_stream.png")
with self.assertRaises(IOError):
im.load()
def test_broken_datastream_without_errors(self):
if "zip_encoder" not in codecs:
self.skipTest("PNG (zlib) encoder not available")
im = Image.open("Tests/images/broken_data_stream.png")
ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
im.load()
finally:
ImageFile.LOAD_TRUNCATED_IMAGES = False
2017-03-11 18:35:03 +03:00
class MockPyDecoder(ImageFile.PyDecoder):
def decode(self, buffer):
2017-04-20 14:14:23 +03:00
# eof
2018-10-02 11:55:28 +03:00
return -1, 0
2017-03-11 18:35:03 +03:00
2018-03-03 12:54:00 +03:00
2017-03-11 18:35:03 +03:00
xoff, yoff, xsize, ysize = 10, 20, 100, 100
2017-04-20 14:14:23 +03:00
2017-03-11 18:35:03 +03:00
class MockImageFile(ImageFile.ImageFile):
def _open(self):
2019-06-13 18:54:46 +03:00
self.rawmode = "RGBA"
self.mode = "RGBA"
self._size = (200, 200)
2019-06-13 18:54:46 +03:00
self.tile = [("MOCK", (xoff, yoff, xoff + xsize, yoff + ysize), 32, None)]
2017-03-11 18:35:03 +03:00
2017-04-20 14:14:23 +03:00
2017-03-11 18:35:03 +03:00
class TestPyDecoder(PillowTestCase):
def get_decoder(self):
decoder = MockPyDecoder(None)
def closure(mode, *args):
decoder.__init__(mode, *args)
return decoder
2019-06-13 18:54:46 +03:00
Image.register_decoder("MOCK", closure)
2017-03-11 18:35:03 +03:00
return decoder
def test_setimage(self):
2019-06-13 18:54:46 +03:00
buf = BytesIO(b"\x00" * 255)
2017-03-11 18:35:03 +03:00
im = MockImageFile(buf)
d = self.get_decoder()
im.load()
self.assertEqual(d.state.xoff, xoff)
self.assertEqual(d.state.yoff, yoff)
self.assertEqual(d.state.xsize, xsize)
self.assertEqual(d.state.ysize, ysize)
2019-06-13 18:54:46 +03:00
self.assertRaises(ValueError, d.set_as_raw, b"\x00")
2017-03-11 18:35:03 +03:00
2017-03-11 19:43:44 +03:00
def test_extents_none(self):
2019-06-13 18:54:46 +03:00
buf = BytesIO(b"\x00" * 255)
2017-03-11 19:43:44 +03:00
im = MockImageFile(buf)
im.tile = [("MOCK", None, 32, None)]
d = self.get_decoder()
im.load()
self.assertEqual(d.state.xoff, 0)
self.assertEqual(d.state.yoff, 0)
self.assertEqual(d.state.xsize, 200)
self.assertEqual(d.state.ysize, 200)
2017-03-11 18:35:03 +03:00
def test_negsize(self):
2019-06-13 18:54:46 +03:00
buf = BytesIO(b"\x00" * 255)
2017-03-11 18:35:03 +03:00
im = MockImageFile(buf)
2019-06-13 18:54:46 +03:00
im.tile = [("MOCK", (xoff, yoff, -10, yoff + ysize), 32, None)]
2018-10-02 11:44:43 +03:00
self.get_decoder()
2017-03-11 18:35:03 +03:00
self.assertRaises(ValueError, im.load)
2019-06-13 18:54:46 +03:00
im.tile = [("MOCK", (xoff, yoff, xoff + xsize, -10), 32, None)]
2017-03-11 18:35:03 +03:00
self.assertRaises(ValueError, im.load)
def test_oversize(self):
2019-06-13 18:54:46 +03:00
buf = BytesIO(b"\x00" * 255)
2017-03-11 18:35:03 +03:00
im = MockImageFile(buf)
2019-06-13 18:54:46 +03:00
im.tile = [("MOCK", (xoff, yoff, xoff + xsize + 100, yoff + ysize), 32, None)]
2018-10-02 11:44:43 +03:00
self.get_decoder()
2017-03-11 18:35:03 +03:00
self.assertRaises(ValueError, im.load)
2019-06-13 18:54:46 +03:00
im.tile = [("MOCK", (xoff, yoff, xoff + xsize, yoff + ysize + 100), 32, None)]
2017-03-11 18:35:03 +03:00
self.assertRaises(ValueError, im.load)
def test_no_format(self):
2019-06-13 18:54:46 +03:00
buf = BytesIO(b"\x00" * 255)
im = MockImageFile(buf)
self.assertIsNone(im.format)
self.assertIsNone(im.get_format_mimetype())
2019-03-12 02:27:43 +03:00
def test_exif_jpeg(self):
im = Image.open("Tests/images/exif-72dpi-int.jpg") # Little endian
exif = im.getexif()
self.assertNotIn(258, exif)
self.assertIn(40960, exif)
self.assertEqual(exif[40963], 450)
self.assertEqual(exif[11], "gThumb 3.0.1")
2019-06-13 18:54:46 +03:00
out = self.tempfile("temp.jpg")
2019-03-12 02:27:43 +03:00
exif[258] = 8
del exif[40960]
exif[40963] = 455
exif[11] = "Pillow test"
im.save(out, exif=exif)
reloaded = Image.open(out)
reloaded_exif = reloaded.getexif()
self.assertEqual(reloaded_exif[258], 8)
self.assertNotIn(40960, exif)
self.assertEqual(reloaded_exif[40963], 455)
self.assertEqual(exif[11], "Pillow test")
im = Image.open("Tests/images/no-dpi-in-exif.jpg") # Big endian
exif = im.getexif()
self.assertNotIn(258, exif)
self.assertIn(40962, exif)
self.assertEqual(exif[40963], 200)
self.assertEqual(exif[305], "Adobe Photoshop CC 2017 (Macintosh)")
2019-06-13 18:54:46 +03:00
out = self.tempfile("temp.jpg")
2019-03-12 02:27:43 +03:00
exif[258] = 8
del exif[34665]
exif[40963] = 455
exif[305] = "Pillow test"
im.save(out, exif=exif)
reloaded = Image.open(out)
reloaded_exif = reloaded.getexif()
self.assertEqual(reloaded_exif[258], 8)
self.assertNotIn(40960, exif)
self.assertEqual(reloaded_exif[40963], 455)
self.assertEqual(exif[305], "Pillow test")
2019-06-13 18:54:46 +03:00
@unittest.skipIf(
not HAVE_WEBP or not _webp.HAVE_WEBPANIM,
"WebP support not installed with animation",
)
2019-03-12 02:27:43 +03:00
def test_exif_webp(self):
im = Image.open("Tests/images/hopper.webp")
2019-03-12 02:27:43 +03:00
exif = im.getexif()
self.assertEqual(exif, {})
2019-06-13 18:54:46 +03:00
out = self.tempfile("temp.webp")
2019-03-12 02:27:43 +03:00
exif[258] = 8
exif[40963] = 455
exif[305] = "Pillow test"
def check_exif():
reloaded = Image.open(out)
reloaded_exif = reloaded.getexif()
self.assertEqual(reloaded_exif[258], 8)
self.assertEqual(reloaded_exif[40963], 455)
self.assertEqual(exif[305], "Pillow test")
2019-06-13 18:54:46 +03:00
2019-03-12 02:27:43 +03:00
im.save(out, exif=exif)
check_exif()
im.save(out, exif=exif, save_all=True)
check_exif()
def test_exif_png(self):
im = Image.open("Tests/images/exif.png")
exif = im.getexif()
self.assertEqual(exif, {274: 1})
2019-06-13 18:54:46 +03:00
out = self.tempfile("temp.png")
2019-03-12 02:27:43 +03:00
exif[258] = 8
del exif[274]
exif[40963] = 455
exif[305] = "Pillow test"
im.save(out, exif=exif)
reloaded = Image.open(out)
reloaded_exif = reloaded.getexif()
2019-06-13 18:54:46 +03:00
self.assertEqual(reloaded_exif, {258: 8, 40963: 455, 305: "Pillow test"})
def test_exif_interop(self):
im = Image.open("Tests/images/flower.jpg")
exif = im.getexif()
2019-06-13 18:54:46 +03:00
self.assertEqual(
exif.get_ifd(0xA005), {1: "R98", 2: b"0100", 4097: 2272, 4098: 1704}
)