png

tape
@profile(t1);
import fs from "fs";
import io from "io";
import png from "png";

var pixels: [65536]u32;

fn main() -> i32 {
    let data: string = fs.read_file("icon.png") or { return 1; };
    let i: png.Info = png.decode_into(data, pixels[0..65536]) or {
        io.println("icon.png: {err}");
        return 2;
    };
    io.println("{i.width} x {i.height}, the first pixel {pixels[0]}");
    return 0;
}

png decodes a PNG file’s bytes into 32-bit words of yours, 0xAARRGGBB and not premultiplied, width x height with no padding: the pixels of a gfx.Surface of format Argb, the same as image.decode gives. It is written in tape over compress, so a program that uses it does not need the image library next to it; use image for the other formats, for interlaced PNGs and for encoding.

FunctionDoes
info(bytes) -> Info or PngErrorThe size, bit depth and colour type, from the header alone
decode_into(bytes, out) -> Info or PngErrorThe pixels into out
decode_argb(bytes, out, &w, &h) -> boolThe same as colorfont’s painter takes a decoder: false for an image it can’t read

Every colour type (grey, RGB, palette, grey with alpha, RGBA) at every depth it allows (1 to 16 bits), all the row filters and transparency (tRNS) are read; 16-bit samples keep their high byte. Errors print as what went wrong: NotPng, Truncated, Corrupt (a damaged chunk or compressed data), Unsupported (an interlaced image), TooLarge (more pixels than out holds). A damaged file is an error, never a crash.

Last modified: