2019-01-13 20:00:12 +03:00
|
|
|
from .helper import unittest, PillowTestCase
|
2014-07-16 19:36:56 +04:00
|
|
|
from io import BytesIO
|
|
|
|
from PIL import Image
|
|
|
|
|
|
|
|
|
|
|
|
test_files = ["Tests/images/sugarshack.mpo", "Tests/images/frozenpond.mpo"]
|
|
|
|
|
|
|
|
|
|
|
|
class TestFileMpo(PillowTestCase):
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
codecs = dir(Image.core)
|
|
|
|
if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:
|
|
|
|
self.skipTest("jpeg support not available")
|
|
|
|
|
2014-07-30 18:14:09 +04:00
|
|
|
def frame_roundtrip(self, im, **options):
|
|
|
|
# Note that for now, there is no MPO saving functionality
|
2014-07-16 19:36:56 +04:00
|
|
|
out = BytesIO()
|
|
|
|
im.save(out, "MPO", **options)
|
2015-04-24 11:24:52 +03:00
|
|
|
test_bytes = out.tell()
|
2014-07-16 19:36:56 +04:00
|
|
|
out.seek(0)
|
|
|
|
im = Image.open(out)
|
2015-04-24 11:24:52 +03:00
|
|
|
im.bytes = test_bytes # for testing only
|
2014-07-16 19:36:56 +04:00
|
|
|
return im
|
|
|
|
|
|
|
|
def test_sanity(self):
|
|
|
|
for test_file in test_files:
|
|
|
|
im = Image.open(test_file)
|
|
|
|
im.load()
|
|
|
|
self.assertEqual(im.mode, "RGB")
|
|
|
|
self.assertEqual(im.size, (640, 480))
|
|
|
|
self.assertEqual(im.format, "MPO")
|
|
|
|
|
2018-11-17 13:56:06 +03:00
|
|
|
def test_unclosed_file(self):
|
|
|
|
def open():
|
|
|
|
im = Image.open(test_files[0])
|
|
|
|
im.load()
|
|
|
|
self.assert_warning(None, open)
|
|
|
|
|
2014-07-16 19:36:56 +04:00
|
|
|
def test_app(self):
|
|
|
|
for test_file in test_files:
|
|
|
|
# Test APP/COM reader (@PIL135)
|
|
|
|
im = Image.open(test_file)
|
|
|
|
self.assertEqual(im.applist[0][0], 'APP1')
|
|
|
|
self.assertEqual(im.applist[1][0], 'APP2')
|
|
|
|
self.assertEqual(im.applist[1][1][:16],
|
2014-08-28 15:44:19 +04:00
|
|
|
b'MPF\x00MM\x00*\x00\x00\x00\x08\x00\x03\xb0\x00')
|
2014-07-16 19:36:56 +04:00
|
|
|
self.assertEqual(len(im.applist), 2)
|
|
|
|
|
|
|
|
def test_exif(self):
|
|
|
|
for test_file in test_files:
|
|
|
|
im = Image.open(test_file)
|
|
|
|
info = im._getexif()
|
|
|
|
self.assertEqual(info[272], 'Nintendo 3DS')
|
|
|
|
self.assertEqual(info[296], 2)
|
|
|
|
self.assertEqual(info[34665], 188)
|
|
|
|
|
|
|
|
def test_mp(self):
|
|
|
|
for test_file in test_files:
|
|
|
|
im = Image.open(test_file)
|
2014-07-24 23:00:19 +04:00
|
|
|
mpinfo = im._getmp()
|
2014-07-25 22:47:07 +04:00
|
|
|
self.assertEqual(mpinfo[45056], b'0100')
|
2014-07-24 23:00:19 +04:00
|
|
|
self.assertEqual(mpinfo[45057], 2)
|
2014-08-28 15:44:19 +04:00
|
|
|
|
2014-07-24 23:00:19 +04:00
|
|
|
def test_mp_attribute(self):
|
|
|
|
for test_file in test_files:
|
|
|
|
im = Image.open(test_file)
|
|
|
|
mpinfo = im._getmp()
|
|
|
|
frameNumber = 0
|
|
|
|
for mpentry in mpinfo[45058]:
|
|
|
|
mpattr = mpentry['Attribute']
|
|
|
|
if frameNumber:
|
|
|
|
self.assertFalse(mpattr['RepresentativeImageFlag'])
|
|
|
|
else:
|
|
|
|
self.assertTrue(mpattr['RepresentativeImageFlag'])
|
|
|
|
self.assertFalse(mpattr['DependentParentImageFlag'])
|
|
|
|
self.assertFalse(mpattr['DependentChildImageFlag'])
|
|
|
|
self.assertEqual(mpattr['ImageDataFormat'], 'JPEG')
|
|
|
|
self.assertEqual(mpattr['MPType'],
|
2014-08-28 15:44:19 +04:00
|
|
|
'Multi-Frame Image: (Disparity)')
|
2014-07-24 23:00:19 +04:00
|
|
|
self.assertEqual(mpattr['Reserved'], 0)
|
|
|
|
frameNumber += 1
|
|
|
|
|
2014-07-22 21:31:51 +04:00
|
|
|
def test_seek(self):
|
|
|
|
for test_file in test_files:
|
|
|
|
im = Image.open(test_file)
|
|
|
|
self.assertEqual(im.tell(), 0)
|
|
|
|
# prior to first image raises an error, both blatant and borderline
|
|
|
|
self.assertRaises(EOFError, im.seek, -1)
|
|
|
|
self.assertRaises(EOFError, im.seek, -523)
|
2014-08-28 15:44:19 +04:00
|
|
|
# after the final image raises an error,
|
|
|
|
# both blatant and borderline
|
2014-07-22 21:31:51 +04:00
|
|
|
self.assertRaises(EOFError, im.seek, 2)
|
|
|
|
self.assertRaises(EOFError, im.seek, 523)
|
|
|
|
# bad calls shouldn't change the frame
|
|
|
|
self.assertEqual(im.tell(), 0)
|
|
|
|
# this one will work
|
|
|
|
im.seek(1)
|
|
|
|
self.assertEqual(im.tell(), 1)
|
|
|
|
# and this one, too
|
|
|
|
im.seek(0)
|
|
|
|
self.assertEqual(im.tell(), 0)
|
2014-08-28 15:44:19 +04:00
|
|
|
|
2015-06-07 18:01:34 +03:00
|
|
|
def test_n_frames(self):
|
|
|
|
im = Image.open("Tests/images/sugarshack.mpo")
|
|
|
|
self.assertEqual(im.n_frames, 2)
|
2015-06-30 06:25:00 +03:00
|
|
|
self.assertTrue(im.is_animated)
|
2015-06-07 18:01:34 +03:00
|
|
|
|
2015-06-18 17:49:18 +03:00
|
|
|
def test_eoferror(self):
|
|
|
|
im = Image.open("Tests/images/sugarshack.mpo")
|
|
|
|
n_frames = im.n_frames
|
2017-09-06 06:19:33 +03:00
|
|
|
|
|
|
|
# Test seeking past the last frame
|
|
|
|
self.assertRaises(EOFError, im.seek, n_frames)
|
|
|
|
self.assertLess(im.tell(), n_frames)
|
|
|
|
|
|
|
|
# Test that seeking to the last frame does not raise an error
|
|
|
|
im.seek(n_frames-1)
|
2015-06-18 17:49:18 +03:00
|
|
|
|
2014-07-23 19:27:46 +04:00
|
|
|
def test_image_grab(self):
|
|
|
|
for test_file in test_files:
|
|
|
|
im = Image.open(test_file)
|
|
|
|
self.assertEqual(im.tell(), 0)
|
|
|
|
im0 = im.tobytes()
|
|
|
|
im.seek(1)
|
|
|
|
self.assertEqual(im.tell(), 1)
|
|
|
|
im1 = im.tobytes()
|
|
|
|
im.seek(0)
|
|
|
|
self.assertEqual(im.tell(), 0)
|
2014-07-23 19:36:23 +04:00
|
|
|
im02 = im.tobytes()
|
2014-07-23 19:27:46 +04:00
|
|
|
self.assertEqual(im0, im02)
|
|
|
|
self.assertNotEqual(im0, im1)
|
2014-07-30 18:14:09 +04:00
|
|
|
|
|
|
|
def test_save(self):
|
|
|
|
# Note that only individual frames can be saved at present
|
|
|
|
for test_file in test_files:
|
|
|
|
im = Image.open(test_file)
|
|
|
|
self.assertEqual(im.tell(), 0)
|
|
|
|
jpg0 = self.frame_roundtrip(im)
|
|
|
|
self.assert_image_similar(im, jpg0, 30)
|
|
|
|
im.seek(1)
|
|
|
|
self.assertEqual(im.tell(), 1)
|
|
|
|
jpg1 = self.frame_roundtrip(im)
|
|
|
|
self.assert_image_similar(im, jpg1, 30)
|
|
|
|
|
2014-07-16 19:36:56 +04:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
unittest.main()
|