Sequence ======== .. note:: The image :file:`sequence-animation.gif` used in this docs has been released into the public domain by its author, C6541_ at Wikipedia_ project. This applies worldwide. (Source_) .. _C6541: http://en.wikipedia.org/wiki/User:C6541 .. _Wikipedia: http://en.wikipedia.org/wiki/ .. _Source: http://commons.wikimedia.org/wiki/File:1.3-B.gif .. versionadded:: 0.3.0 Some images may actually consist of two or more images. For example, animated :mimetype:`image/gif` images consist of multiple frames. Some :mimetype:`image/ico` images have different sizes of icons. .. image:: ../_images/sequence-animation.gif :alt: sequence-animation.gif For example, the above image :file:`sequence-animation.gif` consists of the following frames (actually it has 60 frames, but we sample only few frames to show here): .. image:: ../_images/sequence-frames.gif :alt: frames of sequence-animation.gif :attr:`~wand.image.BaseImage.sequence` is a :class:`~collections.Sequence` -------------------------------------------------------------------------- If we :doc:`open ` this image, :class:`~wand.image.Image` object has :attr:`~wand.image.BaseImage.sequence`. It's a list-like object that maintain its all frames. For example, :func:`len()` for this returns the number of frames: >>> from wand.image import Image >>> with Image(filename='sequence-animation.gif') as image: ... len(image.sequence) ... 60 You can get an item by index from :attr:`~wand.image.BaseImage.sequence`: >>> with Image(filename='sequence-animation.gif') as image: ... image.sequence[0] ... Or slice it: >>> with Image(filename='sequence-animation.gif') as image: ... image.sequence[5:10] ... [, , , , ] :attr:`~wand.image.Image` versus :attr:`~wand.sequence.SingleImage` ------------------------------------------------------------------- Note that each item of :attr:`~wand.image.BaseImage.sequence` is a :class:`~wand.sequence.SingleImage` instance, not :class:`~wand.image.Image`. :class:`~wand.image.Image` is a container that directly represents *image files* like :file:`sequence-animation.gif`, and :class:`~wand.sequence.SingleImage` is a single image that represents *frames* in animations or *sizes* in :mimetype:`image/ico` files. They both inherit :class:`~wand.image.BaseImage`, the common abstract class. They share the most of available operations and properties like :meth:`~wand.image.BaseImage.resize()` and :attr:`~wand.image.BaseImage.size`, but some are not. For example, :meth:`~wand.image.Image.save()` and :attr:`~wand.image.Image.mimetype` are only provided by :class:`~wand.image.Image`. :attr:`~wand.sequence.SingleImage.delay` and :attr:`~wand.sequence.SingleImage.index` are only available for :class:`~wand.sequence.SingleImage`. In most cases, images don't have multiple images, so it's okay if you think that :class:`~wand.image.Image` and :class:`~wand.sequence.SingleImage` are the same, but be careful when you deal with animated :mimetype:`image/gif` files or :mimetype:`image/ico` files that contain multiple icons. Manipulating :attr:`~wand.sequence.SingleImage` ----------------------------------------------- When working with :attr:`~wand.image.BaseImage.sequence`, it's important to remember that each instance of :class:`~wand.sequence.SingleImage` holds a *copy* of image data from the stack. Altering the copied data will not automatically sync back to the original image-stack. >>> with Image(filename='animation.gif') as image: ... # Changes on SingleImage are invisible to `image` container. ... image.sequence[2].negate() ... image.save(filename='output.gif') # Changes ignored. If you intended to alter a :class:`~wand.sequence.SingleImage`, and have changes synchronized back to the parent image-stack, use an additional with-statement context manager. >>> with Image(filename='animation.gif') as image: ... # Changes on SingleImage are sync-ed after context manager closes. ... with image.sequence[2] as frame: ... frame.negate() ... image.save(filename='output.gif') # Changes applied.