JPEG codec support

August 10, 2026 ยท View on GitHub

This document is the capability contract for PureJsImage's first-party JPEG codec. A checked item is implemented and covered by tests, pinned fixtures, or the benchmark suite. An unchecked item is planned and must not be presented as supported until its output is independently validated.

Decode

Common JPEG structure

  • JPEG detection from the start-of-image marker
  • Header-only width, height, bit depth, Adobe/component-ID color-space classification, chroma subsampling, MPF image count, and EXIF orientation inspection without decoding entropy-coded pixels
  • 8-bit baseline sequential DCT with Huffman coding (SOF0)
  • 8-bit progressive DCT with Huffman coding (SOF2)
  • Single-component grayscale images
  • Non-interleaved grayscale scans with non-unit frame sampling factors
  • Three-component YCbCr images
  • 4:4:4, 4:4:0, 4:2:2, 4:2:0, and 4:1:1 chroma sampling with pinned asymmetric-layout compatibility fixtures
  • Image dimensions that do not end on an MCU boundary
  • Per-image quantization and Huffman tables
  • Entropy byte stuffing and restart intervals (DRI / RST0-RST7)
  • Compatible restart recovery in TypeScript and opt-in Rust/WASM by default for out-of-order markers, bounded intervening bytes, and premature scan ends, with explicit strict validation through tolerantDecoding: false
  • Multi-scan progressive DC and AC first-pass and refinement scans
  • Bounded tolerant recovery for partial progressive scans ending at inter-scan DHT, SOS, or EOI boundaries, with strict rejection through tolerantDecoding: false
  • Extended sequential 8-bit JPEG (SOF1)
  • Structured UNSUPPORTED_OPERATION rejection for recognized 12-bit and arithmetic-coded frames
  • Extended sequential 12-bit JPEG (SOF1)
  • Lossless JPEG (SOF3)
  • Arithmetic-coded sequential, progressive, and lossless JPEG
  • Hierarchical JPEG processes
  • Sequential images split into multiple non-progressive component scans
  • Define-number-of-lines (DNL) images whose height is supplied after the frame header
  • AVI1/MJPEG baseline frames that omit DHT segments and use standard luminance/chrominance Huffman table identifiers 0 and 1
  • Abbreviated JPEG or MJPEG frames that depend on omitted nonstandard coding tables supplied outside the individual image

Color and metadata

  • Grayscale-to-RGB output
  • YCbCr-to-RGB output
  • EXIF orientation values 1-8 through explicit autoOrient() processing
  • Four-component CMYK JPEG decode with an explicit Adobe transform marker
  • Adobe YCCK JPEG decode and Adobe color-transform detection
  • Three-component JPEGs explicitly encoded as RGB rather than YCbCr
  • Ordered multi-segment ICC profile assembly and color-managed conversion to sRGB for RGB matrix/TRC and ICC v4 mAB LUT A2B0 profiles plus CMYK lut16 A2B0 profiles
  • Broader ICC transform coverage, including lut8, device-link, gray, and uncommon parametric or sampled profile forms
  • Full EXIF, XMP, IPTC/IIM, Photoshop image-resource, JFIF density, comment, and application-marker exposure
  • Opt-in compatible ICC and EXIF preservation, with metadata stripped by default
  • Bounded-row, chroma-siting-aware bilinear upsampling with horizontal and vertical halo samples across MCU-row boundaries

Compound and HDR JPEG files

  • Decode and pixel-validate the SDR primary image from pinned Apple and self-contained Android-style Ultra HDR gain-map JPEG fixtures without misreading their appended secondary images
  • Header-only MPF image-count inspection; the pinned Apple gain-map fixture reports its two constituent images
  • Ultra HDR / JPEG_R and ISO 21496-1:2025 gain-map discovery, HDR reconstruction, encoding, and preservation
  • Multi-Picture Format (MPF / MPO) secondary-image enumeration and selection for gain maps, depth maps, stereo pairs, bursts, and other auxiliary images
  • Motion Photo XMP and appended-video discovery, extraction, and preservation

