Reference

Everything public

Every type, method, function and value, grouped by package. The signatures are the ones the compiler sees; the prose is the comment the source carries. Generated from those two, so the page cannot drift from the code.

moonimage Every format, one door

Format detection, decoding, encoding and animation, all of it delegating to the packages below.

functions
function pub fn decode(bytes : BytesView, limits? : @raster.Limits) -> @raster.Image raise @raster.Refused

The image in these bytes, whichever format they are.

The limits default to Limits::default(); a caller reading untrusted files should pass Limits::strict() or a tighter record.

function pub fn decode_animation(bytes : BytesView, limits? : @raster.Limits) -> @raster.Animation raise @raster.Refused

Every frame in these bytes, whichever format they are.

A format that does not animate comes back as an animation of one frame over the whole canvas, so a caller that only draws animations does not need to branch.

function pub fn encode(image : @raster.Image, format : @raster.Format) -> Bytes

The image as bytes of the named format, with that format's defaults.

A caller that wants to choose how it is written calls the format's own package, which takes its options record.

function pub fn encode_animation(animation : @raster.Animation, format : @raster.Format) -> Bytes raise @raster.Refused

The animation as bytes of the named format, with that format's defaults.

The formats that animate keep every frame; the ones that do not write the first, which is what a viewer of a still image shows.

raster Pictures and pixels

The picture itself: layouts, conversion, geometry, scaling, animation frames, metadata, limits and the one error type.

struct pub(all) struct Animation

A sequence of frames over one canvas.

  • widthInt32 The canvas width every frame is placed on.
  • heightInt32 The canvas height every frame is placed on.
  • loopsInt32 How many times the animation plays. 0 means forever, which is what an animation without a repeat count means in all three formats.
  • framesArray[Frame] The frames, in order.
  • metadataMetadata Metadata that belongs to the animation as a whole.
pub fn Animation::compose(self : Animation) -> Array[Image]

Every frame as a full canvas, in order, with each rule applied as it goes.

The result is what a viewer shows: the same length as frames, each one the whole canvas. This is the expensive way to watch an animation and the only way to see it out of context, which is what a test does.

The canvas is sixteen-bit, so that an eight-bit animation and a sixteen-bit one come out of the same code without either losing its precision.

pub fn Animation::new(width : Int32, height : Int32, frames : Array[Frame], loops? : Int32, metadata? : Metadata) -> Animation

An animation over a canvas, with no frames yet unless given some.

enum pub(all) enum Blend

How a frame's pixels meet what is already on the canvas.

  • Source Replace, alpha and all.
  • Over Composite, the usual over.
struct pub(all) struct Chromaticities

The white point and the three primaries, as chromaticity coordinates.

Eight numbers rather than a matrix: this is what a file writes, and a matrix would be a conversion, which this library does not do.

  • white_xDouble
  • white_yDouble
  • red_xDouble
  • red_yDouble
  • green_xDouble
  • green_yDouble
  • blue_xDouble
  • blue_yDouble
pub fn Chromaticities::srgb() -> Chromaticities

The primaries of sRGB, which is what almost every file means when it says nothing.

enum pub(all) enum Dispose

What to do with the frame's rectangle once the frame has been shown.

  • Keep Leave it: the next frame draws over it.
  • Background Clear it to transparent black.
  • Previous Put back whatever was under it before it was drawn.
enum pub(all) enum Format

The formats this library reads and writes.

  • Png PNG, with APNG for animation.
  • Qoi Quite OK Image.
  • Bmp Windows bitmap.
  • Tga Truevision TGA.
  • Jpeg JPEG, baseline and progressive.
  • Gif GIF, with animation.
  • Webp WebP, lossless, lossy and animated.
  • pub
pub fn Format::extension(self : Format) -> String

The extension a file of this format usually has, without the dot.

pub fn Format::mime(self : Format) -> String

The media type a server would send for this format.

pub fn Format::of(bytes : BytesView) -> Format raise Refused

Which format these bytes are, by signature.

Raises Unknown when nothing matches and Truncated when there are too few bytes to tell: two bytes of a PNG are not a PNG, and saying so is better than guessing.

pub fn Format::to_string(Self) -> String
struct pub(all) struct Frame

