paged.image — raster
The raster-image plugin — a Rust/WASM pipeline of GPU kernels with PSD round-trip, dual processing engines, color management, and in-editor ingest into the engine's image scene layer.
In short paged.image is a raster-processing subsystem in Rust/WASM —
GPU-executed adjustment kernels, two processing engines, color management, and
byte-faithful PSD/PSB round-trip ("paged never destroys a PSD"). It's wired into
the editor: place → ingest → GPU adjust → in-frame composite.
What it does
- A library of GPU compute kernels (adjustments, transforms, blurs) with scalar reference twins used only in tests.
- Two engines — a demand-driven streaming pipeline and a persistent tiled buffer.
- PSD/PSB parsing + mutation + preservation-safe round-trip; hybrid color management.
- In-editor ingest: placed-asset bytes → decode → GPU adjust → scene-layer composite → tiles.
How it's built
A Cargo workspace (image-core, image-kernels, image-gpu, image-pipeline,
image-psd, image-cms, image-codecs, image-js) plus a TS bundle. A
registry-driven coverage gate requires every kernel to have a test.
Capability state
● shipped & verified · ◍ shipped, untested · ◐ partial · ✗ failing · · planned
Plugin · image 61 features · 72% green
| Feature | Shell | API | Image |
|---|---|---|---|
A sampled .abr tip paints through the existing stroke accumulatorimage.abr.engine-bridge | ◐ | ||
.abr brush-preset reader over a new PSD descriptor readerimage.abr.reader | ◐ | ||
The .abr regression gate, split into the two lanes its roles can runimage.abr.regression-gate | ◐ | ||
Per-channel statistics, from the same buffer as the histogramimage.channels.readout | ◐ | ||
Load a channel as the selection (luminosity masking)image.channels.to-selection | ● | ||
CMS display lane — qcms RGB↔RGB (the exact build core ships, page/editor agree)image.cms.display | ◐ | ||
CMS behind the swappable CmsEngine seam (D-11: hybrid)image.cms.engine | ◐ | ||
CMS rung 1 — the RGB display transform at decodeimage.cms.ingest-transform | ◐ | ||
CMS print lane — moxcms per-intent RGB↔RGB + CMYK8→RGBA8 ingestimage.cms.print | ◐ | ||
AVIF / JXL / camera-RAW / HEIC — codec verdicts (deferred + explicit non-goals)image.codec.avif | · | ||
EXIF/TIFF read — orientation + DPI + color-space tag, auto-orient at ingestimage.codec.exif | ● | ||
Codec adapter contract (ImageSource/ImageTarget over sans-IO ByteSource) + PNG + rawimage.codec.traits | ● | ||
Conformance harness — scalar references, gpu↔ref parity, fixture corpusimage.conformance.harness | ◐ | ||
Panel + chain integration of the new adjustments and generatorsimage.editor.adjust-breadth | ◍ | ||
Auto-enhance — gray-world WB + percentile auto-levels params from the panel histogramimage.editor.auto-enhance | ● | ||
Photoshop .abr brush libraries load and set the brushimage.editor.brush-presets | ◐ | ||
Clone stamp — the brush with a sampled paint layerimage.editor.clone-stamp | ● | ||
Content-aware fill — coarse-to-fine exemplar inpaintingimage.editor.content-aware-fill | ◍ | ||
Editor crop + straighten tool — host-agnostic crop machine over the geom.crop windowimage.editor.crop | ◍ | ||
Crop straighten commits (arbitrary-angle rotation resample)image.editor.crop-straighten | ◍ | ||
Editor levels/curves/white-balance panel — histogram view + adjust kernelsimage.editor.curves | ◐ | ||
K-3 decode worker pool — off-main-thread ingest decode (host.workers consumer)image.editor.decode-pool | ◐ | ||
Filters — blur / unsharp / hue-rotate / invert in the adjustments panelimage.editor.filters | ● | ||
Healing brush — a clone tone-matched in the gradient domainimage.editor.healing-brush | ● | ||
History panel over the tile journalimage.editor.history-panel | ◍ | ||
M4 editor enablement — C-5 placed bytes → decode → adjust → C-1 Stage-A in-frame compositeimage.editor.ingest | ◐ | ||
Pixel-layer stack with a compose.* foldimage.editor.layers | ◐ | ||
Brush / Pencil / Eraser — the raster paint laneimage.editor.paint | ◍ | ◐ | |
Raster type — shaped glyphs painted into a layerimage.editor.raster-type | ◐ | ||
Resample — resize the working image through the registered kernelsimage.editor.resample | ● | ||
C-6 tile provider for placed images (host.images.claimImageResource, v44; honest level-0 subset)image.editor.tile-provider | ◐ | ||
Bounded COW tile journal — undo/redo for pixel editsimage.editor.undo-journal | ◐ | ||
Engine B — persistent buffer graph (invalidation, mip-aware eval, Gestures/Operations)image.graph.engine-b | ◐ | ||
16-bit PSD sources open, reduced to 8 and reportedimage.io.depth-16bit-ingest | ◐ | ||
Save-back — adjusted composite to PSD / PNG / JPEGimage.io.save-back | ◍ | ◐ | |
Kernel breadth — 24 new point/compose/gen kernels (73 → 97)image.kernel.breadth-2026-08 | ◍ | ||
T0 generated kernel families (arith/relational/boolean/cast/band/minmax/linear)image.kernel.family-t0 | ◐ | ||
T1 crown-jewel kernels (conv/resample/compose — handwritten WGSL modules, ABI v1.1)image.kernel.family-t1 | ◐ | ||
T2 editor-bearing kernels (adjust/geom/generators)image.kernel.family-t2 | ◐ | ||
T3 breadth kernels (morphology, rank/median, distance transform)image.kernel.family-t3 | ◐ | ||
1D and 3D LUT sampler classesimage.kernel.lut-samplers | ◐ | ||
General backward-map warpimage.kernel.warp-backward | ◐ | ||
Frozen WGSL kernel ABI v1 (4 bind groups, 16×16, mask-mixed pointwise)image.kernel.wgsl-abi | ● | ||
Clipping layers — an adjustment confined to the layer beneathimage.layers.clipping | ◍ | ||
The layer fold keeps adjustment layers in f16image.layers.f16-fold | ◍ | ||
Layer groups — pass-through and isolated, nesting up to eightimage.layers.groups | ◍ | ||
A host path becomes the selectionimage.paths.path-to-selection | ● | ||
A raster selection becomes a real vector pathimage.paths.selection-to-path | ◐ | ||
Engine A async sinks — to_buffer_async/to_encoder_async (the wasm32/WebGPU readback lane)image.pipeline.async-sink | ● | ||
Engine A — demand-driven streaming pipeline skeletonimage.pipeline.engine-a-skeleton | ● | ||
paged.image bundle (media.paged.image) — manifest + activate + panelimage.plugin.bundle-manifest | ◐ | ||
PSD structural session — layer list/edit/save reach the editorimage.psd.editor-doors | ◍ | ||
PSD import populates the layer stack (declines rather than approximates)image.psd.layer-import | ◐ | ||
PSD mutatable — edits re-encode through the preservation writerimage.psd.mutatable | ◐ | ||
PSD rendered tier — channel decode + flatten render oracleimage.psd.rendered | ◐ | ||
PSD/PSB structural parse + preservation-invariant writerimage.psd.roundtrip | ◐ | ||
Reductions — histogram + min/max/mean statisticsimage.reduce.statistics | ◐ | ||
Residency Tier 0/1 hardening under working-set pressureimage.residency.tier01 | ● | ||
Selection-mask plumbing — the §6.1 mask surfaced end-to-endimage.selection.mask | ● | ||
Selection system — marquee/ellipse/lasso/wand over the mask ABIimage.selection.mask-tools | ◍ | ● | |
Selection coverage threaded through the GPU adjust chainimage.selection.masked-pipeline | ● |
Recent activity
- 2026-08-19ci: bypass the Azure apt mirror too8b6e844
- 2026-08-19ci: bound the apt call, and skip it when brotli is already there2af0ab2
- 2026-08-19corpus: packs moved to vendor/envatofa748c2
- 2026-08-19chore: adopt the 100 MB app-wide wasm budget9ff5b93
- 2026-08-19image: decode a JPEG we did not write — including five real CMYK ones64dcd31
- 2026-08-19image: parse Photoshop files a designer actually saved — and they're CMYK35f76b2
- 2026-08-18image: clone and heal get their own glyphs (0.1.0-canary.14, audit U-icons)f9529ee
- 2026-08-17test: first wasm-EXECUTION lane — real kernels run through the committed artifact in CIc814fa9
paged.web — HTML/CSS
The web-content plugin — author HTML/CSS as a content type, with a sandboxed preview and on-canvas rendering via a Blitz/WASM lowering to the engine's scene layer.
paged.sheet — spreadsheets
The spreadsheet plugin — a Rust/WASM calc engine with spill, structured tables, charts, and XLSX round-trip, lowered to native print-grade tables and editable in-frame.