Pure-MoonBit image decoder/encoder covering BMP / QOI / TGA / PNG / GIF / JPEG with zero external runtime dependencies. Decoders raise a structured `DecodeError` sub-error type so callers can branch on cause (UnsupportedFormat / TruncatedData / InvalidHeader / InvalidValue / EncodeNotImplemented).
| Field | Supported |
|---|---|
| Byte order | II (little-endian); MM raises InvalidHeader |
| Compression | 1 (none); LZW / Deflate / JPEG-in-TIFF rejected |
| Photometric | 0 (WhiteIsZero), 1 (BlackIsZero), 2 (RGB), 3 (Palette) |
| BitsPerSample | 1 / 2 / 4 / 8 / 16 (uniform across samples) |
| SamplesPerPixel | 1 (greyscale / palette) or 3 (RGB) |
| PlanarConfiguration | 1 (chunky); planar rejected |
| Layout | single strip only |
| Sample format | UINT |
| Variant | When it fires |
|---|---|
| DecodeError::UnsupportedFormat(String) | magic bytes do not match any known format signature |
| DecodeError::TruncatedData(String) | a frame / chunk / scanline ended in the middle of a read |
| DecodeError::InvalidHeader(String) | a header field is out of range or has an unsupported value |
| DecodeError::InvalidValue(String) | a header / pixel-data value was readable but rejected downstream |
| DecodeError::EncodeNotImplemented(String) | encode() was called with a decode-only format |
match fmt {
ImageFormat::BMP => ...
f if f.is_decodable() => ...
}// one-shot auto-detect decoder; raises DecodeError
pub fn decode(data : Bytes) -> Image raise DecodeError
// header-only dimension read (no pixel decode)
pub fn image_dimensions(data : Bytes) -> (Int, Int, ImageFormat) raise DecodeError
// per-format decoders (still raise the lower-level Failure)
pub fn decode_bmp(data : Bytes) -> Image raise Failure
pub fn decode_qoi(data : Bytes) -> Image raise Failure
pub fn decode_tga(data : Bytes) -> Image raise Failure
pub fn decode_png(data : Bytes) -> Image raise Failure
pub fn decode_gif(data : Bytes) -> Image raise Failure
pub fn decode_jpeg(data : Bytes) -> Image raise Failure
// writers (QOI + BMP only); encode() raises DecodeError::EncodeNotImplemented
// for everything else
pub fn encode(image : Image, format : ImageFormat) -> Bytes raise DecodeError
pub fn encode_qoi(image : Image) -> Bytes raise Failure
pub fn encode_bmp(image : Image) -> Bytes raise Failure// decode a JPEG -> Image, resize, re-encode as QOI
let img = @moonbit_image.decode(jpeg_bytes) catch {
err => {
@log.warn("decode failed: \{err}")
abort("give up")
}
}
let half = img.resize_nearest(img.width / 2, img.height / 2)
let qoi = @moonbit_image.encode(half, ImageFormat::QOI)pub suberror DecodeError {
UnsupportedFormat(String)
TruncatedData(String)
InvalidHeader(String)
InvalidValue(String)
EncodeNotImplemented(String)
}fn AnimatedImage::new(frames : Array[Image], delays : Array[Int], width : Int, height : Int, loop_count : Int) -> AnimatedImagepub struct Color {
r : Int
g : Int
b : Int
a : Int
}pub enum ImageFormat {
BMP
QOI
TGA
PNG
GIF
JPEG
ICO
TIFF
}pub enum PixelFormat {
Gray8
GrayA8
RGB8
RGBA8
}Pure-MoonBit image decoder/encoder covering BMP / QOI / TGA / PNG / GIF / JPEG with zero external runtime dependencies. Decoders raise a structured `DecodeError` sub-error type so callers can branch on cause (UnsupportedFormat / TruncatedData / InvalidHeader / InvalidValue / EncodeNotImplemented).