Skip to content

std/png ​

Encode and decode PNG images (RFC 2083) in pure Milo: the chunk stream, zlib inflation, and the per-scanline filters. It handles 8-bit grayscale, RGB and RGBA without interlacing, the common web and screenshot case. Palette, gray+alpha, sub-8-bit, 16-bit and Adam7 images are not supported. Decoded images are std/image's Image, the type std/jpeg uses too.

milo
from "std/png" import { Png }

Example ​

milo
// a 2x1 RGB image: one red pixel, one blue
let pixels = "\xff\x00\x00\x00\x00\xff"
let file = Png.encode(pixels, 2, 1, 3)!
let img = Png.decode(file)!
print($"{img.width}x{img.height}")   // 2x1

API reference ​

Png ​

milo
pub struct Png

Png namespace — Png.decode(src) reads a PNG, Png.encode(...) writes one.

Png.decode ​

milo
fn Png.decode(src: &string): Result<Image, string>

Png.encode ​

milo
fn Png.encode(pixels: &string, width: i64, height: i64, channels: i64): Result<string, string>

Functions ​

encodePng ​

milo
pub fn encodePng(pixels: &string, width: i64, height: i64, channels: i64): Result<string, string>

Encode 8-bit grayscale (1 channel), truecolour (3) or truecolour+alpha (4) to a PNG.

Every scanline is written with filter type 0 (None). Filtering exists to make the deflate stream smaller, and the encoder's job here is to be obviously correct rather than small — the filters are the part of PNG that is easy to get subtly wrong, and this is the write side of a decoder that already has to implement all five of them to read other people's files.