Files
image-tools/public/docs/ARCHITECTURE.md
T
2026-09-01 02:47:11 +02:00

3.4 KiB
Raw Permalink Blame History

Architecture

Image Tools is a relocatable Vite/React application using the shared Toolbox shell. It has no server component, account, database, telemetry or remote processing API.

Trust boundary and lifecycle

Every selected File is untrusted. src/image/headers.ts reads a metadata window of at most the first 1 MiB with Blob.slice() and performs checked-offset parsing for JPEG markers, PNG chunks and WebP RIFF chunks. PNG and WebP receive an additional structural pass that reads only eight-byte chunk headers, skips payloads by checked offset, stops at image data, and refuses more than 4,096 pre-image chunks. This prevents APNG or animated-WebP control chunks hidden behind a large ancillary payload from bypassing static-only enforcement. Inspection establishes dimensions, recognized animation/multi-picture state, EXIF orientation and a bounded metadata inventory. The image is not given to a browser decoder until source, dimension, pixel and estimated-memory policies pass.

Each preview or export gets its own generation-bound module worker. The caller terminates the worker on replacement, cancellation, unmount or the 120-second deadline, so a stale result cannot replace current state. Files are structured-cloned to the worker; results return as Blob objects. Browsers without worker OffscreenCanvas use the same pure pipeline on the main thread and report missing capabilities instead of substituting a remote service.

Object URLs are scoped to React lifecycles and revoked on replacement/unmount. Source files are never mutated. Downloads happen only after an explicit user action.

Operation order

The canvas pipeline has one documented order:

  1. Decode with createImageBitmap(..., { imageOrientation: "none" }).
  2. Normalize EXIF orientation 18 into visible pixel coordinates.
  3. Apply the normalized crop rectangle.
  4. Apply the selected quarter-turn and flips around the image centre.
  5. Apply fit, centre-cropped fill, exact resize, or keep the transformed size.
  6. Composite transparency over the selected background for JPEG only.
  7. Encode with the browser's PNG, JPEG or WebP canvas encoder.

The returned MIME type must exactly equal the requested type. A browser that substitutes PNG for an unsupported encoder produces an error and no misleading filename.

Intermediate canvases are released as soon as their next stage is drawn. The conservative preflight estimate allows twelve live bytes per source pixel, covers three RGBA-sized surfaces, and rejects sources above 40 megapixels or 512 MiB estimated working memory. Preview output is capped to a 1,600-pixel edge, while reports retain intended export dimensions. Batch execution is sequential and keeps at most 256 MiB of completed output blobs.

Domain boundaries

Format inspection, checked limits, geometry, filenames, reports, downloads and processor RPC are separate modules under src/image/. These are deliberately shaped for later replacement with @add-ideas/toolbox-helpers primitives. The Helpers 0.1 package was not yet published while this slice was implemented, so Image Tools does not carry an unresolved dependency.

No third-party codec or helper runtime dependency is added in v0.1. Native codecs avoid a large WASM/source-identity release burden, at the cost of explicitly documented browser-dependent encoding and colour-management behaviour. A future controlled codec adapter can implement the same processing request/result contract without changing the UI model.