Import with #import "std/image".
Image :: struct { width: s32; height: s32; pixels: Vec(u8); }IndexedImage :: struct { width: s32; height: s32; palette: Vec(u8); indices: Vec(u8); }A palette picture: one palette index per pixel, and RGB palette entries.
NewImage :: (width: s32, height: s32, red: u8, green: u8, blue: u8, alpha: u8) -> ImageA WIDTH by HEIGHT picture filled with one colour, transparent black by default.
ImageValid :: (image: *Image) -> boolWhether the picture has a size and every pixel.
CopyImage :: (image: *Image) -> ImageDropAlpha :: (image: *Image)Every pixel opaque, keeping its colour, as Pillow's convert("RGB") does.
RotateLeft :: (image: *Image) -> ImageThe picture turned a quarter turn counterclockwise, as Pillow's Transpose.ROTATE_90.
RotateRight :: (image: *Image) -> ImageThe picture turned a quarter turn clockwise, as Pillow's Transpose.ROTATE_270 and rotate(-90).
RotateHalf :: (image: *Image) -> ImageThe picture turned upside down, as Pillow's Transpose.ROTATE_180.
FlipLeftRight :: (image: *Image) -> ImageThe picture mirrored left to right, as Pillow's Transpose.FLIP_LEFT_RIGHT.
CropImage :: (image: *Image, left: s32, top: s32, right: s32, bottom: s32) -> ImageThe part from LEFT, TOP up to (not including) RIGHT, BOTTOM, as Pillow's crop: parts outside the picture are transparent black.
AlphaBounds :: (image: *Image) -> (s32, s32, s32, s32)The smallest box holding every pixel with any alpha, as Pillow's getchannel("A").getbbox(): left, top, right, bottom, or all zero.
PasteImage :: (destination: *Image, source: *Image, x: s32, y: s32)Copies SOURCE onto DESTINATION with its top left corner at X, Y, replacing the pixels underneath; parts outside are cut off.
AlphaComposite :: (destination: *Image, source: *Image, x: s32, y: s32, from_x: s32, from_y: s32, width: s32, height: s32)Draws SOURCE over DESTINATION at X, Y as Pillow's Image.alpha_composite.
AlphaCompositeAt :: (destination: *Image, source: *Image, x: float64, y: float64)Draws SOURCE over DESTINATION with its top-left corner at the fractional position X, Y, blending the neighbouring pixels it falls between as a browser canvas's drawImage does. Whole positions draw it unchanged.
Silhouette :: (image: *Image, red: u8, green: u8, blue: u8, alpha: u8)Every pixel takes the colour RED, GREEN, BLUE, its alpha scaled by ALPHA: the picture's shape filled with one colour.
ResizeNearest :: (image: *Image, width: s32, height: s32) -> ImagePillow's Resampling.NEAREST: each pixel copies the source pixel under its centre, positions stepped as Pillow steps them.
ResizeBox :: (image: *Image, width: s32, height: s32) -> ImagePillow's Resampling.BOX: each pixel averages the source pixels it covers.
ResizeLanczos :: (image: *Image, width: s32, height: s32) -> ImagePillow's Resampling.LANCZOS, three lobes.
ResizeBicubic :: (image: *Image, width: s32, height: s32, reducing_gap: float64) -> ImagePillow's RGBA Resampling.BICUBIC. Gap 0 means None; otherwise it must be finite and >= 1. RGBA's premultiplied resize does not use integer reduction, including when every pixel is opaque, just as in Pillow.
ResizeBicubicInto :: (image: *Image, width: s32, height: s32, output: *Image) -> boolFallible Pillow bicubic resize, equivalent to ResizeBicubic's default gap. OUTPUT owns its result and may be reused; it must not alias IMAGE or borrow IMAGE's pixel storage. Failure empties OUTPUT (including dimensions) and releases partial buffers. Null output or identical records fail without mutation. IMAGE and its pixels stay unchanged on success and failure.
Thumbnail :: (image: *Image, max_width: s32, max_height: s32, reducing_gap: float64) -> ImageAn owned RGBA thumbnail, matching Pillow's default bicubic thumbnail. Never enlarges; chooses floor/ceil by aspect error, keeping at least one pixel per axis. Does not rotate/transpose or modify the source. Invalid images/nonpositive bounds return an empty Image. A resize also rejects an invalid reducing_gap; an unchanged thumbnail returns before checking it.
ImageColorBox :: struct { start: s64; count: s64; }A run of colours that one palette entry stands for (QuantizeImage's working state; public only so a vector of them compiles).
QuantizeImage :: (image: *Image, colors: s32, dither: bool) -> IndexedImageThe picture's colours reduced to at most COLORS palette entries by median cut, alpha dropped, with Floyd–Steinberg error diffusion when DITHER. A picture with no more colours than that keeps every one exactly.