Skip to content

Commit

Permalink
Merge pull request #3778 from radarhere/all_frames
Browse files Browse the repository at this point in the history
Added ImageSequence all_frames
  • Loading branch information
radarhere committed Jun 29, 2019
2 parents a7bdd64 + d2fdb48 commit 9074eda
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 0 deletions.
22 changes: 22 additions & 0 deletions Tests/test_imagesequence.py
Expand Up @@ -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)
8 changes: 8 additions & 0 deletions docs/releasenotes/6.1.0.rst
Expand Up @@ -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 be used to return all frames from an image, each rotated 90 degrees.

Variation fonts
^^^^^^^^^^^^^^^

Expand Down
22 changes: 22 additions & 0 deletions src/PIL/ImageSequence.py
Expand Up @@ -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

0 comments on commit 9074eda

Please sign in to comment.