From db4916849ec255a9f4312e02dced7b3f893471ea Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 23 Jun 2019 07:34:39 +1000 Subject: [PATCH 1/3] Added ImageSequence all_frames --- Tests/test_imagesequence.py | 22 ++++++++++++++++++++++ src/PIL/ImageSequence.py | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/Tests/test_imagesequence.py b/Tests/test_imagesequence.py index 38645f13389..5d90dc4c5af 100644 --- a/Tests/test_imagesequence.py +++ b/Tests/test_imagesequence.py @@ -74,3 +74,25 @@ def test_palette_mmap(self): im.seek(0) color2 = im.getpalette()[0:3] self.assertEqual(color1, color2) + + def test_all_frames(self): + # Test a single image + im = Image.open("Tests/images/iss634.gif") + ims = ImageSequence.all_frames(im) + + self.assertEqual(len(ims), 42) + for i, im_frame in enumerate(ims): + self.assertFalse(im_frame is im) + + im.seek(i) + self.assert_image_equal(im, im_frame) + + # Test a series of images + ims = ImageSequence.all_frames([im, hopper(), im]) + self.assertEqual(len(ims), 85) + + # Test an operation + ims = ImageSequence.all_frames(im, lambda im_frame: im_frame.rotate(90)) + for i, im_frame in enumerate(ims): + im.seek(i) + self.assert_image_equal(im.rotate(90), im_frame) diff --git a/src/PIL/ImageSequence.py b/src/PIL/ImageSequence.py index 84199fe2726..f9be92d4838 100644 --- a/src/PIL/ImageSequence.py +++ b/src/PIL/ImageSequence.py @@ -54,3 +54,25 @@ def __next__(self): def next(self): return self.__next__() + + +def all_frames(im, func=None): + """ + Applies a given function to all frames in an image or a list of images. + The frames are returned as a list of separate images. + + :param im: An image, or a list of images. + :param func: The function to apply to all of the image frames. + :returns: A list of images. + """ + if not isinstance(im, list): + im = [im] + + ims = [] + for imSequence in im: + current = imSequence.tell() + + ims += [im_frame.copy() for im_frame in Iterator(imSequence)] + + imSequence.seek(current) + return [func(im) for im in ims] if func else ims From 1abcada1c52c041347ac1882d66bf530ad645e73 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 29 Jun 2019 17:47:55 +1000 Subject: [PATCH 2/3] Added release notes [ci skip] --- docs/releasenotes/6.1.0.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/releasenotes/6.1.0.rst b/docs/releasenotes/6.1.0.rst index 98568fb52ec..783c4d32326 100644 --- a/docs/releasenotes/6.1.0.rst +++ b/docs/releasenotes/6.1.0.rst @@ -11,6 +11,14 @@ An optional ``include_layered_windows`` parameter has been added to ``ImageGrab. defaulting to ``False``. If true, layered windows will be included in the resulting image on Windows. +ImageSequence.all_frames +^^^^^^^^^^^^^^^^^^^^^^^^ + +A new method to facilitate applying a given function to all frames in an image, or to +all frames in a list of images. The frames are returned as a list of separate images. +For example, ``ImageSequence.all_frames(im, lambda im_frame: im_frame.rotate(90))`` +could used to return all frames from an image, each rotated 90 degrees. + Variation fonts ^^^^^^^^^^^^^^^ From d2fdb4818c8e51e683f0f038846bd44882c815f8 Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Sat, 29 Jun 2019 18:02:08 +1000 Subject: [PATCH 3/3] Fixed wording Co-Authored-By: Hugo --- docs/releasenotes/6.1.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releasenotes/6.1.0.rst b/docs/releasenotes/6.1.0.rst index 783c4d32326..851dcb2d0a4 100644 --- a/docs/releasenotes/6.1.0.rst +++ b/docs/releasenotes/6.1.0.rst @@ -17,7 +17,7 @@ ImageSequence.all_frames A new method to facilitate applying a given function to all frames in an image, or to all frames in a list of images. The frames are returned as a list of separate images. For example, ``ImageSequence.all_frames(im, lambda im_frame: im_frame.rotate(90))`` -could used to return all frames from an image, each rotated 90 degrees. +could be used to return all frames from an image, each rotated 90 degrees. Variation fonts ^^^^^^^^^^^^^^^