1#
2# The Python Imaging Library.
3# $Id$
4#
5# sequence support classes
6#
7# history:
8# 1997-02-20 fl Created
9#
10# Copyright (c) 1997 by Secret Labs AB.
11# Copyright (c) 1997 by Fredrik Lundh.
12#
13# See the README file for information on usage and redistribution.
14#
15
16##
17from __future__ import annotations
18
19from . import Image
20
21TYPE_CHECKING = False
22if TYPE_CHECKING:
23 from collections.abc import Callable
24
25
26class Iterator:
27 """
28 This class implements an iterator object that can be used to loop
29 over an image sequence.
30
31 You can use the ``[]`` operator to access elements by index. This operator
32 will raise an :py:exc:`IndexError` if you try to access a nonexistent
33 frame.
34
35 :param im: An image object.
36 """
37
38 def __init__(self, im: Image.Image) -> None:
39 if not hasattr(im, "seek"):
40 msg = "im must have seek method"
41 raise AttributeError(msg)
42 self.im = im
43 self.position = getattr(self.im, "_min_frame", 0)
44
45 def __getitem__(self, ix: int) -> Image.Image:
46 try:
47 self.im.seek(ix)
48 return self.im
49 except EOFError as e:
50 msg = "end of sequence"
51 raise IndexError(msg) from e
52
53 def __iter__(self) -> Iterator:
54 return self
55
56 def __next__(self) -> Image.Image:
57 try:
58 self.im.seek(self.position)
59 self.position += 1
60 return self.im
61 except EOFError as e:
62 msg = "end of sequence"
63 raise StopIteration(msg) from e
64
65
66def all_frames(
67 im: Image.Image | list[Image.Image],
68 func: Callable[[Image.Image], Image.Image] | None = None,
69) -> list[Image.Image]:
70 """
71 Applies a given function to all frames in an image or a list of images.
72 The frames are returned as a list of separate images.
73
74 :param im: An image, or a list of images.
75 :param func: The function to apply to all of the image frames.
76 :returns: A list of images.
77 """
78 if not isinstance(im, list):
79 im = [im]
80
81 ims = []
82 for imSequence in im:
83 current = imSequence.tell()
84
85 ims += [im_frame.copy() for im_frame in Iterator(imSequence)]
86
87 imSequence.seek(current)
88 return [func(im) for im in ims] if func else ims