an.stage.raster#
Raster art: what a PNG, JPEG or WebP is, read from its header (an#211).
Every piece of art the cutout renderer drew was SVG, and the size probe said
so: svg_raster_size parses its input as XML, so a PNG
plate died in the compiler with ParseError: not well-formed (invalid token):
line 1, column 0 — the error a user sees for “I gave it a picture”. Art carved
out of footage, a scanned drawing, a photographed paper cut-out: those are
raster, and tracing them to SVG throws away the shading that made them worth
carving.
PixiJS loads PNG, JPEG and WebP natively (its loadTextures parser, chosen by
the file’s extension), so the renderer needed nothing new. What the COMPILER
needed was three answers it previously got only from an SVG:
how big is it —
image_size(), read from the header (no decode, no dependency: the four formats state their pixel size in the first few dozen bytes, and a header parse is the same cost as the SVG probe it sits beside);what size does this art draw at, whatever it is —
art_size(), the one probe the compiler, the fidelity check andan validatecall;what exactly is it —
content_digest(), because a raster texture is addressed by its bytes: a re-carved part is a different texture (the runtime’s loader ignores a re-added alias on hot reload, an#155) and a different compiled contract, so the contract hash covers the pixels it will draw.
EXIF orientation (an#218). A JPEG whose EXIF says “rotate 90°” (a phone
photo) is decoded upright by Chromium, so its box is the stored size
transposed: image_size() reads the orientation tag and swaps width and
height for the four orientations that turn the picture a quarter (5-8).
Why a raster part is never recoloured. A StylePack recolours SVG art by
rewriting the literal colours its descriptor tags (colour_roles). A raster
has no literals — its colours are pixels, and inferring a role from a pixel is
exactly what caused an#99’s wrong-tone lid — so it renders as drawn, and the
compiler says so once.
>>> is_raster("parts/head.png"), is_raster("parts/head.svg")
(True, False)
Module Attributes
The raster formats a plate or a part may be, by file suffix. |
Functions
|
The size a piece of art rasterises at, whatever format it is. |
|
The hex sha256 of a file's bytes, cached by (path, mtime, size). |
|
Whether the image can be transparent anywhere; |
|
|
|
Whether |
|
The file path a (possibly versioned) texture |
|
|
Exceptions
A file named as raster art whose header this module cannot read. |
- an.stage.raster.RASTER_SUFFIXES: tuple[str, ...] = ('.png', '.jpg', '.jpeg', '.webp')#
The raster formats a plate or a part may be, by file suffix. PixiJS 7’s
loadTexturespicks its parser by extension and accepts exactly these (plus AVIF, left out because Chromium’s AVIF decode is the one of the four whose output is not specified bit-exactly and the render is a contract).
- exception an.stage.raster.RasterFormatError[source]#
Bases:
ValueErrorA file named as raster art whose header this module cannot read.
A
ValueError, so the compiler’s size probe treats it exactly like a malformed SVG: the art is declared (and fails loudly at load) rather than silently dropped.
- an.stage.raster.art_size(source)[source]#
The size a piece of art rasterises at, whatever format it is.
SVG: its declared
width/height(else its viewBox), as the browser does —svg_raster_size(). Raster: its pixel size. The ONE probe the compiler, the fidelity check andan validateshare, so none of them can size a PNG as if it were XML again.
- an.stage.raster.content_digest(path)[source]#
The hex sha256 of a file’s bytes, cached by (path, mtime, size).
The ENCODED bytes, not the pixels: re-saving the same image with another encoder changes the digest (and so the alias and the contract hash) — which is the conservative direction for a contract.
Cached because a rig registers every attachment of every slot and a scene compiles each shot separately; keyed on the stat so an edited file is re-read, which is what makes the digest safe to put in a texture alias.
- Return type:
- an.stage.raster.has_alpha(source)[source]#
Whether the image can be transparent anywhere;
Noneif unknown.A PNG says so in its header (colour type 4 or 6) or with a
tRNSchunk; a JPEG never can; a WebP says so in itsVP8Xflags or by being lossless with an alpha bit. A cut-out part without alpha is a rectangle — the whole canvas draws, background and all — which is whatan character validateuses this for.
- an.stage.raster.image_size(source)[source]#
(width, height)in pixels of a PNG, JPEG or WebP, from its header.sourceis a path or the file’s bytes.>>> import struct, zlib >>> ihdr = struct.pack(">IIBBBBB", 3, 2, 8, 6, 0, 0, 0) >>> png = (b"\x89PNG\r\n\x1a\n" + struct.pack(">I", 13) + b"IHDR" + ihdr ... + struct.pack(">I", zlib.crc32(b"IHDR" + ihdr))) >>> image_size(png) (3.0, 2.0)
- an.stage.raster.is_raster(src)[source]#
Whether
srcnames raster art, by its suffix (case-insensitive).- Return type:
>>> is_raster("plates/Street.JPG") True >>> is_raster("data:image/svg+xml;base64,AAAA") False