|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| from __future__ import annotations
|
|
|
| from . import Image
|
|
|
| TYPE_CHECKING = False
|
| if TYPE_CHECKING:
|
| from collections.abc import Callable
|
|
|
|
|
| class Iterator:
|
| """
|
| This class implements an iterator object that can be used to loop
|
| over an image sequence.
|
|
|
| You can use the ``[]`` operator to access elements by index. This operator
|
| will raise an :py:exc:`IndexError` if you try to access a nonexistent
|
| frame.
|
|
|
| :param im: An image object.
|
| """
|
|
|
| def __init__(self, im: Image.Image) -> None:
|
| if not hasattr(im, "seek"):
|
| msg = "im must have seek method"
|
| raise AttributeError(msg)
|
| self.im = im
|
| self.position = getattr(self.im, "_min_frame", 0)
|
|
|
| def __getitem__(self, ix: int) -> Image.Image:
|
| try:
|
| self.im.seek(ix)
|
| return self.im
|
| except EOFError as e:
|
| msg = "end of sequence"
|
| raise IndexError(msg) from e
|
|
|
| def __iter__(self) -> Iterator:
|
| return self
|
|
|
| def __next__(self) -> Image.Image:
|
| try:
|
| self.im.seek(self.position)
|
| self.position += 1
|
| return self.im
|
| except EOFError as e:
|
| msg = "end of sequence"
|
| raise StopIteration(msg) from e
|
|
|
|
|
| def all_frames(
|
| im: Image.Image | list[Image.Image],
|
| func: Callable[[Image.Image], Image.Image] | None = None,
|
| ) -> list[Image.Image]:
|
| """
|
| 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
|
|
|