nika:image_compose
Media
Tool family from the canonical registry.
invoke
Call this builtin through the invoke verb.
Read this contract
This reference preserves the specification at the revision linked below. Source examples are fragments: their surrounding tasks, inputs and permissions are not supplied here. Consult engine status andnika catalog --tools --json for the installed implementation; a registry declaration is not a runtime qualification.
Usage and behavior
illustration
row), a vertical stack (column). Like
image_fx it is pure pixel work: NO provider, NO network, NO clock, NO
keys, and byte-identical output for identical (input bytes, args) —
the artifact’s sha256 joins the hash-chained trace, re-render IS the
tamper check, and the recipe (contract tag image_compose/v1 · each
input’s sha256 and size · the resolved layout) rides the artifact as a
PNG nika tEXt chunk. The recipe carries no timestamp and no path: the
same bytes composed from another folder are the same file. Identical
bytes already at out: = idempotent skip (skipped_existing).
Geometry (NORMATIVE — for a byte-deterministic builtin the arithmetic IS
the wire contract;
round(a ÷ b) is ⌊(a + ⌊b ÷ 2⌋) ÷ b⌋, never below 1) ·
- the placed size of a
w × hinput in acw × chcell:none→w × h·fit→round(w·ch ÷ h) × chwhenw·ch ≤ h·cw, elsecw × round(h·cw ÷ w)·fill→ the cover box (round(w·ch ÷ h) × chwhenw·ch ≥ h·cw, elsecw × round(h·cw ÷ w)), cropped tocw × chat(⌊(sw − cw) ÷ 2⌋, ⌊(sh − ch) ÷ 2⌋); - scaling is the
image_fxresizeop withfilter: auto(linear light) to the placed box — the same bytes that op produces; - tracks: with
fit/fillevery column iscwwide and every rowchhigh; withnonea column is as wide as its widest image and a row as high as its tallest; - each image is centered in its cell at
(⌊(track_w − pw) ÷ 2⌋, ⌊(track_h − ph) ÷ 2⌋); - the canvas is
2·padding + Σ column widths + gap·(columns − 1)by2·padding + Σ row heights + gap·(rows − 1); - an input’s alpha is composited over
backgroundBEFORE any scaling, per channel⌊(c·a + bg·(255 − a) + 127) ÷ 255⌋in sRGB integers · the artifact is RGB8 (PNG color type 2).
-005) · each input ≤ 16384 per side · the SUM of the
inputs’ pixels ≤ 2^26 · each fit / fill scaled box (the placed size
above, before the fill crop) ≤ 16384 per side and ≤ 2^26 pixels · the
canvas ≤ 16384 per side and ≤ 2^26 pixels — all judged from the PNG
headers and the args BEFORE any decompression or canvas allocation. An
input carries exactly one IHDR, its first chunk (PNG-3): the size the caps
judged is the size decoded, and a second IHDR is -004. The input count
(1..=64) is an argument, -001.
Output · { path, sha256, size_bytes, width, height, format, layout, columns, rows, scale, inputs: [{ path, sha256, width, height }], skipped_existing } — artifact bytes NEVER ride outputs (the disk law).
Authority. The tool grant, permits.fs.read for EVERY input and
permits.fs.write for out:. A static checker judges each literal input
path (or whole bare const: reference) as a read and a literal out: as a
write, before anything runs: a missing read grant is a check-time
NIKA-SEC-004, never a surprise at run, and a read grant an input uses is
a use, never declared-but-unused advice. A templated list or element
defers to the run’s boundary (NIKA-SEC-004 there).
Determinism contract (normative) · no wall-clock · no randomness ·
integer/fixed-point pixel math · identical (input bytes, args) MUST
produce byte-identical artifacts across platforms and releases within a
stdlib major (the recipe carries the stable contract tag
image_compose/v1, never the engine build). An engine that cannot honor
this is not conformant (07-conformance §3). Labels and JPEG input are not
part of v1.
Throws · NIKA-BUILTIN-IMAGE_COMPOSE-001 invalid arguments (unknown key ·
out-of-range value · columns/rows outside grid · cell with
scale: none · a grid smaller than the list · out: not .png ·
validation_error) · -002 an input read failed (tool_error · the
message names the index) · -003 unsupported input format (non-PNG ·
palette · exotic depth/interlace · validation_error) · -004 decode
failed (structural corruption · CRC/Adler mismatch · tool_error) ·
-005 a cap exceeded (security_error · never transient) · -006
artifact save failed (tool_error) — image_fx’s ladder, code for code.
Plus the boundary NIKA-SEC-004 (paths outside permits.fs).
Related concepts
Arguments
Pass the values required by the tool contract.
Permissions
Understand authority before granting effects.
Errors and recovery
Read diagnostics and choose a recovery policy.
Workflow templates
Put the fragment inside a complete workflow.
Contract provenance
Read the pinned specification · Canonical registry. Tool identity:nika:image_compose. Specification revision: 5cd95cd25c0f.
Documentation
Guides, reference contracts and working examples.
Language spec
the nine-key envelope, Apache-2.0. The contract these docs explain.
Engine source
Rust, AGPL-3.0-or-later. Every commit public.
TypeScript SDK
Use one typed lifecycle locally or against authenticated nika serve HTTP.
Editor extension
The editor extension, frozen at 0.120 and not qualified with 0.124: use
nika lsp and the JSON Schema.Homebrew tap
brew install supernovae-st/tap/nika for the latest tagged CLI release.SuperNovae
The Paris studio crafting Nika. 🦋