Skip to content

Comparison with other tools

YadeWira edited this page Jun 10, 2026 · 2 revisions

Comparison with other tools

How packJPG stacks up against the other lossless JPEG recompressors and adjacent codecs. Numbers below are measured on a representative 6-file / ~3.7 MB JPEG corpus; use them as ballpark — your mileage will vary by content.


Quick verdict

Tool Ratio vs packJPG Decode speed Status
packJPG v4.0e reference (-21 % vs raw JPEG) reference active LTS
Brunsli -1 to -2 % (worse) 2-3× faster actively maintained (Google)
Lepton ≈ identical comparable archived 2023 (Dropbox)
JXL --lossless_jpeg +4.27 % (worse) n/a (different format) actively maintained (libjxl)

Short answer: packJPG is on the Pareto frontier for ratio. If you need maximum compression and the format-lock-in is acceptable, packJPG is the right tool. If you need fast streaming decode, Brunsli is worth the small ratio cost.


Detailed: ratio comparison

Measured on a 6-file 3.76 MB corpus of mixed natural-photo JPEGs:

File Original (.jpg) packJPG v4.0c (.pjg) cjxl --lossless_jpeg=1 -e 9 jxl/pjg ratio
0028B2CCB 438,466 292,697 309,278 105.66 %
03BBDEEFD 733,040 625,361 651,808 104.23 %
042888CB3 509,183 394,037 411,868 104.53 %
042B9B813 516,642 411,133 427,736 104.04 %
06FDB6EDE 325,339 257,455 263,799 102.46 %
0D5362BB7 1,241,507 1,059,680 1,105,625 104.34 %
TOTAL 3,764,177 3,040,363 (80.77 %) 3,170,114 (84.22 %) +4.27 %

JXL's lossless-JPEG mode targets ~20 % off baseline; packJPG hits ~19 % on the same files but with a more aggressive entropy coder, netting it ahead by ~4 % on this corpus. JXL -e 10 (max effort) is 0.1 % worse than -e 9 — so the gap isn't a tuning artifact.


How each tool works (TL;DR)

packJPG

  • Entropy coder: custom binary arithmetic coder with PPM order-2 context model.
  • Transforms: strips Huffman, separates DC from AC, splits AC by zigzag position, predicts DC from neighbours (averaged + diagonal-variance), Lakhani edge predictor for AC.
  • Cross-component: v4.0+ uses Y's bit-length as an extra context for Cb/Cr in 4:4:4 sub-formats.
  • Format: custom .pjg, version byte + sub-markers.

Brunsli

  • Entropy coder: rANS with 18-symbol alphabet, 10-bit precision tables.
  • Transforms: similar coefficient repacking to packJPG.
  • Strength: decode speed (single-state rANS is ~3-5× faster than binary arithmetic).
  • Trade-off: fixed alphabet limit forces multi-stage encoding for symbols > 18, costing some compression density.
  • Maintenance: active (commits May 2026 in the upstream repo).

Lepton (Dropbox)

  • Entropy coder: VP8-style binary arithmetic.
  • Transforms: richer than packJPG — pixel-domain DC predictor (IDCT of neighbour blocks), Lakhani edge predictor, neighbour-presence templates, neighbour nonzero counts as context.
  • Strength: designed for streaming decode (resumable, bounded memory).
  • Trade-off: Per the NSDI '17 paper (Horn et al.), ratio is ≈ within 0.5 % of packJPG. The win is in streaming throughput, not size.
  • Maintenance: archived 2023-02-14. Microsoft maintains a Rust port at microsoft/lepton_jpeg_rust.

JPEG XL cjxl --lossless_jpeg=1

  • Entropy coder: rANS with meta-adaptive (MA) context trees — DAGs of context selectors signaled per-image.
  • Transforms: runs DCT coefficients through JXL's VarDCT entropy stage.
  • Format: outputs .jxl (not interchangeable with .pjg); decoders decode either to the original JPEG or to native JXL display.
  • Maintenance: actively maintained (libjxl 0.11+, contributions through 2025-2026).

When to pick which

Need Pick
Maximum ratio, archival use packJPG
Fastest decode, small ratio penalty Brunsli
Streaming JPEG transcoding Lepton (Rust port)
Future-proof image format (not just JPEG) JPEG XL
Already in the JXL ecosystem cjxl --lossless_jpeg

For backups and "download original" hosted images where bit-exact recovery matters, packJPG. For HTTP delivery of recompressed images, JXL or WebP. For high-throughput cold storage (Dropbox-style), Lepton's Rust port.


Why hasn't packJPG been beaten on ratio?

JPEG redundancy lives mostly in:

  1. The Huffman entropy stage (table-coded, sub-optimal vs adaptive arithmetic).
  2. Inter-block correlation between DCT coefficients of neighbouring 8×8 blocks.

packJPG's PPM order-2 model captures (1) and most of (2). Five empirical attempts during 2026-04 / 2026-05 to push further (SITX-style 2-way DC ensemble, SITX-style 2-way AC bpos ensemble in 4 weight variants, pre-trained PPM priors at 3 strengths) all lost ratio relative to v4.0c. PPM order-2 with adaptive escape turns out to be very hard to beat on this signal.

External evidence backs the plateau: the NSDI '17 Lepton paper notes Lepton is "roughly equivalent" to packJPG on ratio; JXL with its meta-adaptive context trees still trails by ~4 % on tested corpora; Brunsli explicitly accepts a ratio loss in exchange for decode speed.

This is why the v4.0 line is positioned as LTS — the recompression ratio has plateaued, so releases focus on stability, tooling, and embedding rather than format changes. The line is format-stable since v4.0b; anything that would break the .pjg format would land in a future v4.1.


Reproducing these numbers

Sample command for the JXL comparison:

# Encode with cjxl
cjxl --lossless_jpeg=1 -e 9 photo.jpg photo.jxl

# Encode with packJPG
packJPG a photo.jpg

# Compare
ls -l photo.jpg photo.jxl photo.pjg

For ratio benchmarks across a corpus, run the encode in a loop and sum file sizes. The -vp flag in packJPG gives a progress bar; cjxl has its own --quiet etc.

Clone this wiki locally