Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

imagine.animation

import imagine.animation

imagine lifts part of this module out to its own top level; each name below is shown with the path that reaches it. Anything still spelled imagine.animation.* needs import imagine.animation.

Animation: an ordered set of frames with per-frame delays, which is what an animated GIF or WebP decodes to and encodes from.

Frames are full images rather than deltas, so each can be edited on its own and the encoder works out what actually changed.

Classes

Animation

class imagine.Animation

A sequence of images with a delay between each, read from or written to an animated format.

Frames are whole images, already composited against whatever came before them, so frame 5 can be pulled out and used on its own without replaying the first four. That is the useful shape almost all of the time, and it is why the disposal and transparency rules an animated GIF is built from never surface here.

import imagine { Animation }

var animation = Animation.open('loading.gif')

echo '${animation.length()} frames, ${animation.duration()}ms total'

animation
  .map(@(frame) {
    return frame.grayscale()
  })
  .save('loading-grey.gif')
What can be read and written

Animated GIF and animated WebP can both be read. Only GIF can be written; an animation saved as WebP raises EncodeError rather than quietly writing one frame. [[imagine.capabilities]] lists what is available under animated.

Memory

Every frame is a full image, so a 100-frame 500x500 animation is 100 MB decoded. Animations are worth streaming frame by frame when they are large, which frames() allows by handing back the list itself.

  • printable — has a @to_string(), so echo and print() show something useful

Constructor

imagine.Animation(frames: list, delay, repeat, format)

Creates an animation from a list of images.

Every frame must be the same size, since animated formats have one canvas that each frame paints into.

Parameters

  • frames (list) — A list of [[imagine.Image]].
  • delay (?number|list) — Milliseconds per frame, either one number for all of them or one per frame - Default: 100.
  • repeat (?number) — How many times to loop, 0 for forever - Default: 0.
  • format (?string) — The format these frames were decoded from, recorded as metadata - Default: nil.

Raises ImageError When the frames are not all images of one size.

Animation.open()

imagine.Animation.open(source) -> Animation

Opens an animated image file.

A still image opens as a one-frame animation rather than an error, so code that handles both does not need to branch.

Parameters

  • source (string|file)

Returns Animation

Raises DecodeError When the file is not a readable image.

Animation.decode()

imagine.Animation.decode(data: bytes) -> Animation

Decodes animated image data held in memory.

Parameters

  • data (bytes)

Returns Animation

Raises DecodeError When the data is not a readable image.

Animation.length()

imagine.Animation.length() -> number

How many frames the animation has.

Returns number

Animation.frames()

imagine.Animation.frames() -> list

The frames, as a list of [[imagine.Image]].

This is the live list, not a copy: changing an image in it changes the animation, which is what makes frame-by-frame editing possible without duplicating everything. Use map() when you want the original left alone.

Returns list

Animation.frame()

imagine.Animation.frame(index: number) -> Image

One frame by index, counting from zero.

Parameters

  • index (number)

Returns Image

Raises ImageError When there is no such frame.

Animation.delays()

imagine.Animation.delays() -> list

The per-frame delays in milliseconds.

Returns list

Animation.duration()

imagine.Animation.duration() -> number

How long one pass through the animation takes, in milliseconds.

Returns number

Animation.width()

imagine.Animation.width() -> number

The frames’ shared width in pixels.

Returns number

Animation.height()

imagine.Animation.height() -> number

The frames’ shared height in pixels.

Returns number

Animation.format()

imagine.Animation.format() -> ?string

The format this animation was decoded from, or nil.

Returns ?string

Animation.repeat()

imagine.Animation.repeat(times: number)

Sets how many times the animation loops when written out.

Parameters

  • times (number) — 0 loops forever.

Returns — self

Animation.delay()

imagine.Animation.delay(delay)

Sets the delay between frames.

Parameters

  • delay (number|list) — One value for every frame, or one per frame.

Returns — self

Animation.map()

imagine.Animation.map(fn: function) -> Animation

Applies a function to every frame, returning a new animation.

Each frame is copied before the function sees it, so a filter chain works directly as the body and this animation is left alone. That copy is the reason map() costs as much memory again as the animation itself; to filter in place instead, walk frames() and change each image directly.

var grey = animation.map(@(frame) {
  return frame.grayscale().blur(1)
})

Parameters

  • fn (function(1))

Returns Animation

Raises ImageError When the function returns anything but an image.

Animation.reverse()

imagine.Animation.reverse() -> Animation

Returns a new animation with the frames in reverse order.

The frames themselves are shared with this animation rather than copied, since reordering them changes nothing about them. Editing one afterwards therefore shows up in both; map() is the one that copies.

Returns Animation

Animation.to_image()

imagine.Animation.to_image() -> Image

Returns the animation as a single image: its first frame.

Returns Image

Animation.encode()

imagine.Animation.encode(format, options) -> bytes

Encodes the animation and returns the bytes.

Parameters

  • format (?string) — Default: GIF.
  • options (?dict)

Returns bytes

Raises EncodeError When the format cannot hold an animation.

Animation.save()

imagine.Animation.save(path: string, options)

Writes the animation to a file.

Parameters

  • path (string)
  • options (?dict) — format, plus everything encode() takes.

Returns — self

Animation.to_string()

imagine.Animation.to_string()

2026, Richard Ore and Zuri contributors