One frame: a picture, where it goes, and how long it stays.

  • imageImage The pixels of this frame, already in a pixel format.
  • xInt32 Where the frame's top-left corner sits on the canvas.
  • yInt32 Where the frame's top-left corner sits on the canvas.
  • delayInt32 How long the frame is shown, in milliseconds.
  • disposeDispose What to do with the rectangle afterwards.
  • blendBlend How to lay the frame over what is there.
pub fn Frame::new(image : Image, x? : Int32, y? : Int32, delay? : Int32, dispose? : Dispose, blend? : Blend) -> Frame

A frame that covers the canvas, shown for a tenth of a second, drawn over what is there.

struct pub(all) struct Icc

An embedded ICC profile, kept by name and bytes. Not applied: a caller that wants colour management hands these bytes to something that does it.

  • nameString
  • profileBytes
struct pub(all) struct Image

An image: its shape, its layout, and the bytes.

  • widthInt32 How many pixels across.
  • heightInt32 How many pixels down.
  • formatPixelFormat How each pixel is laid out.
  • strideInt32 How many bytes from the start of one row to the start of the next.
  • pixelsBytes The samples, row after row, height * stride bytes or a little less when the last row is tight.
  • premultipliedBool Whether the colour channels have already been multiplied by alpha.
  • metadataMetadata What the file said about itself.
pub fn Image::convert(self : Image, format : PixelFormat) -> Image

The same image, in another sample format.

Colour is preserved as far as the target can hold it: a grey image becomes grey, an image without alpha becomes opaque, and narrowing rounds to nearest.

pub fn Image::crop(self : Image, x : Int32, y : Int32, width : Int32, height : Int32) -> Image raise Refused

The rectangle at (x, y) of the given size, as an image of its own.

Raises when the rectangle does not fit: a crop is a claim about the image, and a crop that reaches outside it is a bug in the caller.

pub fn Image::flip_horizontal(self : Image) -> Image

The image reflected left to right.

pub fn Image::flip_vertical(self : Image) -> Image

The image reflected top to bottom.

pub fn Image::new(width : Int32, height : Int32, format : PixelFormat, stride? : Int32, premultiplied? : Bool, metadata? : Metadata) -> Image

A black image of this shape, with tight rows.

stride is only needed when the rows must be padded; leave it out and the rows are as wide as the pixels.

pub fn Image::of(width : Int32, height : Int32, format : PixelFormat, pixels : Bytes, stride? : Int32, premultiplied? : Bool, metadata? : Metadata) -> Image raise Refused

An image over bytes that already exist.

Raises when the bytes cannot hold the shape: a stride narrower than a row, or fewer bytes than the last row needs.

pub fn Image::pixel(self : Image, x : Int32, y : Int32) -> Pixel raise Refused

The pixel at a coordinate, in the units every operation works in.

Straight alpha, as stored: an image that says it is premultiplied returns premultiplied samples, because pretending otherwise would be a conversion the caller did not ask for.

pub fn Image::rotate(self : Image, quarters? : Int32) -> Image

The image turned a quarter turn clockwise, quarters times.

Negative counts turn anticlockwise, and anything beyond four wraps: this is a total function because a rotation is.

pub fn Image::row(self : Image, y : Int32) -> BytesView raise Refused

One row, without its padding.

pub fn Image::scale(self : Image, width : Int32, height : Int32, sampling? : Sampling) -> Image raise Refused

The image at a new size.

Raises when either dimension is not positive, and when the result would be larger than Limits::default() — a scaler is easy to point at a huge size by accident.

pub fn Image::to_premultiplied(self : Image) -> Image

The same image with colour multiplied by alpha.

Idempotent: an image that already says it is premultiplied comes back unchanged, so a caller can ask without checking first.

pub fn Image::to_straight(self : Image) -> Image

The same image with alpha divided back out.

The inverse of to_premultiplied up to rounding, which is why a round trip is only exact for images whose colour is already premultiplied.

enum pub(all) enum Intent

What a column of pixels was meant to be seen in.

  • Perceptual For a picture.
  • Relative For a colour that should come out as it went in.
  • Saturation For a diagram, where saturation matters more than hue.
  • Absolute For comparing against a proof.
pub fn Intent::code(self : Intent) -> Int32

The number a file writes for this intent, which is how PNG's sRGB chunk numbers them.

pub fn Intent::of(code : Int32) -> Intent?

The intent a number stands for, or None if it is not one of the four.

struct pub(all) struct Limits

