faceless-photolib

Migrating: OpenRaster (.ora)

OpenRaster import/export scope, the best-effort/source-preservation policy, the generated blend-mode fidelity table, and a live import demo.

Generated from code

The import-ora package has landed. The blend-mode fidelity table below is generated at build time from @faceless-photolib/import-pipeline's real mapping table (task 5.1) — a mapping change updates this page on the next site rebuild, with no manual doc edit. The import demo at the bottom runs the real worker pipeline on a bundled sample.

Why OpenRaster first

ORA is the closest prior art to this format (see Overview → Positioning) and, per the design, the only export target in v0 — it's trivially producible from the reference renderer and buys immediate GIMP/Krita interop for demos. Import and export are two separate, asymmetric operations; see the scopes below.

Policy

Import here follows the same policy every importer in this format follows — never a fidelity promise:

  • Best-effort, raster-safe subset. An importer maps what it confidently can onto the native document model and is honest about the rest — see History-DAG model for how every import lands as a first-class intent.kind: "external-tool" history node, not a side channel.
  • A fidelity report is data, not prose. Every layer/feature gets a mapped | degraded | dropped verdict plus a human-readable detail — shown to the user in a pre-commit dialog before the import is accepted, per the tasker-ui-site-and-format-docs spec's live-demo requirement. A degraded verdict always fires a warnDegraded beacon in the same call that constructs it — it can never enter a report silently.
  • Source preservation. The original .ora bytes are stored as a content-addressed blob (role: "master") and referenced from the import's history node — you can always get the exact original back and re-import later with a better importer, because nothing about the original is discarded even when the mapped result is lossy.
  • Detection is content-based, never filename-based. ORA is detected by its zip mimetype member (image/openraster), not the .ora extension — a renamed file still imports correctly, and a file with an .ora extension that isn't actually one is never silently mis-imported.

Import scope

Per design D4: stack.xml's layer tree maps to groups and raster layers with name/visibility/opacity/x,y offsets; mergedimage.png becomes a preview-role blob; SVG layers rasterize through the existing image-decode path with a degraded verdict (the source SVG is preserved as its own blob, not discarded).

Export scope

Per design D5, ORA export is a raster-safe projection, not a lossless round-trip: every layer flattens to PNG at document resolution through the reference renderer, stack.xml is emitted with the mappable subset (name/opacity/visibility/offset/blend mode), and mergedimage.png plus a thumbnail come from packages/backend-cpu. The export's fidelity report uses the identical verdict shape as import — it shows what got dropped on the way out, symmetrically.

Blend-mode mapping (generated from import-pipeline)

The ORA↔native blend-mode table lives in @faceless-photolib/import-pipeline (mapOraCompositeOp) — shared by both the importer and exporter, so the same ORA composite-op value always produces the same verdict regardless of which direction it's crossed. This table is rendered from that exact code at build time:

ORA composite-opNative modeVerdict
svg:src-overnormalmapped
svg:multiplymultiplymapped
svg:screenscreenmapped
svg:overlayoverlaymapped
svg:darkendarkenmapped
svg:lightenlightenmapped
svg:color-dodgecolorDodgemapped
svg:color-burncolorBurnmapped
svg:hard-lighthardLightmapped
svg:soft-lightsoftLightmapped
svg:differencedifferencemapped
svg:colorcolormapped
svg:luminosityluminositymapped
svg:huehuemapped
svg:saturationsaturationmapped
svg:plus, svg:dst-in, svg:dst-out, svg:src-atop, svg:dst-atopnormaldegraded

The degraded row isn't a gap to be filled later — those five ORA operators are true Porter-Duff compositing operators (they change which pixels show at all), not per-pixel color-blend functions, so mapping them onto a blend mode would silently change the image rather than just its color math. They degrade to normal by design, never a nearest-match guess.

Try it: run the real import pipeline

The demo below fetches the corpus's ora/import-sample entry (a group, a svg:multiply layer, and one svg:plus layer) via the server proxy and runs it through the same format-worker pipeline the editor uses — the fidelity report you see is the pipeline's actual output.

Run the bundled import-sample.ora (a group, a multiply layer, and one Porter-Duff svg:plus layer) through the real worker pipeline and see exactly what survives. Nothing is committed anywhere.

Corpus samples

Every ORA fixture in the sample corpus — group/isolation cases and the svg:* composite-op matrix — is served through the same /api/samples/<id> proxy every other demo on this site uses; no direct storage URL ever appears in this page. "Open in editor" runs the real import pipeline end to end, fidelity dialog included.

Samples — import-ora
Run checks in Test Lab

Preparing sample list…

Next

Krita · Photoshop · Flat images