JPEG XL
Decode JPEG XL and verify exact JPEG transcoding in JavaScript
PureJsImage implements a checked static JPEG XL subset in first-party TypeScript. This workbench runs in a browser worker and keeps local files on your device.
Quick answer
Decode common static JPEG XL with native precision, color, alpha and HDR; inspect progressive stages, iterate timed animation frames and exact Level 10 native layers, preserve source-profile samples, write bounded grouped lossless Level 10 planes, stream lossless or Experimental lossy animation, and reconstruct eligible JPEGs byte for byte.
Use native pipelines when the target can preserve source precision and color. Request display conversion explicitly for 8-bit output. Pixel-lossless encoding preserves samples; exact JPEG transcode preserves eligible original bytes. Use onlyIfSmaller when JPEG output size is a hard requirement. Compression promotion uses 156 procedural cases. The prior real-asset regression set exposed large-photo and screenshot compression limits. Efforts 3/5/7 now search bounded multi-group predictors and entropy coding, with palette and Squeeze candidates at higher effort. Extended frozen-corpus size and quality gates remain unfinished; experimental lossy distance controls quantization without guaranteeing a perceptual score.
Interactive workbench
Encode pixels, inspect JPEG XL, or transcode JPEG
Loading a deterministic JPEG sample…
Decoded preview
Result summary
- Status
- Waiting
Inspection and execution evidence
Waiting for local inspection.
Use the ordinary pixel pipeline
import { createImageLibrary } from 'purejsimage'
import { jpegxlCodec } from 'purejsimage/codecs/jpegxl'
const images = createImageLibrary([jpegxlCodec])
const image = await images.open(input)
const output = await image
.jpegxl({ mode: 'lossless', effort: 7, container: true })
.toUint8Array()The stable encoder accepts native gray8, gray16, rgb8, rgb16, rgba8, and rgba16 input. Native re-encode inherits color and independent alpha precision, structured color and luminance fields. Explicit storage conversion retains valid HDR luminance metadata. Source gray plus alpha becomes RGBA pixels with RGB semantics. Output is deterministic and exact for supported integer samples. See the tested precision and profile examples.
Transcode eligible JPEG coefficients
import {
transcodeJpegToJpegXl,
reconstructJpegFromJpegXl,
} from 'purejsimage/jpegxl'
const result = await transcodeJpegToJpegXl(jpegBytes, {
reconstruction: 'required',
onlyIfSmaller: true,
})
const originalJpeg = await reconstructJpegFromJpegXl(result.data)The default policy requires exact reconstruction and verifies every byte before returning. Use reconstruction: 'prefer' with fallback: 'pixel-lossless' only when preserving decoded pixels is acceptable and preserving the original JPEG file is not required.
Progressive and Range explorer
Open a JPEG XL file or a URL that supports HTTP Range. Native preview stops at the encoded resolution boundary. Progressive mode shows complete stages; viewport mode decodes a selected region. Earlier stages stay visible if a later stage fails.
Choose an input to begin.
Requested source ranges: teal marks first access; orange marks repeated access. HTTP transfer bytes and cache counts appear below. Local-file reads do not use the network.
Managed peak bytes cover session working memory. Source cache and canvas memory are separate. Unknown accounting is reported as null. This explorer limits working memory to 256 MiB and the displayed image to 4 megapixels.
Current limits
The documented static Modular and VarDCT subsets support all eight orientations, structured color, native integer precision, high-depth and float VarDCT output, independent alpha precision, and explicit HDR display conversion. Source metadata and emitted pixel semantics are distinct: gray plus alpha expands to RGBA with RGB semantics. The explicit sequence API adds rational animation timing, frame replay, composition and streamed lossless/lossy writing. Native channel APIs preserve exact unsigned samples through the JPEG XL maximum of 31 bits in Uint32 storage, IEEE binary16 and binary32 bit patterns, grouped shifted extra channels, black channels and matching GRAY/RGB/CMYK ICC profiles. Level 10 native and general forward VarDCT output uses a container with jxll=10; writers choose the minimum valid level from depth, dimensions, pixel count, profile size and channel metadata, and reject conflicting raw or Level 5 requests. Forward VarDCT selects Level 10 automatically for exact Modular alpha above 12 bits and accepts an explicit Level 10 request across its existing integer gray/RGB/RGBA subset. Streamed Level 10 animation uses an unbounded jxlc box instead of buffering the completed output. Explicit finite-range float-to-RGBA16 and profile-defined CMYK-to-RGBA8 conversions preserve supported straight integer alpha, including signaled shifted black and alpha planes, while leaving raw planes available. Floating and associated alpha in these display helpers are rejected. Unshifted native planes can be written across multiple 1024-pixel Modular groups. Shifted native writing remains single-group. Ordinary display supports integer samples through 16 bits and rejects wider integer input before conversion. It also rejects unavailable gray ICC plus alpha expansion, high-depth profile conversion, floating encoded input and non-alpha extra channels. Native extraction is separate from rendering; raw layers reconstruct patch and progressive dependencies; uncommon display layouts remain explicit errors. Experimental forward VarDCT encoding supports integer gray/RGB/RGBA, exact straight alpha with lossy replacement of fully transparent color samples, DCT8 with effort-5/7 Hornuss and rectangular half-block choices, local chroma-from-luma, adaptive quantization, and optional two-pass output. Known-primary sRGB, linear, gamma, and PQ inputs use default intensity targets; HLG, custom chromaticities, premultiplied alpha, larger DCT/AFV strategies, and Gaborish remain unsupported by the forward writer. Residual-scaled edge-preserving restoration is available for opaque standard-sRGB gray/RGB at effort 5/7 and distance 2 or above when most blocks need filtering. Exact JPEG reconstruction requires the checked three-component 8-bit Huffman subset, orientation absent or 1, and absent or independently checked sRGB profile signaling. Native re-encode inherits depths and luminance metadata; storage conversion retains luminance fields, while explicit HDR-to-SDR conversion replaces incompatible signaling. Display-window and LUT re-encode cannot inherit source color meaning. Explicit sessions support embedded previews and selective 8-bit SDR XYB DC/pass output. Other dependencies use declared complete static fallbacks or strict rejection; unavailable native stages are errors.
The pixel encoder retains full input and accounts for owned backing buffers before allocation through maxWorkingBytes, defaulting to maxDecodedBytes (1 GiB by default). It includes candidates, entropy state, writer growth and sections. Forward VarDCT retains compact DC/control planes and reuses group-local AC storage; progressive output reuses quantized candidates across passes; caller input, sink storage and JavaScript object overhead are separate. maxOutputBytes bounds encoded output including metadata, up to 128 MiB. Explicit session DC preview retains compact LF state and restoration bands without full-resolution output. Pass and final VarDCT stages retain full output; common 8-bit sRGB uses bounded restoration bands. High-depth, float and compositing paths retain full working planes. JPEG-derived decode uses compact coefficients and bounded component rows. Grouped Modular retains intersecting bands. ICC and metadata have separate limits. Sequence decoding retains a full canvas, the current layer and up to four references, with cumulative replay-work limits and no decoded sequence cache. Native planar writing emits bounded 1024-pixel group sections and preserves encoded sample grids; shifted native planes remain single-group.
The compression promotion suite contains 156 procedural cases across 12 classes. The separate holdout includes real screenshots, transparent assets and native large photographs, with all results retained. M1 uses 250 eligible COCO JPEGs of at least 224 KiB. M3 uses variants of 100 COCO photographs with explicit resizing and upscaling. The documented 8-bit VarDCT comparison allows maximum error 1 and RMSE 0.55 as an independently justified exception to the original RMSE 0.25 target.
FAQ
What is JPEG XL?
JPEG XL is an image format for lossless and lossy images. It also defines a way to carry JPEG coefficients and reconstruction data.
Can JavaScript decode JXL?
Yes. PureJsImage decodes its checked static JPEG XL subset in first-party TypeScript in Node.js and modern browsers.
What does pixel-lossless mean?
Pixel-lossless output preserves the supported decoded sample values. It does not promise the same source file bytes or metadata layout.
Can PureJsImage reconstruct the original JPEG byte for byte?
Yes, for the documented eligible JPEG subset. Exact mode rebuilds the JPEG from parsed coefficients and reconstruction data, then compares every byte before it succeeds. The checked corpus also reconstructs each output through pinned djxl.
Why can an exact JXL be larger than its source JPEG?
Container and entropy-model overhead can still make small JPEGs grow. Select the size requirement to reject those results.
Which JPEG files are currently eligible?
Eligible files use the checked three-component 8-bit Huffman baseline or progressive subset, supported marker structure, orientation absent or 1, and no ICC or the checked sRGB ICC.
Are Exif orientation and non-sRGB ICC supported by exact transcode?
Non-default Exif orientation and non-sRGB or malformed ICC profiles are rejected because the current JPEG XL codestream writer cannot represent those display semantics correctly.
Does PureJsImage have a general lossy JPEG XL encoder?
An experimental first-party VarDCT encoder is available through explicit lossy mode. The default pixel pipeline stays lossless. Full quality and performance qualification is still in progress.
Does this work in Node.js and browsers?
Yes. The shared codec runs in both. This page performs local work in a browser worker, and Node.js uses the same portable implementation through its platform adapters.