Releases: a-r-d/PureJsImage
Release list
PureJsImage v0.17.0
Added
- Added an explicit optional Rust/WASM WebP accelerator with scalar and SIMD modules for VP8 row
color conversion, VP8L predictor and color transforms, lossless encode transforms, and lossy
RGBA or gray to YUV420 conversion. Measured RGB input keeps the existing paired-row TypeScript
conversion because it is faster end to end. The TypeScript codec still owns RIFF parsing, entropy
coding, limits, metadata, and bounded row orchestration. Module or kernel failures fall back to
the TypeScript path. The pull-request corpus workflow now forces scalar and SIMD WebP runs and
checks exact decode pixels, deterministic encode bytes, and actual kernel use. - Added a pull-request-only Imazen corpus workflow for JPEG, PNG, WebP, TIFF, GIF, and BMP. The
workflow checks out the corpus at a pinned commit, runs every file in an isolated process, fails
on per-file behavior changes, and uploads the generated reports for review. - Added forced scalar and SIMD Imazen lanes for JPEG, PNG, and WebP. Eligible inputs must execute
the selected WASM kernels. JPEG and PNG decode pixels remain exact, deterministic scalar and PNG
encoders require byte parity, and the SIMD JPEG AAN encoder keeps its existing PSNR and size gate.
Changed
- Refreshed the stable-codec, cross-library web-codec, JPEG, PNG, and WebP WASM benchmarks, package
metrics, result index, README charts, website charts, and accelerator benchmark pages after the
current codec and runtime work. - Node orientation and rotation now use lazy chunked memory by default. Pass
{ temporaryFiles: true }as the second argument tocreateImageLibrary()to opt into a lower
process-RSS file spool. The opt-in path probes file creation, writing, reading, and truncation
before consuming image rows. Failed setup or later file writes fall back to memory. The previous
64 MiB Node memory fallback ceiling has been removed; normal image limits still apply. - The optional WebP WASM accelerator now uses four-pixel SIMD for VP8L color transforms, fuses the
common inverse color, predictor, and subtract-green row sequence into one call, and specializes
uniform mode-11 prediction. Seven paired 4000x3000 lossless WebP trials reduced the median from
617.90 ms to 518.50 ms, with exact output and a 2.00% peak RSS reduction. - The optional Rust/WASM JPEG encoder now uses a separable f32 AAN transform, precomputed
reciprocal quantization factors, and four-pixel SIMD RGB and RGBA compositing and color
conversion. Unused SIMD scratch arrays were removed. Seven paired end-to-end trials reduced the
png-to-jpegworkflow median by 24.58% with the output quality, size, and correctness gates
unchanged. - The optional Rust/WASM JPEG decoder now skips the full IDCT for DC-only blocks. Seven paired
end-to-end trials reduced thejpeg-to-pngworkflow median by 5.64% with exact output
correctness and a 0.46% peak RSS reduction. - JPEG WASM exactness now covers DC-only inverse-transform half-integer boundaries and scalar
encoder values immediately below a positive half-integer. The Rust decoder now validates the
end-of-scan marker after its final MCU while still allowing legal bytes after EOI. - Rust/WASM JPEG and PNG builds now reserve a bounded 128 KiB stack, trap on unexpected panics,
and reject out-of-bounds or overlapping JPEG buffers before reading or writing memory. Initial
accelerator memory remains within four WebAssembly pages. - The Imazen corpus command now accepts
--baseline <directory>and exits with an error when a
file changes outcome, completed stage, structured error, diagnostic, child exit code, or signal.
Timing and machine metadata remain outside the comparison.
PureJsImage v0.16.0
Added
- Added the
purejsimage/georaster API with CRS and affine grid metadata, resolution levels,
bands and non-spatial axes, bounded pixel and world views, target-grid comparison, caller-supplied
coordinate transforms, inverse-mapped reprojection, and the existing band math, terrain,
statistics, histogram, and line-profile operations. - Added lazy geo readers for GeoTIFF and COG, GeoZarr v2 and v3, world-file TIFF, JPEG, and PNG,
georeferenced ENVI, Esri ASCII Grid, SRTM HGT, and classic NetCDF CDF-1 and CDF-2 files with
regular rectilinear CF coordinates. The readers preserve native sample values, selected
multidimensional axes, cancellation, source ownership, and bounded region access where the
source format permits it. - Added a generated geo compatibility manifest and deterministic CI benchmarks for remote COG,
sharded and multidimensional GeoZarr, ENVI, classic NetCDF, and identity reprojection. The
benchmark records request, byte, cache, chunk, shard, pixel, timing, and memory evidence while
enforcing selective reads and output correctness. - Added the
/geo/browser demo with deterministic local fixtures, public Kentucky aerial imagery,
a USGS Grand Canyon elevation COG, pan and zoom controls, hillshade, live range telemetry, clear
loading and error states, and copyable examples for the active GeoTIFF or GeoZarr view.
Changed
- The installed-package Geo consumer now runs deterministic range-backed GeoTIFF and
multidimensional GeoZarr workflows through the public Geo, scientific, and tile-runtime entries.
It also checks stable resource identity, cancellation ownership, exact cleanup, reprojection, and
a browser Worker bundle. The Geo architecture guide now documents this application pattern. - GeoTIFF overview levels now derive their affine transform when an overview repeats CRS metadata
without its own model transform. Hillshade reads its required one-pixel source border without
weakening the 196,608-pixel output limit, and geo views preserve exact nodata values and source
level identity. Geo reprojection policies, serialized plans, and result provenance now preserve
caller-supplied full-range int64 and uint64 nodata as canonical decimal strings.
PureJsImage v0.14.0
PureJsImage 0.14.0 adds deterministic, bounded numeric-raster analysis plans and tile executors for band math, normalized difference, linear combinations, subtraction, terrain slope/aspect/hillshade, regional statistics and histograms, line profiles, explicit target-grid resampling, and caller-supplied inverse reprojection.
Plans record raw/scaled value handling, units, nodata, algorithm versions, coordinate-transform identity and accuracy, and explicit tile and memory limits without adding runtime dependencies or full-raster materialization.
The browser convert demo also keeps original and converted images side by side on large screens and includes constrained AVIF output.
PureJsImage v0.12.0
PureJsImage 0.12.0
Added
-
Added a deterministic Cloud Optimized GeoTIFF compatibility corpus, checked compression matrix,
public boundedinspectCog()structural report, explicit compression ID/name errors, and a
simulated-HTTP-range viewport benchmark that asserts overview selection and reports requests,
bytes fetched, cache hits, first decoded tile-block latency, and decoded pixels. -
Added typed GeoTIFF spatial references to ordinary TIFF scientific dataset descriptors and
SubIFD levels, including CRS authority/code and citation, six-parameter pixel-to-model affine,
invertible inverse, model bounds, pixel-is-area/point semantics, scalar or component GDAL nodata,
and JSON-safe source metadata. Region reads remain in raster pixel coordinates, and malformed
optional georeferencing does not block native TIFF pixels. -
Expanded the official common-web (
web-codecs) suite with JPEG→AVIF, JPEG→lossy WebP, AVIF
crop+resize, the Lambda JPEG thumbnail, progressive JPEG resize, and lossless WebP alpha decode.
The published speed and memory SVG charts include those jobs, and the README now shows both
charts. -
Added the explicit
purejsimage/scientific/readers/ome-zarrreader for OME-NGFF 0.4 and 0.5
image multiscales on first-party Zarr v2 and v3 directory stores. Selected planes fetch only
intersecting regular orsharding_indexedchunks through the existing companion resolver; bytes,
gzip, zlib, zstd, crc32c, transpose, shuffle, and Blosc 1 (LZ4/zlib/zstd/memcpy) are implemented;
missing chunks become fill values. Sibling and root NGFF labels become separate datasets with
image-labelcolors; plate wells become one dataset per field. A ZIP archive with root-level
zarr.jsonor.zgroupopens as a single-file store without companions. Partial last chunks,
sharded inner endian, Blosc split streams, and the C-Blosc compressor enumeration are handled.
A pinned IDR 6001240 coarsest-plane slice cross-checks NGFF 0.4 Blosc/LZ4 against 0.5 sharded
Blosc/zstd. The reader also accepts omitted v3chunk_key_encoding, exact integer and hex
fill_values, F-order padded last chunks, numeric OMERO colors, UTF-8 BOM metadata, and
big-endian shard indexes, and rejects overlapping shard payloads.any-axis-pairplanes are
packed into destination row order. Zarr v2fill_value: nulldecodes present chunks and fails
on absent ones instead of inventing zeros; a present zero-byte chunk is malformed; missing
shard inners use only the uint64 all-ones sentinel pair. Directory dataset identity includes
defining metadata plus a session store id; ZIP identity stays the archive source. Chunk lookup
uses a bounded LRU somaxOpenSourcesis not a lifetime visit limit. Clipped last chunks no
longer fail when the nominal chunk exceeds the decode budget; empty optional.zattrs, trailing
dataset slashes, bare one-byte NumPy dtypes,numcodecs.*codec ids, and case-insensitive
NaN/Infinity fills are accepted. bioformats2raw0/,1/, … series roots and a single nested
ZIP store prefix are supported; ambiguous multi-root ZIPs stay rejected. Series discovery also
works without a root.zattrsfile,bioformats2raw.layoutmay be a numeric string, and
seriesCountcounts series groups rather than every collected dataset. ZIP stores named
*.zarr/*.ome.zarrprobe as OME-Zarr, macOS__MACOSX/sidecars no longer make a unique
nested root look ambiguous, a rootlabelslist does not hide bioformats2raw series, and extra
integer series beyondmaxDatasetsraiseLIMIT_EXCEEDED. ZIP probes use name-plus-magic
evidence and do not open the archive. Generic Zarr v2 groups are not detected without NGFF
attributes. Zarr storage fill is recorded aszarrFillrather thannoDataValue; v3 rejects
null and non-numeric integer fills; shard-index codecs must declare endian; nonempty
storage_transformersare unsupported; NGFF axes must be time, then channel or custom, then
2–3 spatial axes; OMERO colors must be six hex digits or 0–0xffffff; and the chunk cache is
bounded bymaxCachedChunkBytes. Pinned IDR slices now include 6001240 sibling labels, an
IDR0010 0.5 plate well, an IDR0001 0.4 plate field, and an IDR0101 translation image. BloscLZ,
Snappy, bitshuffle, tables, RFC-9 zip-comment/jsonFirstrequirements, nonempty storage
transformers, repeated transpose codecs, and writers remain explicit unsupported operations.
ZIP members are limited before decompression; sharded plane reads resolve each shard once;
bioformats2raw.layoutmust be3; and directory calibration cites the resolved metadata
resource id. Plane-session caches stay bounded and layer over the persistent chunk LRU;
a source larger thanmaxCachedChunkBytesis held at most as one transient shard.
Changed
- Speed up first-party AVIF decode after the retained inverse-transform skip: decode equiprobable
bits without a throwaway CDF, skip zero-coefficient dequant, upsample interior 4:2:0 chroma
without edge clips, renormalize the arithmetic coder with integer shifts, clamp YUV bytes with
integer rounding, hoist SGR prefix-row bases, and inline the common 8-bit 4:2:0 convert. Local
avif-fox-resize-jpegfell from 589 ms to 500 ms (−15%) with an exact output hash; neighbor
avif-fox-full-pngimproved 11%. The Imazen AVIF survey stayed 36/36 decoded with maximum RGB
error 2; post-filter, color, high-bit, tile, q-matrix, and common-photo oracles were unchanged. - Speed up first-party AVIF inverse transforms by reusing residual scratch and skipping 1D
transforms on all-zero rows and columns. Localavif-fox-resize-jpegfell from 621 ms to 589 ms
(−5%) with an exact output hash. The Imazen AVIF survey stayed 36/36 decoded with maximum RGB
error 2; post-filter, high-bit, tile, q-matrix, and common-photo oracles were unchanged. - Speed up first-party AVIF loop restoration by specializing the 8-bit SGR box filter, restoring
8-bit SGR/Wiener as unit-width tiles in 8-row bands, and applying interior Wiener 7-tap filters
directly from the CDEF plane. Localavif-fox-resize-jpegfell from 838 ms to 623 ms (−25%) with
an exact output hash; neighboravif-fox-full-pngimproved 18%. High-bit restoration stays on
4-wide 4-row tiles so Int32 prefix squares do not overflow. The Imazen AVIF survey stayed 36/36
decoded with maximum RGB error 2. - Fuse 8-bit AC Huffman prefix decoding into scaled JPEG block decode. Local
jpeg-resize-1200
fell from 543 ms to 511 ms (−7%) with an exact bitstream hash; neighborjpeg-crop-resize
improved 3.9% andnorthstar-photo-pipelineimproved 3.4%. Imazen JPEG stayed 39 pass / 2
unsupported / 167 rejected-safely / 46 accepted. - Speed up JPEG resize-to-encode pipelines by unrolling the scale-2 4×4 IDCT, skipping vertical
chroma bilinear on 4:2:2 (chroma already has full vertical resolution), and unrolling the encoder
DCT. Localjpeg-resize-1200fell from 715 ms to 543 ms (−24%) with an exact bitstream hash;
neighborjpeg-crop-resizeimproved 18%. Imazen JPEG stayed 39 pass / 2 unsupported / 167
rejected-safely / 46 accepted. - Speed up scaled JPEG decode by skipping unused AC store after the last zigzag the reduced IDCT
reads, fusing leftover Huffman bit skips, unrolling the scale-4 2×2 IDCT, stopping restart
indexing once the crop target is passed, and inlining leftover-AC skip on the entropy reader.
Officialnorthstar-photo-pipelinefell from 1181 ms to 802 ms (−32%) on top of the previous
scaled-IDCT work, with an exact bitstream hash. Neighborjpeg-crop-resizeimproved 13.5%;
jpeg-resize-1200kept its exact hash. Imazen JPEG stayed 39 pass / 2 unsupported / 167
rejected-safely / 46 accepted. - Speed up large JPEG crop-then-resize pipelines by snapping unaligned decoder crops to a
containing scale-aligned box so scaled IDCT can run. Officialnorthstar-photo-pipelinefell
from 2857 ms to 1181 ms (−59%). Pixel samples stayed inside the documented ±8 tolerance; the
lossy JPEG bitstream changed as expected. Aligned neighbors kept exact hashes. Imazen JPEG
stayed 39 pass / 2 unsupported / 167 rejected-safely / 46 accepted. - Speed up JPEG-to-PNG conversion by recycling decoder row buffers after encode, specializing
adaptive PNG filter scoring for RGB8, and skipping bilinear luma interpolation when luma is
already full resolution. Officialjpeg-to-pngfell from 552 ms to 444 ms (−20%) with a 6.5%
peak-RSS drop on the recycle path; neighborjpeg-resize-1200improved 4.5%. Output hashes and
the Imazen JPEG/PNG corpora were unchanged. - Fail full official
web-codecsandcompetitorsbenchmark runs when any matched pass/pass wall
median is more than 10% slower than the published headline snapshot. Single-workflow hillclimb
runs are not gated. - Publish web-codec and competitor benchmark charts as SVG instead of rasterizing them to PNG.
- Speed up first-party AVIF decode after the retained restoration gather/prefix work: hoist SGR
prefixes, unroll Wiener and SGR blend, copy interior CDEF windows, reuse inverse-transform
scratch buffers, specialize 4:2:0 chroma upsample, and specialize 8-bit Wiener rounding. Official
avif-fox-resize-jpegfell from 1452 ms to 803 ms (−45%) andavif-fox-full-pngfrom 1573 ms to
987 ms (−37%) on the 2026-08-17 web-codec snapshot, with unchanged output hashes. - Speed up first-party lossless WebP encoding by replacing the shifting LZ77 candidate table with a
ring buffer, recording match tokens once for histogram and bitstream emission, and scoring color
cache sizes in a single scan. Isolated 1200x480 effort-4 encode oftransparent-logo-1200x480
fell from 166 ms to 100 ms with an unchanged bitstream. - Speed up first-party lossy WebP encoding by adding the DC predictor during reconstruction instead
of prefilling each 4x4, and by finalizing RGB8 chroma in the 2x2 write. Isolated 1200x900
quality-80 enc...
PureJsImage v0.11.0
PureJsImage 0.11.0
Added
-
Added the explicit
purejsimage/codecs/webentry with the frozenallWebCodecsJPEG, PNG, WebP,
and AVIF aggregate, plus a correctness-gated common-web benchmark profile with AVIF metadata,
full-decode, resize, conversion, and external Sharp and jSquash comparison rows. The historical
ordinary competitor profile remains unchanged. -
Completed the initial Milestone H interchange and detector set with explicit portable readers
for RPL/RAW, EMSA/MAS, NRRD, MetaImage MHD/MHA, NIfTI-1/2 including bounded.nii.gz, NPY,
NanoMegas BLO, processed Merlin MIB, and rectangular ANG/CTF orientation maps. The readers
preserve native numeric samples and calibration evidence, provide bounded selected reads where
their storage permits, reject recognized unsupported variants, ship as individual package
entries, and pass generated structural, hostile-limit, packed-consumer, size, and real-Chromium
coverage. Pinned RosettaSciIO files independently exercise RPL/RAW, ISO EMSA, BLO, and processed
Merlin MIB without redistributing their GPL binaries. EDAX and Bruker BCF remain the roadmap's
explicit later items. -
Added the public
purejsimage/scientific/readers/ncem-emdreader for the fixture-proven
Berkeley/openNCEM 0.2 subset. It accepts integer or decimal-string versions, discovers numeric
groups below/dataor/signals, preserves exact labeled coordinates and bounded scalar or
array acquisition metadata, and performs selected HDF5 hyperslab reads. Three pinned real
RosettaSciIO application files join generated hostile and independent h5py coverage without
redistributing their GPL binaries; Direct Electron.de5remains explicitly unsupported. -
Added the separate public
purejsimage/scientific/readers/velox-emdE2 image reader with
hierarchy-based probing, bounded per-frame JSON under an aggregate budget, separate detector
datasets and frame axes, native scalar and complex data, preserved positive-half uncentered FFT
storage, and explicit
pruned-spectrum-image errors. Every metadata column is preserved, while calibration-critical
conflicts fall back to index axes with a structured warning. Generated hostile fixtures and
pinned TEM stack, DPC, and FFT files verify the reader without committing the GPL fixture
binaries. Sparse Velox spectra remain gated on the Lab Viewer spectrum surface and explicit
event-decoding contracts. -
Added structured calibration provenance to scientific axes, including validated embedded,
sidecar, derived, and format-default evidence. GSF, FITS, MRC/CCP4, OME-TIFF, and Aperio SVS
readers now identify the exact source resource and stable metadata locator behind each available
physical axis. -
Added the public
createImageCodecScientificReader()fallback adapter and individually
importable PNG, JPEG, WebP, BMP, and JP2 scientific readers. They preserve codec pixels and
component semantics, source identity, cancellation, block release ownership, and explicit reader
registration without linking codecs into the base scientific entry. -
Added
purejsimage/scientific/readers/tiff, a native-precision ordinary TIFF reader with labeled
page axes, incompatible-series separation, SubIFD resolution levels, bounded normalized optional
metadata, native N-channel layouts, and lower probe priority than OME-TIFF and Aperio SVS. -
Added bounded FEI SFEG/Helios and Zeiss SEM TIFF calibration profiles with fixture-backed physical
axes, embedded evidence, normalized acquisition metadata, and non-fatal malformed-tag handling. -
Added a package-private bounded DM3/DM4 tag-tree indexer with checked 32-bit and 64-bit structure,
separate payload byte order, recursive value descriptors, deterministic duplicate-name paths,
lazy image payload spans, and size-limited metadata projection for the upcoming scientific
reader. -
Added the public
purejsimage/scientific/readers/digital-micrographreader for supported DM3/DM4
rank-2 through rank-4 scalar images and volumes, all signed/unsigned 8/16/32-bit and
float32/float64 samples, fixture-proven packed BGRA, calibrated axes and intensity units,
bounded namespaced Gatan metadata, and direct selected-region reads. Rank-1, complex,
undocumented packed, encrypted, and external image content remains explicitly unsupported. -
Added a generated scientific-reader capability section covering every public reader descriptor,
package export, hint, resource model, dataset kind, direct-range boundary, evidence, and fixture
source. Added a pinned, checksum-verified RosettaSciIO DigitalMicrograph compatibility corpus
workflow without redistributing its GPL-licensed fixture binaries in the package repository. -
Added evidence-gated DigitalMicrograph multidimensional semantics: ordinary X/Y/Z volumes,
Gatan-tagged X/Y/energy EELS spectrum images, and C-ordered 4D-STEM exposed logically as
scanX/scanY/kx/ky with direct kx/ky diffraction-plane reads. Ambiguous rank-4 arrays remain
neutral. A pinned small DM4 volume and bounded HTTP-range verification of LiberTEM's 1.19 GB
CC-BY-4.0 Zenodo 4D-STEM fixture cover the new mappings without committing the large file. -
Added honest one-axis scientific datasets with explicit native series-read capabilities, bounded
ScientificSeriesBlockoutput, strict series request normalization, and a bounded row/column
adapter over existing plane readers. Existing plane-only descriptors and readers remain
unchanged. -
Added the public
purejsimage/scientific/readers/tia-serreader for FEI/Thermo TIA SER v528 and
v544 scalar spectra, spectrum images, and image series. It indexes calibrated elements and valid
counts without eager payload reads, preserves incomplete elements as bounded document metadata,
provides direct canonical sample reads, and is verified against pinned real RosettaSciIO files
without redistributing their GPL-licensed binaries. -
Added the public
purejsimage/scientific/readers/tia-emicompanion reader for portable embedded
ObjectInfoXML, numbered SER resource composition, acquisition metadata, stable identities,
and evidence-preserving reciprocal-space reinterpretation. Contradictory SER coordinates remain
authoritative and are reported rather than overwritten. -
Added a package-private HDF5 file and address layer with legal user-block signature discovery,
superblock versions 0 through 3, 2/4/8/16-byte integers, relocation-aware bigint addresses,
lookup3 superblock checksum verification, and a bounded source-identity-aware metadata page
cache. Legacy family, multi-file, and unknown drivers plus modern superblock extensions remain
explicit unsupported boundaries while the object graph is implemented separately. -
Added the first package-private HDF5 object-graph slice with version 1 and 2 object headers,
checksummed continuation chunks, compact hard and soft links, link-info storage descriptors,
bounded legacy symbol-table groups with local heaps and B-tree v1, and configurable
hostile-metadata limits. A revision- and SHA-256-pinned HDF Group fixture verifies the real legacy
group path without adding its binary to the repository. -
Continued the package-private HDF5 object graph with checksummed fractal-heap headers, root direct
and recursive indirect managed blocks, seven-byte managed heap IDs, and type-5 B-tree v2 leaf and
internal nodes for modern dense groups. Generated hostile fixtures cover hard, soft, ASCII, UTF-8,
creation-order, bounds, cycles, ordering, and corruption behavior. A second pinned HDF Group file
verifies a real 40-record dense index and the explicit external-link boundary. Huge and tiny heap
objects, filtered heaps, and the secondary creation-order index remain explicit deferred
variants; bounded graph traversal, attributes, dataset layouts, chunk indexes, required filters,
and exact selected reads are implemented by the later package-private D2-D6 layers. General
public HDF5 reader claims remain intentionally absent. -
Completed the fixture-proven package-private HDF5 D3-D6 substrate: bounded datatypes,
dataspaces, attributes, compact/contiguous/chunked layouts, every required classic and modern
chunk index, raw/Deflate/Shuffle/Fletcher32 filters, exact fill handling, local/HTTP parity, and
cancellable selected dataset blocks. Contiguous rank-2 strided selections now batch many rows
under independent input-span, output, and read-operation caps. -
Added public Nanonis SXM, Igor Binary Wave v5, Digital Surf SUR/PRO, and ISO 5436-2 X3P surface
readers plus a bounded ZIP/ZIP64 container. Committed test-only surface binaries now have a
machine-readable per-file manifest with exact source revision/path/URL, license, attribution,
redistribution rationale, SHA-256, and oracle.
Changed
- Documentation pages keep wide tables, code samples, comparison matrices, and chip navigation
inside named mobile scroll regions. The homepage comparison now leads with a compact six-dimension
summary on narrow screens and keeps the full TIFF matrix in an expandable, prerendered section. - The README now leads with measured whole-slide, scientific explorer, and web codec memory visuals,
and the generated scientific reader block is a family summary that links to the format reference. - Hardened scientific probing and metadata semantics after review: HDF5 dialect probes use exact
eight-byte signature reads and pass the verified user-block offset into dialect opening; shared
HDF5 loads isolate caller cancellation, preserve late-waiter coalescing, coalesce graph accounting,
and cannot repopulate after close; Velox enforces its JSON budget across the complete document;
NIfTI ignoresscl_interwhenscl_slopeis zero, classifies affine columns relative to their
own scale, and rejects non-finite header fields explicitly; and DM, TIA SER, Velox, and NIfTI
omit physical units/evidence when numeric calibration is incomplete while re...
PureJsImage v0.9.0
Added
- Expanded TIFF decoding with unsigned 6-, 10-, 12-, and 14-bit grayscale, 2-, 4-, 10-, 12-,
and 14-bit chunky or planar RGB, native packed horizontal prediction, direct 16-bit output,
and five-sample CMYK plus associated or unassociated alpha while retaining bounded segment
memory. - Added explicit WebP-in-TIFF composition through
createTiffCodec({ embeddedCodecs: [webpCodec] }); the default TIFF codec and root package do
not import or activate WebP automatically. - Added a complete development-only TIFF dependency matrix plus isolated raw full-image and region
benchmark operations with source-read, maximum decoded-block, external-memory, and ArrayBuffer
measurements. - Added a generated evidence-backed TIFF library comparison across the README and documentation,
backed by pinned versions and a 154-file isolated-process conformance run that reports exact
pixels, mismatches, unsupported cases, errors, timeouts, crashes, native scientific rasters, and
malformed-input behavior separately. - Expanded the browser demo from 8 to 38 public examples spanning ECCI scanning electron
microscopy, OME-TIFF microscopy dimensions, FLIM, SPIM, high-content screening, pathology,
scientific JPEG 2000, high-bit-depth AVIF, and additional unusual codec layouts. - Added a published
llms.txtwith a capability-manifest-generated codec map, complete quick API
reference, runtime and safety boundaries, and migration guidance for Jimp, Sharp, image-js,
jSquash, GeoTIFF.js, and UTIF.js; every website footer now links the guide and sitemap. - Added TIFF signed 8-/16-bit and IEEE float16/float32/float64 grayscale and RGB decoding with
native-precision raw pixel blocks, deterministic display ranges, bounded Predictor 2 and
floating Predictor 3 reversal, and browser-compatible display conversion. - Added unsigned 24-/32-/64-bit TIFF grayscale and RGB decoding with canonical
gray32,
rgb32,gray64, andrgb64raw blocks, exact values above JavaScript's safe-integer range,
bounded wide Predictor 2 reversal, and deterministic display conversion without an 8-/16-bit
raw intermediate or per-pixel BigInt arithmetic. - Added bounded TIFF SGILog and SGILog24 decompression with native CIE Y/XYZ float32 pixel
blocks, logarithmic luminance and chroma reconstruction, deterministic CCIR 709 gamma-2
display conversion, exact segment validation, and browser-compatible strip and tile decoding. - Added explicit TIFF top-level frame and reduced-resolution SubIFD selection for Classic TIFF
and BigTIFF, with selected-level metadata, bounded IFD graph traversal, cycle rejection,
alias-safe shared-directory reuse, global directory limits, and no reads from unselected pixel
segments. - Added 16-bit TIFF palette decode with exact full-range ColorMap scaling, plus signed 8-/16-bit
and float16/float32/float64 CMYK display conversion using declared sample ranges or deterministic
full-type defaults, bounded segment output, and independent pixel validation. - Added 8-bit TIFF CIELab conversion from D65-referenced Lab* to sRGB, bounded CMYK
lut16A2B0 ICC-profile conversion with profile precedence over numeric display, and
FillOrder=2normalization for non-fax strips and tiles before predictor reversal without
mutating aliased source buffers. - Added a public TIFF document layer at
purejsimage/tiffwith stable top-level/SubIFD graphs,
absolute IFD offsets and lookup, bounded defensive-copy private metadata reads, cached immutable
typed tags with per-call limits, per-directory display and native raster decoders, deterministic
third-party profile registration with isolated detector failures and ambiguity rejection, and
typed explicitTiffProfile<T>opening. - Added native-precision planar or interleaved N-channel
RasterBlockoutput plus explicit
rasterToPixels()range mapping, so scientific samples no longer require an implicit RGB
interpretation. - Added
purejsimage/scientificOME-TIFF datasets with validated Z/C/T dimensions, channel and
physical-pixel metadata, explicit or implicitTiffDataplane mappings, separate-channel
assembly, and reduced-resolution SubIFD selection. - Added a generic
WholeSlideImagecontract and first-party Aperio SVS profile with bounded
pyramid/associated-image region reads, MPP and objective metadata, reusable JPEG 2000 codestream
composition, and TIFF compression tags 33003/33005. The pinned irreversible Aperio tile is
independently validated against OpenSlide within two 8-bit code values. - Added a separately compiled Leica SCN single-area profile example that imports only published
package entries, with an automated boundary check suitable for independent vendor packages. - Added a dedicated TIFF documentation page covering the complete decode matrix, scientific and
whole-slide APIs, third-party profiles, canonical output, memory model, and unsupported
boundaries; reduced the README TIFF and Zstandard sections to direct documentation links and
refreshed the measured bundle and installed-size tables. - Added a reusable first-party Zstandard decompressor at
purejsimage/compression/zstdwith
explicit output and window bounds, raw/RLE/compressed blocks, Huffman and FSE entropy decoding,
repeated tables and offsets, frame checksums, and structured malformed-input failures. - Added bounded TIFF
Compression=50000strip and tile decoding through the reusable Zstandard
backend, preserving existing predictor, sample, and pixel processing. - Replaced simple uncompressed TIFF output with a canonical Classic little-endian 8-bit RGB/RGBA
encoder using independently Deflate-compressed, horizontally predicted strips, automatic
roughly 128 KiB strip planning, strict extensible strategy options, bounded raw strip scratch,
compatible RGB ICC preservation, and exact ImageMagick/LibTIFF interoperability validation. - Added bounded first-party TIFF LERC2 and LERC-plus-Deflate segment decoding with mask handling,
native numeric sample reconstruction, independently validated byte/float pixels, and structured
rejection of corrupt headers, dimensions, masks, checksums, and codec metadata. - Added first-party GeoTIFF model, coordinate, bounding-box, GeoKey, GDAL metadata, and nodata
helpers over the public TIFF document API, with exact affine and tiepoint semantics. - Added a bounded
HttpRangeSourcewith request coalescing, validator-protected reads, byte-capped
LRU caching, response cancellation, and selective COG-style region access that does not fetch
unrelated tiles. - Expanded structured TIFF output with explicit rows per strip, tiled RGB/RGBA segments, automatic
or explicit BigTIFF selection, multi-page top-level IFD chains, and reduced-resolution SubIFD
pyramids, independently reopened through GeoTIFF.js. - Added a development-only TIFF conformance harness that scores PureJsImage, GeoTIFF.js, UTIF.js,
image-js, and Jimp against independent sharp/ImageMagick RGBA output with isolated memory,
timeout, crash, exact-pixel, and error reporting.
Changed
- Moved OME-TIFF and raster helpers, Aperio SVS, and GeoTIFF profiles out of the root and browser
entries intopurejsimage/scientific,purejsimage/pathology, andpurejsimage/tiff; moved
HttpRangeSourceintopurejsimage/sources/http-rangeso the core bundle does not retain
specialized TIFF workflows or the optional HTTP adapter. - Relabeled TIFF conformance as an unreleased commit-pinned workspace snapshot and made decoded
coverage the compact comparison headline, with exact pixels and failure counts reported
separately.
PureJsImage v0.8.0
Added
- Extended the isolated Imazen codec-corpus harness and independent baselines across JPEG, PNG,
WebP, TIFF, GIF, and BMP, covering complete decode-to-PNG round trips, structured rejection,
timeouts, crashes, memory failures, upstream categories, and format-specific feature groups. - Added an explicitly imported first-party Rust/WASM PNG accelerator for common non-interlaced
8-bit grayscale, RGB, and RGBA scanline decode and encode, retaining native runtime zlib,
bounded-row memory, scalar fallback, and the TypeScript reference for every ineligible workload. - Added a separate
purejsimage-wasmcompetitor benchmark engine and seven-engine speed, memory,
and quality reports so the explicitly registered JPEG/PNG accelerators can be compared directly
with the unchanged default TypeScript package. - Added an explicit optional first-party Rust/WASM baseline JPEG decoder that fuses entropy decode,
IDCT, chroma upsampling, and RGB conversion while preserving bounded MCU-row output, exact
TypeScript parity, lazy warm reuse, and clean fallback for unsupported or unhelpful workloads. - Added optional first-party scalar and SIMD Rust/WASM baseline JPEG encoders with bounded MCU-row
input, JavaScript-owned sink backpressure, RGB/RGBA/grayscale and 4:2:0/4:2:2/4:4:4 parity, explicit
workload selection, plus an ABI-compatible SIMD JPEG decoder artifact with scalar fallback.
Specialized entropy writes, validated-row input reads, chroma sampling, Huffman lookup, and paired
decoder upsampling reduce pinned warm encoder time by 61.7%-66.0% versus TypeScript and pinned warm
decoder time by 58.4%, while retaining the same output contracts and bounded memory. - Added first-party refinement-based progressive JPEG encoding for grayscale and 4:2:0, 4:2:2,
and 4:4:4 YCbCr output, with compact coefficient limits, per-scan restart markers, independent
pixel validation, browser coverage, and isolated runtime/RSS/size benchmarks. - Added jSquash as an isolated WebAssembly competitor using its pinned JPEG, PNG, WebP, and resize
packages, with documented Node WASM initialization, explicit unsupported classifications,
startup/package-footprint measurements, a codec-matched bundle comparison with exact package
versions, validated workflow results, and regenerated charts. - Added premultiplied-RGBA PSNR against independent exact-area references to quality-enabled
competitor workflows, with quality recorded outside timing and peak-RSS sampling, included in
Markdown and JSON reports, and published as a dedicated comparison chart. - Added a fully client-side browser conversion demo with content-based format detection, optional
transforms, honest timing and memory reporting, and an artifact-only GitHub Pages deployment
that keeps its generated all-codec bundle out of repository history.
Changed
- Moved HEIF/HEIC decode to the explicit
purejsimage/codecs/experimental/heicentry, removed it fromallCodecsand
the default browser demo, and documented that MIT grants no third-party HEVC
patent rights. - Documented when native Sharp is the better performance choice and added measured Lambda sizing
guidance: 256 MiB completed every pinned 12-megapixel workflow, but 1024 MiB cut the JPEG-to-WebP
warm operation from 10.6 seconds to 2.5 seconds while peak use remained about 120 MiB.
Fixed
-
Kept the nested packed-declaration smoke test operational during
npm pack --dry-run, so the
documented release gate validates package contents instead of inheriting npm's outer dry-run mode. -
JPEG decoding now treats sampling factors as one for single-component non-interleaved scans,
tolerantly preserves completed progressive coefficients when a partial scan reaches a DHT, SOS,
or EOI boundary, and decodes AVI1/MJPEG baseline frames that omit standard Huffman tables. Strict
progressive decoding continues to reject partial entropy. -
Recognized 12-bit and arithmetic-coded JPEG inputs now fail with
UNSUPPORTED_OPERATION,
separating deliberate codec boundaries from supported-subset failures in the Imazen conformance
baseline. -
TIFF decoding now defers BigTIFF offset validation until an inline value actually needs an
external offset, recognizes legacy LSB-packed LZW streams with late code-width changes, accepts
legacy tile tables in strip tags, bounds padded final YCbCr LZW strips, reconstructs multi-strip
old-style JPEGs with omitted legacy fields, and decodes one-dimensional Group 3 fax rows without
EOL markers. Recognized 64-bit sample layouts remain structured unsupported boundaries. BMP RLE4
now accepts the single encoded padding pixel used for odd-width scanlines while retaining overrun
rejection. -
Animated GIF pixel decode now fails with
UNSUPPORTED_OPERATIONinstead of silently discarding
animation; callers can explicitly request the supported first image withopen(input, { frame: 0 }). -
Baseline JPEG restart recovery now defaults to tolerant decoding for malformed real-world files;
passopen(input, { tolerantDecoding: false })to require strict restart sequencing. Explicit
Rust/WASM decoding now implements the same bounded recovery instead of being skipped. JPEG and
PNG decode accelerator setup or midstream failures now resume through their TypeScript decoders
without duplicate rows. Focused scalar and SIMD PNG regressions keep trailingIENDdata,
full-rangecICP, and ICC v4 RGBmABcolor conversion at parity without silently falling back.
The same corpus-driven work completed those compatibility fixes for the TypeScript reference. -
Removed ambient
Bufferreferences from the Node entry's published declarations so strict
TypeScript consumers can compile the zero-dependency package without installing@types/node. -
Changed the default resize kernel from bilinear to scale-aware Lanczos 3 so ordinary downscales
no longer discard most source samples and alias heavily; strong downscales now use bounded
streaming box pre-shrink before the final Lanczos pass, format-specialized horizontal kernels,
opaque-RGBA handling, and a fixed retained-row ring instead of a map. Bilinear remains available
as an explicit faster, lower-quality option, and benchmark reports identify cross-kernel
comparisons. On the pinned profiles, the 4× PNG resize fell from 1,253 ms to 530 ms and the
10× 100-megapixel downscale fell from 8,455 ms to 2,408 ms. -
Allowed the browser demo to convert the supported primary image from iPhone-style MPF JPEGs while
warning that auxiliary images and gain maps are not preserved; true animated inputs remain blocked. -
Reduced progressive JPEG output with two-pass, scan-specific optimized Huffman tables; the pinned
quality-80 benchmark moved from 3.29% larger than baseline to 7.26% smaller with identical decoded
PSNR. -
Corrected AV1 quantization-matrix coefficient-axis lookup and adjusted matrix
dimensions for 64-point transforms, with q30-q90 YUV and displayed-RGB gates
against independent libaom, dav1d, Sharp, and Chromium decoders. -
Reduced lossless WebP output for screenshot-style pixels with block-adaptive VP8L predictors,
adaptive color-cache codes, and a deeper bounded match search, while retaining exact independent
libwebp pixel validation and documenting the fixed match-table memory cost. -
Fixed progressive JPEG AC refinement after a zero-run-length symbol so common Sharp/libjpeg
output decodes correctly and can be resized and converted to WebP in Node.js and browsers.
PureJsImage v0.7.0
Added
- Completed the common static 8-bit Huffman JPEG reference before optional WASM work: incremental
entropy input, restart-aware region seeking, chroma-aware bilinear upsampling, SOF1 and sequential
multi-scan decode, 4:4:0 and 4:1:1 fixtures, native grayscale and restart-marker output, hostile
input limits, and provider-neutral parity vectors. - Added native 1/2, 1/4, and 1/8 JPEG IDCT output, decoder-driven scale selection for safe
full-frame downscales, baseline/progressive/restart/subsampling regressions, and an isolated
runtime, RSS, avoided-pixel, and output-error benchmark against the full-resolution path. - Added an explicit modern-browser entry with File/Blob, ArrayBuffer, Uint8Array, Blob output,
custom sinks, browser-safe TypeScript declarations, and a browser bundle gate that rejects Node
built-ins across the full codec graph. - Added browser PNG encoding through
CompressionStreamand bounded browser rotation/orientation
storage through OPFS, a lazy 64 MiB chunked-memory fallback, and IndexedDB for larger transforms. - Added HEIF/HEIC EXIF and RGB ICC preservation for conversion workflows, including orientation
normalization, plus structured ICC and nclx color-profile metadata for HEIF and AVIF. - Refreshed the static GitHub Pages documentation with responsive guides, API and codec references,
benchmark tables, memory-model explanations, and clearer capability boundaries. - Documented the progressive JavaScript, optional WASM, and future WebGPU backend roadmap,
including capability probing, workload-based selection, bounded GPU memory rules, runtime
fallback policy, correctness gates, and a staged browser-first delivery plan. - Added a reproducible bundle and deployment-footprint comparison for PureJsImage, Jimp, image-js,
and Sharp, with a matched common codec set and explicit accounting for Sharp's native payload. - Added one machine-readable codec capability manifest that generates README, detailed codec,
website, public JSON, and compatibility-test expectations, with a stale-output CI gate and a
repository agent skill for rolling capabilities out consistently.
Changed
- Made bundle and installed-package size reporting part of the mandatory
npm run checkgate. - Reworked the root README into a shorter human-facing overview with a practical all-codec example,
bundle sizes, codec support and compatibility links, benchmark charts, and direct routes to the
API, benchmark, browser, temporary-storage, specification, and contributor details. - Split Node file, Buffer, zlib, and temporary-file services from the portable codec and pipeline
core while preserving the existing Node API and measured transform performance. - Made Node.js and modern-browser portability an explicit project goal and release requirement.
- Reused a single Node file descriptor across detection, metadata, and execution reads, and avoided
redundant copies when stable sources fill codec regions. - Surfaced the measured 191.8-211.0 MiB JPEG 2000 decode peak and its 512 MiB Lambda-tier guidance
in the README and codec documentation.
Fixed
- Reduced first-party lossless WebP output for graphics by adding predictor and subtract-green
transforms, LZ77 references, and adaptive Huffman trees, with exact Sharp/libwebp pixel checks
and an isolated size and peak-memory benchmark for the documented full-frame encoder state. - Decoded the quantization matrices and block delta-Q syntax used by default Sharp/libaom AVIF
output in the restricted opaque 8-bit YUV 4:2:0 path, with exact q50 and q80 YUV agreement
against both dav1d and libaom while delta loop-filter syntax remains explicitly unsupported. - Restricted SVG recognition to the document's first element so HTML with inline SVG and JSON text
mentioning<svgare no longer misreported as SVG input.
PureJsImage v0.6.0
Added
- Added first-party JPEG 2000 / JP2 decoding for common Part 1 grayscale and RGB still images,
including reversible 5/3 and irreversible 9/7 reconstruction, all five progression orders,
multiple tiles, 1-16-bit unsigned samples, strict container validation, public pipeline
conversion, and checksum-pinned fixtures from independent encoders. - Added public-domain real-photograph JP2 fixtures with exact OpenJPEG oracle hashes, structured
container and codestream corruption regressions, a deterministic JP2 mutation campaign, decoded
allocation-limit tests, and isolated cold/warm RSS gates for the documented full-frame fallback. - Added ordered, composable spatial stages: crop-after-resize, multiple resize stages, clockwise
rotate()with arbitrary-angle bilinear sampling, verticalflip(), and horizontalflop(). - Added opt-in
keepExif()andkeepIcc()pipeline operations with JPEG, PNG, and WebP metadata
round trips, TIFF ICC round trips, orientation normalization after pixel reorientation, and
explicit errors for unsupported preservation combinations. - Added a transform-to-JPEG benchmark profile covering quarter-turn and arbitrary rotation,
crop-after-resize with a second resize, and combined flip/flop workflows, with isolated timing,
peak RSS, dimensions, pinned output-pixel validation, and an equivalent-workflow Jimp comparison. - Added a cross-codec transform contract that runs the full ordered transform chain from every
supported decoder through JPEG output, plus focused arbitrary-rotation coverage for grayscale,
RGB, and RGBA sample formats. - Added a contributor guide covering tests, benchmarks, modular feature design, documentation,
changelog entries, AI-assisted changes, MIT licensing, and conflict-free pull requests tomain. - Added a repository release skill with explicit authority, validation, packaging, publishing,
provenance, and post-release consistency gates. - Added a private vulnerability disclosure policy that defines the dependency-free runtime boundary
while keeping CI, build, credential, and published-artifact supply-chain risks in scope. - Added weekly and change-triggered CodeQL analysis for JavaScript and TypeScript using the extended
security query suite. - Added runtime validation for custom
ImageSourcereads, normalizing short, oversized, detached,
and rejected reads into contextualImageErrorresults before codec parsing. - Added a release-gated deterministic corruption campaign with hundreds of bit flips across a
committed benchmark seed for every codec, saved raw-exception reproducers, and a checked-in
regression corpus that automatically turns promoted crashes into permanent tests.
Changed
- Kept arbitrary-angle rotation memory bounded with a temporary 32x32 tile spool and small
destination blocks, without per-pixel promises or temporary sample arrays.
PureJsImage v0.5.0
Added
- Added first-party ICO decoding with validated multi-image selection,
zero-copy embedded PNG entries, common 1/4/8/16/24/32-bit DIB layouts,
one-bit AND masks, partial alpha, and the Windows-compatible legacy
all-zero-alpha fallback. - Added a committed, checksum-pinned ICO corpus plus correctness-gated isolated
benchmarks for metadata, embedded PNG and DIB decoding, masks, alpha, resize,
PNG output, and JPEG output. - Expanded first-party TIFF decoding with BigTIFF 64-bit IFDs and offsets,
padded tiled layouts, 16-bit integer channels, CMYK and subsampled YCbCr
conversion, CCITT Modified Huffman and Group 3 fax, and old/new JPEG-in-TIFF.