Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve handling of PSD frames #3759

Merged
merged 3 commits into from Jun 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions Tests/test_file_psd.py
Expand Up @@ -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"

Expand Down Expand Up @@ -65,6 +71,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)
Expand Down
6 changes: 6 additions & 0 deletions Tests/test_imagesequence.py
Expand Up @@ -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)):
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/ImageSequence.py
Expand Up @@ -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:
Expand Down
14 changes: 12 additions & 2 deletions src/PIL/PsdImagePlugin.py
Expand Up @@ -54,6 +54,7 @@ class PsdImageFile(ImageFile.ImageFile):

format = "PSD"
format_description = "Adobe Photoshop"
_close_exclusive_fp_after_loading = False

def _open(self):

Expand Down Expand Up @@ -128,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

Expand All @@ -150,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")
Expand All @@ -167,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
Expand Down