The ceilings a decoder works under.

The defaults are the ones a desktop application can live with: a texture no larger than a modern GPU takes, and a megabyte of pixels at the very most. A caller reading files from the network should set them lower; a caller reading its own assets can leave them alone.

  • widthInt32 The widest image accepted, in pixels.
  • heightInt32 The tallest image accepted, in pixels.
  • pixelsInt32 The most pixels accepted, whatever the shape: this is the one that stops a long thin image from slipping past the two above.
  • bytesInt32 The most bytes a decoder may produce while unpacking: a compressed stream can expand without limit, so the expansion is capped separately.
pub fn Limits::allows(self : Limits, width : Int32, height : Int32) -> Bool

Whether an image of this shape is inside the limits.

pub fn Limits::check(self : Limits, width : Int32, height : Int32) -> Unit raise Refused

Refuse an image of this shape unless the limits allow it.

The pixel count is multiplied in 64 bits so that a declaration of 65535 × 65535 cannot wrap into a small number and pass.

pub fn Limits::check_bytes(self : Limits, bytes : Int32) -> Unit raise Refused

Refuse a buffer of this many bytes unless the limits allow it.

pub fn Limits::default() -> Limits

The desktop defaults: a million pixels a side, 256 megapixels in all, and a gigabyte of expansion.

pub fn Limits::strict() -> Limits

What a viewer of untrusted uploads would choose: 8192 square, 64 megapixels, 256 MiB of expansion.

struct pub(all) struct Metadata

Everything the file said about itself besides its pixels.

  • gammaDouble? The file gamma: the exponent the samples were encoded with, so that 0.45455 means what sRGB means.
  • chromaticitiesChromaticities? The primaries the image was authored for.
  • intentIntent? The rendering intent, which only means anything next to an sRGB or ICC tag.
  • iccIcc? The embedded profile, if there was one.
  • textsArray[Text] The text notes, in the order the file had them.
pub fn Metadata::default() -> Metadata

No metadata at all, which is what an image built in memory has.

pub fn Metadata::is_empty(self : Metadata) -> Bool

Whether there is nothing to write.

struct pub(all) struct Pixel

One pixel, in the units every operation in the library works in: four samples from 0 to 1, alpha straight.

A grey pixel has r, g and b equal, which is why there is no grey variant: a reader that has to branch on whether a pixel is grey is a reader that will forget to inflate one of the three channels.

  • rDouble
  • gDouble
  • bDouble
  • aDouble
pub fn Pixel::of_rgba8(r : Int32, g : Int32, b : Int32, a? : Int32) -> Pixel

A pixel from the eight-bit values an editor shows.

pub fn Pixel::rgba16(self : Pixel) -> (Int32, Int32, Int32, Int32)

The pixel as sixteen-bit samples, which is what a PNG stores when its bit depth is sixteen.

pub fn Pixel::rgba8(self : Pixel) -> (Int32, Int32, Int32, Int32)

The pixel as bytes an editor shows: rounded, clamped, alpha last.

enum pub(all) enum PixelFormat

How the samples of an image are laid out.

The names are the usual ones: Gray8 is one byte per pixel, Rgba8 four, Rgba16 eight with each channel big-endian, RgbaF32 four floats.

  • Gray8 One sample, 8 bits.
  • GrayAlpha8 Grey and alpha, 8 bits each.
  • Rgb8 Three samples, 8 bits each, red first.
  • Rgba8 Four samples, 8 bits each, red first, alpha last.
  • Gray16 One sample, 16 bits, big-endian.
  • GrayAlpha16 Grey and alpha, 16 bits each.
  • Rgb16 Three samples, 16 bits each, big-endian.
  • Rgba16 Four samples, 16 bits each, big-endian.
  • RgbaF32 Four samples as Float, 0–1, little-endian.
  • pub
pub fn PixelFormat::bits(self : PixelFormat) -> Int32

How many bits one sample takes. For RgbaF32 this is 32, which says how wide the sample is, not that it is an integer.

pub fn PixelFormat::bytes(self : PixelFormat) -> Int32

How many bytes a pixel of this format takes.

pub fn PixelFormat::channels(self : PixelFormat) -> Int32

How many samples a pixel of this format has.

pub fn PixelFormat::has_alpha(self : PixelFormat) -> Bool

Whether the image carries alpha.

pub fn PixelFormat::is_float(self : PixelFormat) -> Bool

