Release Image Tools 0.2.0
Verify / verify (push) Canceled after 0s

This commit is contained in:
2026-09-02 07:56:38 +02:00
parent 83926457b2
commit 79d223c347
36 changed files with 2231 additions and 245 deletions
+23 -9
View File
@@ -6,9 +6,16 @@ Image Tools is a relocatable Vite/React application using the shared Toolbox she
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.
Each preview or export gets its own generation-bound module worker through the
`@add-ideas/toolbox-helpers` worker-job protocol. The caller filters typed
progress by job ID and 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.
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. The crop overlay edits the same normalized rectangle consumed by the pipeline; zoom is view-only CSS state and never enters the recipe.
## Operation order
@@ -24,14 +31,21 @@ The canvas pipeline has one documented order:
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.
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. A separate fflate ZIP step reads at most 128 MiB of those blobs, uses fixed entry dates/collision-free names, includes operation reports and a manifest, and refuses output beyond 160 MiB.
Recipe JSON has an explicit `de.add-ideas.image-tools.recipe.v1` identity. Import validates every normalized crop, rotation, resize and output field before replacing state; unknown output formats cannot enter the processing pipeline through a recipe.
## 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.
Format inspection, checked image limits, geometry, filenames and reports remain
domain modules under `src/image/`. Generic byte-size display, filename safety,
Blob URL leases, single downloads and disposable-worker lifecycle come
from `@add-ideas/toolbox-helpers` 0.2.0.
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.
No third-party image codec is added. The exactly pinned MIT-licensed `fflate`
dependency writes the optional batch container only; it never decodes image
pixels. 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.