Memory and execution

  • Baseline reconstruction in bounded MCU rows without a source-sized RGB or RGBA bitmap
  • Crop-aware RGB emission so pixels outside the requested output region are not materialized
  • Progressive coefficient retention in compact 16-bit planes, followed by bounded-row RGB reconstruction
  • Public crop, resize, auto-orient, JPEG-to-JPEG, and JPEG-to-other-codec pipelines
  • Incremental header and entropy decoding from ImageSource without retaining the complete compressed JPEG input
  • Native 1/2, 1/4, and 1/8 scaled IDCT decode for baseline and progressive JPEGs, including restart-marker and common subsampling paths
  • Decoder-driven resize planning for full-frame downscales; it selects the largest safe denominator that still supplies the requested output dimensions and avoids reconstructing discarded full-resolution MCU samples
  • Restart-marker-assisted region seeking plus skipped IDCT and color work for MCUs outside the requested crop where the file permits it
  • Lossless coefficient-domain rotate, flip, transpose, and MCU-aligned crop without decoding and re-encoding pixels
  • Reduce progressive coefficient memory further where scan dependencies and coefficient ranges permit a smaller representation

Encode

Implemented target

  • First-party 8-bit baseline sequential DCT with Huffman coding (SOF0)
  • JFIF output with three YCbCr components
  • Configurable 4:2:0, 4:2:2, and 4:4:4 output sampling, with 4:2:0 as the photographic default
  • Quality control from 1-100 using scaled luminance and chrominance quantization tables
  • Standard luminance and chrominance Huffman tables for bounded-row baseline output
  • gray8, rgb8, and rgba8 pipeline input
  • Native one-component grayscale output for gray8 input
  • Configurable DRI restart intervals with ordered RST0-RST7 markers and DC predictor resets
  • Deterministic alpha flattening onto white by default or a requested RGB background
  • Streaming top-to-bottom baseline encoding with an 8- or 16-row MCU working buffer rather than a full output frame
  • Refinement-based progressive encoding with fixed four-scan grayscale and six-scan YCbCr scripts backed by compact quantized Int16 coefficient planes
  • Two-pass, scan-specific optimized Huffman tables for progressive DC-first, AC-first, and AC-refinement entropy
  • Edge replication for dimensions that are not multiples of eight
  • Public image.jpeg() and image.encode('jpeg') APIs

Planned for common output

  • Optimized per-image Huffman tables for baseline output without retaining full coefficient planes
  • Faster integer/fixed-point DCT and quantization without changing decoded output beyond defined error bounds
  • Compatible ICC and EXIF metadata writing when explicitly preserved
  • XMP, JFIF density, comment, and application-marker writing or preservation
  • Explicit control over ICC and EXIF stripping versus preservation
  • Custom quantization tables for reproducible advanced workflows
  • CMYK output if real upload or print workflows justify it

Correctness and safety contract

  • Validate marker extents, frame dimensions, component counts, sampling factors, table references, scan progression, and entropy reads
  • Apply configurable input-size, dimension, pixel-count, decoded-byte, compact coefficient, scan-count, restart-index, and ICC limits before large allocations
  • Reject truncated files and unsupported coding processes explicitly
  • Compare baseline grayscale, 4:4:4, 4:2:2, 4:2:0, and restart-marker fixtures against an independent development oracle
  • Compare progressive output pixels against an independent development oracle
  • Compare CMYK and YCCK output against an independent development oracle, and exercise RGB matrix/TRC and CMYK LUT ICC transforms with focused fixtures
  • Pin and pixel-validate libultrahdr ICC and Apple gain-map fixtures plus Web Platform Tests' progressive MozJPEG RGB and YUV browser fixtures
  • Decode encoded output independently and require correct dimensions and pixels before benchmark timing counts
  • Decode progressive encoder output through libjpeg and Chromium, Firefox, and WebKit; require the same final pixels as baseline output from identical coefficients
  • Gate both libjpeg-to-PureJsImage decode and PureJsImage-to-libjpeg encode/decode paths with PSNR floors in CI
  • Measure absolute peak RSS in isolated cold and warm processes for the primary large-JPEG resize workflow
  • Compare 1/2, 1/4, and 1/8 output against the full-resolution resize path and report decoded pixels avoided, wall time, absolute peak RSS, MAE, and PSNR from isolated processes
  • Continue broadening the compatibility corpus with more phone and camera models, image editors, common web upload sources, and a Motion Photo fixture
  • Add checksum-pinned generated Adobe RGB, 4:4:0, 4:1:1, SOF1, sequential multi-scan, and unusual progressive scan fixtures
  • Add structured malformed-marker, entropy, table, restart, sampling, and scan-progression regressions with strict allocation and source-cleanup checks
  • Keep opt-in Rust/WASM baseline decoding at pixel parity, including tolerant restart recovery and bounded TypeScript fallback after setup or midstream failures