Whether the samples are floats rather than integers.

pub fn PixelFormat::is_gray(self : PixelFormat) -> Bool

Whether the image carries colour at all.

pub fn PixelFormat::to_string(Self) -> String
error pub(all) suberror Refused

A refusal to read bytes as an image, or to write an image as bytes.

The variants separate the three questions a caller asks: is this the wrong kind of file (Unknown), is the file damaged (Unexpected, Truncated, Checksum), or is the caller asking for more than it allowed (OverLimit). Unsupported is the fourth: a part of a format this library does not read.

  • Unexpected(at~ : Int32, got~ : String, want~ : String) The bytes at at are not allowed here; want says what is.
  • Unknown(at~ : Int32, got~ : String) Nothing at at is an image this library reads.
  • Unsupported(at~ : Int32, got~ : String) A part of the format this library does not read.
  • Truncated(at~ : Int32, want~ : Int32) The bytes end want short of where the format needs them.
  • OverLimit(limit~ : Int32, got~ : Int32) A size or a length past what the caller's Limits allow.
  • Checksum(at~ : Int32, got~ : String, want~ : String) A checksum that does not match the bytes it covers.
  • pub
pub fn Refused::to_string(Self) -> String
enum pub(all) enum Sampling

How a scaler decides what an unknown pixel is worth.

  • Nearest The nearest pixel, and nothing else: no new colours.
  • Bilinear A weighted average of the four nearest, weights linear in distance.
  • Lanczos A weighted average of the six nearest per axis, weights from the Lanczos window with a = 3.
enum pub(all) enum Text

A text note, in the flavour of the chunk it came from, so that writing the image back produces the same kind of chunk.

  • Latin(keyword~ : String, text~ : String) tEXt: Latin-1, one keyword and one line.
  • Compressed(keyword~ : String, text~ : String) zTXt: the same, deflated.
  • International(keyword~ : String, language~ : String, translated~ : String, text~ : String) iTXt: UTF-8, with a language tag and a translated keyword.
pub fn Text::keyword(self : Text) -> String

The keyword a note is filed under.

pub fn Text::text(self : Text) -> String

What the note says.

functions
function pub fn hex(bytes : BytesView, at : Int32, count : Int32) -> String

A few bytes as hexadecimal, for the got field of a refusal.

bmp Windows bitmap

Every header version, one to thirty-two bits a pixel, the two run-length encodings and both row orders.

enum pub(all) enum Depth

How wide a pixel is written.

  • Bits24 Three bytes per pixel. Alpha is dropped.
  • Bits32 Four bytes per pixel, alpha last. A BMP with an alpha channel is read by Windows itself; other readers may ignore the fourth byte.
struct pub(all) struct EncodeOptions

What to write.

  • depthDepth How wide a pixel is.
  • top_downBool Whether to store the top row first, which the format allows by writing a negative height. Windows writes bottom first, which is the default.
pub fn EncodeOptions::default() -> EncodeOptions

Thirty-two bits per pixel, bottom row first.

functions
function pub fn decode(bytes : BytesView, limits? : @raster.Limits) -> @raster.Image raise @raster.Refused

The image in a BMP file.

function pub fn encode(image : @raster.Image, options? : EncodeOptions) -> Bytes

The image as a BMP file.

gif GIF

Palettes, transparency, interlacing, the LZW stream, and animation with its disposal rules.

struct pub(all) struct EncodeOptions

What to trade when writing a GIF.

  • ditherBool Whether to dither when the image has more colours than a palette holds. On, a gradient looks like a gradient; off, it bands, and the file is smaller.
  • transparentBool Whether to keep alpha as GIF's one transparent colour. Off, alpha becomes the nearest opaque colour.
pub fn EncodeOptions::default() -> EncodeOptions

Dither, and keep transparency.

functions
function pub fn decode(bytes : BytesView, limits? : @raster.Limits) -> @raster.Image raise @raster.Refused

The first frame of a GIF.

function pub fn decode_animation(bytes : BytesView, limits? : @raster.Limits) -> @raster.Animation raise @raster.Refused

Every frame of a GIF, with the rectangle, delay, disposal and transparency each frame declares.

function pub fn encode(image : @raster.Image, options? : EncodeOptions) -> Bytes

The image as a single-frame GIF.

