Skip to content

How it works

YadeWira edited this page Nov 7, 2026 · 2 revisions

How it works

A JPEG is already compressed: its DCT coefficients are coded with Huffman (or arithmetic) codes, which leave a lot on the table. PJA undoes that last step and codes the coefficients again, much better, without touching the image.

  1. Decode to coefficients. pjajpeg reads the JPEG down to its DCT coefficients, plus everything needed to write the very same bits again: tables, markers, padding bits, and the habits of the encoder that made it. JPEG-LS (pjajls) and lossless JPEG decode to samples.
  2. Prove it can rebuild the file. Before anything else it re-encodes the coefficients and compares with the original. If even one bit differs, the file is not modeled as an image; it goes as bytes.
  3. Model and code. pjamodel predicts each coefficient from its neighbours (in the block, around it, across block edges, and from the luma for the chroma) and feeds the predictions to a binary arithmetic coder (pjaarith). Better predictions mean fewer bits.
  4. Verify. The compressor decompresses its own stream and compares it with the input before writing anything.
  5. Wrap. The .pja adds the original's size, a BLAKE3 hash and its extension, so pja x can refuse damage and size bombs before writing.

Large images are split into bands that run on several threads; the streams are the same with any number of threads and on every platform.

JPEG 2000

A JPEG 2000 codestream is not undone to pixels: each code-block's arithmetic-coded decisions (or, for HTJ2K, its cleanup and refinement values) are decoded, coded again with a context-mixing model, and the codestream is rebuilt from them byte for byte: packet headers, tag trees, the MQ coder's terminations and each encoder's habits (pjaj2kcs, pjaj2kt1.c, pjaj2kmc.c, pjaj2kht.c). A lossless codestream may instead be kept as its pixels, through image models (pjaj2kpx), when that is smaller: a scanned 1-bit page shrinks by two thirds. As for JPEG, a codestream that does not come back exactly stays as bytes.

PJA's format is its own: it is not compatible with packJPG's .pjg.

Further reading

Clone this wiki locally