Skip to content

std.image

RGBA images held in one owned array of pixels, and the files that hold them: PNG, which every viewer opens, and the plain PPM. A pixel is a u32 written 0xRRGGBBAA, so a colour reads as the hex a designer writes, and 0xff8800ff is opaque orange. Pixels run in rows, top row first: (x, y) is px[y * w + x], and n is w * h. Cost: new allocates the pixels, the encoders append to a Vec and allocate as it grows, and fill and shade run as parallel regions once an image passes the lane pool's cutoff.

pub struct Image { w:usize; h:usize; n:usize; px:Buf[u32][n]; }

// A w by h image of transparent black. An image has at least one pixel, and w * h is checked, so an empty or
// unaddressable size traps here instead of writing a file no reader accepts.
pub fn new(w:usize, h:usize) -> std.image.Image  // effects: alloc, free, local_read, trap, zero_init

pub fn rgba(r:u8, g:u8, b:u8, a:u8) -> u32  // effects: trap
pub fn red(c:u32) -> u8  // effects: trap
pub fn green(c:u32) -> u8  // effects: trap
pub fn blue(c:u32) -> u8  // effects: trap
pub fn alpha(c:u32) -> u8  // effects: trap

// The pixel at (x, y). A column past the width traps like an index past the end, instead of reading the row below.
pub fn get(img:ro<std.image.Image>, x:usize, y:usize) -> u32  // effects: read:img, trap

pub fn set(img:rw<std.image.Image>, x:usize, y:usize, c:u32)  // effects: read:img, trap, write:img

// Every pixel `c`, as a parallel region.
pub fn fill(img:rw<std.image.Image>, c:u32)  // effects: par:host, read:img, trap, write:img

// Every pixel from `f(x, y)`, as a parallel region: `f` may read what it captured and write nothing.
// effects: indirect_call, lane:f, par:host, read:img, trap, write:img
pub fn shade(img:rw<std.image.Image>, f:ro<fn(usize, usize) -> u32>)

// How many pixels differ; images of different sizes differ everywhere.
pub fn differ(a:ro<std.image.Image>, b:ro<std.image.Image>) -> usize  // effects: read:a, read:b, trap

// The bytes PNG compresses: each row is a filter byte of 0 (none) and then its pixels as R, G, B, A.
// effects: alloc, free, local_write, read:img, trap, zero_init
pub fn scanlines(img:ro<std.image.Image>) -> std.vec.Vec[u8]

// The PNG file of the image: 8-bit RGBA, no interlace, and a zlib stream of stored blocks, so no library and no
// compression. `packed` wraps a stream from std.zlib instead when the size of the file matters.
// effects: alloc, ffi_precondition, free, local_read, local_write, read:img, read:out, stack_storage, trap, write:out,
// zero_init
pub fn png(img:ro<std.image.Image>, out:rw<std.vec.Vec[u8]>)

// The PNG file of a w by h RGBA image whose scanlines `zstream` holds as a zlib stream.
// effects: alloc, ffi_precondition, free, local_read, local_write, read:out, read:zstream, stack_storage, trap,
// write:out, zero_init
pub fn packed(w:usize, h:usize, n:usize, zstream:ro<u8>[n]@host, out:rw<std.vec.Vec[u8]>)

// Write the PNG of `img` to `path`.
// effects: alloc, diverge, ffi:__errno_location, ffi:close, ffi:open, ffi:write, ffi_precondition, free, io,
// local_read, local_write, mmio, read:img, read:path, stack_storage, trap, zero_init
pub fn save_png(img:ro<std.image.Image>, n:usize, path:ro<u8>[n]@host) -> std.core.Result[usize, std.io.IoError]

// The binary PPM of the image: a short header and then R, G, B per pixel; alpha is dropped.
// effects: alloc, diverge, ffi_precondition, free, local_read, local_write, read:img, read:out, stack_storage, trap,
// write:out, zero_init
pub fn ppm(img:ro<std.image.Image>, out:rw<std.vec.Vec[u8]>)

A generic function's effects are what it may do for any arguments within its bounds, besides what their own trait members do.