function pub fn encode_animation(animation : @raster.Animation, options? : EncodeOptions) -> Bytes

The animation as an animated GIF.

jpeg JPEG

Baseline and progressive files, every subsampling, restart markers, and EXIF orientation.

struct pub(all) struct EncodeOptions

What to trade when writing a JPEG.

  • qualityInt32 1 to 100. 90 is the point where a photograph stops showing artefacts at normal viewing distance.
  • subsamplingSubsampling How much colour resolution to give up.
pub fn EncodeOptions::best() -> EncodeOptions

Quality 95, full colour resolution: for a picture that will be edited again.

pub fn EncodeOptions::default() -> EncodeOptions

Quality 90, colour at half resolution both ways.

enum pub(all) enum Orientation

The eight ways a camera says its picture is rotated, numbered the way EXIF numbers them.

  • Normal As stored.
  • FlipHorizontal Mirrored left to right.
  • Rotate180 Upside down.
  • FlipVertical Mirrored top to bottom.
  • Transpose Mirrored across the main diagonal.
  • Rotate90 Turned a quarter clockwise.
  • Transverse Mirrored across the other diagonal.
  • Rotate270 Turned a quarter anticlockwise.
pub fn Orientation::code(self : Orientation) -> Int32

The number EXIF writes for this orientation, 1 to 8.

pub fn Orientation::of(code : Int32) -> Orientation?

The orientation a number stands for, or None if it is not one of the eight.

enum pub(all) enum Subsampling

How much of the colour resolution to give up.

The eye resolves brightness far better than hue, so the two colour channels are stored at half resolution or a quarter, which is where most of JPEG's size comes from.

  • Yuv444 Full resolution in all three channels.
  • Yuv422 Colour at half horizontal resolution.
  • Yuv420 Colour at half resolution both ways, which is what a camera writes.
functions
function pub fn decode(bytes : BytesView, limits? : @raster.Limits, orient? : Bool) -> @raster.Image raise @raster.Refused

The image in a JPEG file.

With orient=true the pixels are rearranged to match the EXIF orientation, which is what a viewer does; without it they are as stored.

function pub fn encode(image : @raster.Image, options? : EncodeOptions) -> Bytes

The image as a baseline JPEG.

function pub fn exif_orientation(bytes : BytesView) -> Orientation?

The orientation in the EXIF block of a JPEG, or None when there is no EXIF or it says nothing this library understands.

A damaged EXIF block is not a damaged image: it comes back as None rather than as a refusal, because a picture with a broken camera note is still a picture.

png PNG

Every colour type and bit depth, Adam7, the five filters, text and colour chunks, and APNG.

struct pub(all) struct EncodeOptions

What to trade when writing a PNG.

  • levelInt32 Deflate level, 0 to 9.
  • filterFilter How rows are filtered before deflating.
  • interlaceBool Whether to write the image in seven passes, which helps a viewer show something before the last byte arrives and makes the file slightly larger.
  • metadataBool Whether to write the metadata the image carries.
  • paletteBool Whether to write a picture of at most 256 colours as a palette. A palette costs a table of colours and saves three quarters of every pixel, which is the difference between a sprite and a photograph in one flag.
pub fn EncodeOptions::best() -> EncodeOptions

For when the file is going to be stored: level 9, adaptive filtering.

pub fn EncodeOptions::default() -> EncodeOptions

Balanced: level 6, adaptive filtering, not interlaced, metadata kept.

pub fn EncodeOptions::fast() -> EncodeOptions

For when the bytes are going to a screen immediately: level 1, no filtering, no metadata.

enum pub(all) enum Filter

Which row filter an encoder uses.

Adaptive is the one the specification recommends: try all five, keep the one whose output has the smallest sum of absolute differences. It costs four extra passes over each row and usually pays for itself several times over in what the compressor then has to store.

  • Adaptive Pick per row.
  • None Store the row as it is.
  • Sub Subtract the pixel to the left.
  • Up Subtract the pixel above.
  • Average Subtract the average of the two.
  • Paeth Subtract the one the Paeth predictor picks.
functions
function pub fn decode(bytes : BytesView, limits? : @raster.Limits) -> @raster.Image raise @raster.Refused

The image in a PNG file.

Raises Refused on any damage, including a chunk whose CRC does not match.

function pub fn decode_animation(bytes : BytesView, limits? : @raster.Limits) -> @raster.Animation raise @raster.Refused

Every frame of an APNG. A PNG that is not animated comes back as one frame covering the whole canvas.

function pub fn encode(image : @raster.Image, options? : EncodeOptions) -> Bytes

The image as a PNG.

function pub fn encode_animation(animation : @raster.Animation, options? : EncodeOptions) -> Bytes

The animation as an APNG.

qoi Quite OK Image

Six opcodes and a run-length code: the smallest complete codec in the package.

functions
function pub fn decode(bytes : BytesView, limits? : @raster.Limits) -> @raster.Image raise @raster.Refused

The image in a QOI file.

A file that declares three channels decodes to Rgb8, one that declares four to Rgba8; a file that declares three and then uses an alpha opcode is not an error, and decodes to Rgba8.

function pub fn encode(image : @raster.Image) -> Bytes

The image as a QOI file.

An image without alpha is written as three channels, one with alpha as four. The encoder follows the reference exactly, so encoding what was decoded reproduces the file byte for byte.

tga Truevision TGA

Paletted, true colour and grey, optional run-length, and both row orders.

enum pub(all) enum Depth

How wide a pixel is written.

  • Bits24 Three bytes per pixel. Alpha is dropped.
  • Bits32 Four bytes per pixel, alpha last.
struct pub(all) struct EncodeOptions

What to write.

  • depthDepth How wide a pixel is.
  • rleBool Whether to run-length code the pixels, which is smaller whenever there are areas of one colour and never much larger.
  • top_downBool Whether to store the top row first. TGA's own convention is bottom first.
pub fn EncodeOptions::default() -> EncodeOptions

Thirty-two bits per pixel, run-length coded, bottom row first.

functions
function pub fn decode(bytes : BytesView, limits? : @raster.Limits) -> @raster.Image raise @raster.Refused

The image in a TGA file.

function pub fn encode(image : @raster.Image, options? : EncodeOptions) -> Bytes

The image as a TGA file.

webp WebP

Lossless and lossy pictures, the alpha chunk that travels beside a lossy one, and animation.

functions
function pub fn decode(bytes : BytesView, limits? : @raster.Limits) -> @raster.Image raise @raster.Refused

The image in a WebP file.

function pub fn decode_alpha(payload : BytesView, width : Int32, height : Int32, limits : @raster.Limits) -> Bytes raise @raster.Refused

The alpha plane that travels beside a lossy picture.

VP8 codes no alpha, so a transparent lossy WebP carries a separate ALPH chunk: one byte saying how it is stored, then the plane — raw, or compressed with the *lossless* codec, in which case the samples sit in its green channel — then a filter along each row, the same idea as PNG's and undone the same way. The result is one byte per pixel, which is all an alpha channel is.

function pub fn decode_animation(bytes : BytesView, limits? : @raster.Limits) -> @raster.Animation raise @raster.Refused

Every frame of an animated WebP.

A still picture comes back as an animation of one frame covering the whole canvas, which is what every other format here does and what lets a caller hand any WebP to one code path.

function pub fn decode_lossless(payload : BytesView, limits : @raster.Limits) -> @raster.Image raise @raster.Refused

The image in a VP8L payload, whose first byte is the signature.

function pub fn decode_lossless_stream(payload : BytesView, width : Int32, height : Int32, limits : @raster.Limits) -> @raster.Image raise @raster.Refused

The image in a lossless *stream*: the part of a VP8L file that comes after its five-byte header, with the size supplied by the caller.

A lossy WebP codes its alpha channel this way, in a separate ALPH chunk whose size is the picture's own, which is why there is no header to read.

function pub fn decode_lossy(payload : BytesView, limits : @raster.Limits) -> @raster.Image raise @raster.Refused

The image in a VP8 payload: a frame header, then the compressed frame.

The header is in the first partition, interleaved with the macroblock modes; the coefficients are spread over up to eight partitions, one per row of macroblocks in rotation, which is what lets a decoder read them in parallel.

function pub fn encode(image : @raster.Image) -> Bytes

The image as a lossless WebP.

Every image can be written — the writer finds its own trees and never has to refuse — so this is the one direction in the library that cannot fail.

function pub fn encode_animation(animation : @raster.Animation) -> Bytes raise @raster.Refused

The animation as an animated WebP.

function pub fn encode_lossless(image : @raster.Image) -> Bytes

The image as a VP8L payload.