From 72d5ee3bfae196ffaf498529d66cf09c36ef24a6 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 31 Mar 2019 22:24:10 +1100 Subject: [PATCH 1/3] Do not close exclusive fp after loading --- Tests/test_file_psd.py | 6 ++++++ src/PIL/PsdImagePlugin.py | 1 + 2 files changed, 7 insertions(+) diff --git a/Tests/test_file_psd.py b/Tests/test_file_psd.py index 3b8a7add689..3d434d5a7fe 100644 --- a/Tests/test_file_psd.py +++ b/Tests/test_file_psd.py @@ -65,6 +65,12 @@ def test_seek_eoferror(self): self.assertRaises(EOFError, im.seek, -1) + def test_open_after_exclusive_load(self): + im = Image.open(test_file) + im.load() + im.seek(im.tell()+1) + im.load() + def test_icc_profile(self): im = Image.open(test_file) self.assertIn("icc_profile", im.info) diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py index a8d370eed3c..17e6bc4e98f 100644 --- a/src/PIL/PsdImagePlugin.py +++ b/src/PIL/PsdImagePlugin.py @@ -54,6 +54,7 @@ class PsdImageFile(ImageFile.ImageFile): format = "PSD" format_description = "Adobe Photoshop" + _close_exclusive_fp_after_loading = False def _open(self): From ea02e28adb6874da9c3417ade7bbfb3406b10434 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 12 Jun 2019 20:11:51 +1000 Subject: [PATCH 2/3] Use _min_frame in ImageSequence.Iterator --- Tests/test_imagesequence.py | 6 ++++++ src/PIL/ImageSequence.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Tests/test_imagesequence.py b/Tests/test_imagesequence.py index 9fbf3fed8a7..aafb6e02e12 100644 --- a/Tests/test_imagesequence.py +++ b/Tests/test_imagesequence.py @@ -32,6 +32,12 @@ def test_iterator(self): self.assertRaises(IndexError, lambda: i[index+1]) self.assertRaises(StopIteration, next, i) + def test_iterator_min_frame(self): + im = Image.open('Tests/images/hopper.psd') + i = ImageSequence.Iterator(im) + for index in range(1, im.n_frames): + self.assertEqual(i[index], next(i)) + def _test_multipage_tiff(self): im = Image.open('Tests/images/multipage.tiff') for index, frame in enumerate(ImageSequence.Iterator(im)): diff --git a/src/PIL/ImageSequence.py b/src/PIL/ImageSequence.py index 1fc6e5de165..84199fe2726 100644 --- a/src/PIL/ImageSequence.py +++ b/src/PIL/ImageSequence.py @@ -32,7 +32,7 @@ def __init__(self, im): if not hasattr(im, "seek"): raise AttributeError("im must have seek method") self.im = im - self.position = 0 + self.position = getattr(self.im, "_min_frame", 0) def __getitem__(self, ix): try: From e1e35cc81945423526e4cf9bf4c735013be22b29 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 1 Apr 2019 00:02:22 +1100 Subject: [PATCH 3/3] Close internal fp when closing and deleting --- Tests/test_file_psd.py | 6 ++++++ src/PIL/PsdImagePlugin.py | 13 +++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Tests/test_file_psd.py b/Tests/test_file_psd.py index 3d434d5a7fe..c62d7ca1062 100644 --- a/Tests/test_file_psd.py +++ b/Tests/test_file_psd.py @@ -17,6 +17,12 @@ def test_sanity(self): im2 = hopper() self.assert_image_similar(im, im2, 4.8) + def test_unclosed_file(self): + def open(): + im = Image.open(test_file) + im.load() + self.assert_warning(None, open) + def test_invalid_file(self): invalid_file = "Tests/images/flower.jpg" diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py index 17e6bc4e98f..576ea90243c 100644 --- a/src/PIL/PsdImagePlugin.py +++ b/src/PIL/PsdImagePlugin.py @@ -129,7 +129,7 @@ def _open(self): self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels) # keep the file open - self._fp = self.fp + self.__fp = self.fp self.frame = 1 self._min_frame = 1 @@ -151,7 +151,7 @@ def seek(self, layer): self.mode = mode self.tile = tile self.frame = layer - self.fp = self._fp + self.fp = self.__fp return name, bbox except IndexError: raise EOFError("no such layer") @@ -168,6 +168,15 @@ def load_prepare(self): if self.mode == "P": Image.Image.load(self) + def _close__fp(self): + try: + if self.__fp != self.fp: + self.__fp.close() + except AttributeError: + pass + finally: + self.__fp = None + def _layerinfo(file): # read layerinfo block