Why JPEG Encodes Faster Than PNG on Old Hardware

Encoding images on older hardware presented severe constraints regarding CPU clock speeds, cache sizes, and memory bandwidth. JPEG is significantly more computationally efficient to encode than PNG in these environments because it relies on fixed-size block processing and mathematically predictable transforms rather than memory-intensive dictionary searches. While PNG demands two passes of complex data analysis—adaptive scanline filtering followed by sliding-window LZ77 compression—JPEG processes independent 8x8 pixel blocks using integer-based Discrete Cosine Transforms (DCT) and simple quantization, demanding vastly fewer CPU cycles and minimal dynamic memory.

8x8 Block Processing vs. Large Sliding Windows

JPEG divides an image into independent 8x8 pixel blocks. To encode a block, the processor only needs 64 pixels loaded into memory at any given moment. This tiny footprint easily fit inside the small L1 caches or limited registers of early CPUs, eliminating the need to constantly fetch data from slow system RAM.

In contrast, PNG uses the Deflate compression algorithm, which relies on a sliding dictionary (typically 32 KB) via LZ77. To find repeating byte sequences, the encoder must maintain a history buffer and navigate hash tables across entire scanlines. On older processors with narrow memory buses and high cache-miss penalties, chasing pointers through a sliding window causes significant memory bottlenecks.

Predictable Math vs. Dynamic String Matching

The mathematical pipeline of JPEG encoding is rigid and data-independent:

  1. Color Conversion and Subsampling: Predictable pixel-averaging operations.
  2. Discrete Cosine Transform (DCT): A fixed mathematical formula applied uniformly to every 8x8 block.
  3. Quantization: Element-by-element division against a fixed matrix.
  4. Entropy Coding: Run-length encoding followed by Huffman coding, which can use precomputed, static tables.

Because the execution path does not change based on image content, older CPUs could execute JPEG routines using streamlined loops without branch mispredictions. Furthermore, the DCT can be fully implemented using fast integer-only arithmetic (such as the Arai, Agui, and Nakajima algorithm) requiring only shifts and additions, avoiding slow floating-point units.

PNG encoding requires heavy, dynamic branching. The LZ77 algorithm must continuously compare substrings across the image data to find the longest matching sequences. String searching is highly branch-intensive, which severely degraded performance on older superscalar processors lacking sophisticated branch prediction.

The Overhead of PNG Filtering

Before PNG compresses any data with Deflate, it attempts to improve compression ratios by filtering the pixels. PNG evaluates each scanline against five different predictor filters (None, Sub, Up, Average, and Paeth).

Determining the optimal filter requires the encoder to either test multiple filters per row—essentially doing the work up to five times—or execute complex heuristics for every line of pixels. The Paeth filter, in particular, requires conditional evaluations and absolute value calculations for every byte relative to its left, upper, and upper-left neighbors. This pre-processing step adds a massive mathematical burden before actual compression even begins.

Streamable Single-Pass Design

JPEG was designed to work as a streamable, single-pass pipeline. Once an 8x8 block is transformed, quantized, and Huffman-coded, its output bytes can be written immediately to the output stream, and the working memory can be discarded.

PNG encoders must retain contextual line data (the current and prior scanline) to perform filtering and maintain dictionary trees for LZ77. The resulting cache thrashing, combined with the non-linear execution profile of dictionary compression, made PNG significantly slower to encode on older, resource-constrained systems.