How JPEG Compression Works — A Visual Guide
Every day, billions of digital photos are captured on smartphones, uploaded to social networks, transmitted across cellular data connections, and rendered in web browsers. Almost all of them pass through an algorithm devised in the late 1980s by the Joint Photographic Experts Group (JPEG).
Despite being over three decades old, the JPEG standard (officially ISO/IEC 10918-1) remains one of the most brilliant triumphs of digital signal processing and human psychophysics ever engineered. A standard JPEG compressor routinely shrinks raw image data by 10× to 20× without any visible loss of fidelity to the naked human eye.
How can an algorithm discard 90% of an image's raw bytes while leaving the picture looking virtually untouched? Where do those characteristic "compression artifacts" come from when you push the quality slider too low?
In this visual, step-by-step engineering guide, we open up the JPEG pipeline and inspect every mathematical gear under the hood.
1. The High-Level Compression Pipeline
JPEG compression is not a single mathematical trick. It is an intricate six-stage assembly line that combines color science, frequency domain mathematics, statistical thresholding, and information theory:
[RGB Pixels] ──► [Color Space Conversion (YCbCr)]
│
▼
[Chroma Subsampling (4:2:0)]
│
▼
[8×8 Block Splitting & Level Shift]
│
▼
[Discrete Cosine Transform (DCT)]
│
▼
[Quantization (The Only Lossy Step!)]
│
▼
[Zig-Zag Scan & Run-Length Encoding]
│
▼
[Huffman Entropy Encoding] ──► [Compressed .JPG Stream]
Let us trace an image through each step of this pipeline to observe how raw light is converted into an ultra-compact byte sequence.
2. Step 1: Color Space Conversion (RGB to YCbCr)
Computer monitors and digital camera sensors natively represent colors as additive mixtures of three primary wavelengths: Red, Green, and Blue (RGB). Each pixel typically uses 8 bits per channel (24 bits total), representing 16.7 million colors.
However, the RGB color model is notoriously inefficient for compression because the three channels are heavily correlated (a bright white light maximizes all three; darkness minimizes all three) and it treats all color information with equal importance.
The human visual system does not perceive light as raw RGB signals. In the human retina, there are roughly 120 million rod cells (which detect luminance, brightness, and contrast) but only about 6 to 7 million cone cells (which detect color wavelengths). Our evolutionary biology makes us exquisitely sensitive to sharp edges in brightness, but relatively blind to subtle color fluctuations.
To exploit this biological quirk, JPEG immediately converts RGB into the YCbCr color space using a linear matrix transformation (defined by ITU-R BT.601):
Y = 0.29900 · R + 0.58700 · G + 0.11400 · B (Luminance: Brightness)
Cb = -0.16874 · R - 0.33126 · G + 0.50000 · B + 128 (Chrominance: Blue difference)
Cr = 0.50000 · R - 0.41869 · G - 0.08131 · B + 128 (Chrominance: Red difference)
By isolating brightness into the Y (luma) channel and separating hue into the Cb and Cr (chroma) channels, JPEG can now treat color and brightness with completely different levels of aggressive compression.
3. Step 2: Chroma Subsampling (Free 50% Reduction)
Before performing any complex mathematical transforms, JPEG discards a massive portion of the color data through a process called chroma subsampling.
In an uncompressed image, every single pixel has its own unique Y, Cb, and Cr values (referred to as 4:4:4 subsampling). But because our eyes struggle to notice chromatic blur over small distances, JPEG encoders typically use 4:2:0 subsampling:
4:4:4 (No Subsampling) 4:2:0 (Standard JPEG)
┌─────┬─────┐ ┌─────┬─────┐
│Y CbCr Y CbCr│ │ Y │ Y │
├─────┼─────┤ ├─────┼─────┤ ◄── 4 Luma samples share
│Y CbCr Y CbCr│ │ Y │ Y │ 1 (Cb, Cr) color pair
└─────┴─────┘ └─────┴─────┘
Total: 4 Y + 4 Cb + 4 Cr = 12 Total: 4 Y + 1 Cb + 1 Cr = 6
Relative size: 100% Relative size: 50%
In 4:2:0 mode, the horizontal and vertical resolution of the color channels is halved. For every 2×2 grid of 4 pixels, the encoder keeps all 4 luminance values, but averages the color into just 1 Cb and 1 Cr value.
This step alone cuts the uncompressed raw data payload from 12 values down to 6 values—a 50% reduction in raw size before any real compression has even taken place, with zero discernible visual degradation on natural photographs!
4. Step 3: 8×8 Block Splitting & The Discrete Cosine Transform (DCT)
Next, JPEG divides each channel (Y, Cb, and Cr) into independent grids of 8×8 pixel blocks. If an image's dimensions are not exact multiples of 8, the encoder pads the bottom and right edges by repeating the border pixels.
For each 8×8 block, pixel values (which range from 0 to 255) are first level-shifted by subtracting 128, re-centering the values around zero (from -128 to +127).
Spatial Domain vs. Frequency Domain
In the spatial domain, an 8×8 block is merely a matrix of 64 brightness values. While humans perceive objects, textures, and gradients, the computer only sees isolated numbers:
Spatial Domain (Raw Pixels, 8×8)
┌────┬────┬────┬────┬────┬────┬────┬────┐
│ 52 │ 55 │ 61 │ 66 │ 70 │ 61 │ 64 │ 73 │
│ 63 │ 59 │ 66 │ 90 │108 │ 85 │ 73 │ 96 │
│ 62 │ 59 │ 68 │113 │144 │104 │ 66 │ 73 │
│ 63 │ 58 │ 71 │122 │154 │106 │ 70 │ 69 │
│ 67 │ 61 │ 68 │104 │126 │ 88 │ 68 │ 70 │
│ 79 │ 65 │ 60 │ 70 │ 77 │ 68 │ 58 │ 75 │
│ 85 │ 71 │ 64 │ 59 │ 55 │ 61 │ 65 │ 83 │
│ 87 │ 79 │ 69 │ 68 │ 65 │ 76 │ 78 │ 94 │
└────┴────┴────┴────┴────┴────┴────┴────┘
To compress this effectively, JPEG converts this matrix from the spatial domain into the frequency domain using the two-dimensional Discrete Cosine Transform (DCT):
F(u,v) = 1/4 · C(u)·C(v) ∑_{x=0}^7 ∑_{y=0}^7 f(x,y) cos[ (2x+1)uπ / 16 ] cos[ (2y+1)vπ / 16 ]
What does DCT actually do?
Think of the DCT as an audio spectrum analyzer for pictures. Just as a musical chord can be broken down into a fundamental pitch plus a series of harmonics (sine waves of increasing frequency), any 8×8 grid of pixels can be represented as a weighted sum of 64 predefined cosine basis patterns:
- The Top-Left Coefficient (0,0) — The DC Coefficient: Represents the zero-frequency baseline—the average brightness of the entire 8×8 block.
- The Remaining 63 Coefficients — The AC Coefficients: Represent fluctuations across horizontal and vertical axes at progressively higher frequencies. As you move toward the bottom-right, the frequencies correspond to rapid, microscopic texture changes.
Crucially, the DCT itself is 100% mathematically lossless and reversible. It does not discard any information; it simply reshuffles the energy of the block so that almost all significant information is packed into the top-left corner, while the bottom-right values hover close to zero.
5. Step 4: Quantization (The Heart of JPEG Compression)
Up to this point, no visual data has been permanently destroyed (except for chroma subsampling). Every transformation has been mathematically reversible.
Quantization is the single step where lossy compression actually occurs. This is where file sizes collapse and where the "Quality Factor" (from 1 to 100) does its work.
The human eye is exquisitely capable of noticing subtle changes in large smooth areas (low frequencies), but almost completely incapable of detecting the exact amplitude of rapid, high-frequency oscillations (fine grain, tiny textures).
JPEG takes each DCT coefficient $F(u, v)$ and divides it by a corresponding entry in a predefined Quantization Matrix $Q(u, v)$, rounding the result to the nearest integer:
Quantized(u, v) = Round( F(u, v) / Q(u, v) )
Here is an example standard luminance quantization matrix specified in Annex K of the JPEG standard:
Standard Luminance Quantization Matrix Q:
┌────┬────┬────┬────┬────┬────┬────┬────┐
│ 16 │ 11 │ 10 │ 16 │ 24 │ 40 │ 51 │ 61 │ ◄── Low frequencies (divided by small numbers)
│ 12 │ 12 │ 14 │ 19 │ 26 │ 58 │ 60 │ 55 │
│ 14 │ 13 │ 16 │ 24 │ 40 │ 57 │ 69 │ 56 │
│ 14 │ 17 │ 22 │ 29 │ 51 │ 87 │ 80 │ 62 │
│ 18 │ 22 │ 37 │ 56 │ 68 │109 │103 │ 77 │
│ 24 │ 35 │ 55 │ 64 │ 81 │104 │113 │ 92 │
│ 49 │ 64 │ 78 │ 87 │103 │121 │120 │101 │
│ 72 │ 92 │ 95 │ 98 │112 │100 │103 │ 99 │ ◄── High frequencies (divided by massive numbers)
└────┴────┴────┴────┴────┴────┴────┴────┘
How the Quality Factor Scales the Matrix
When you adjust the compression slider in an image editor or on CompJPG, you are not changing the DCT algorithm. You are scaling this quantization matrix:
- At Quality = 100: The divisor matrix entries are scaled down to 1. Very little rounding occurs; almost all frequencies are preserved, producing huge file sizes.
- At Quality = 80: Low frequencies are divided by small numbers (preserving fidelity), while high frequencies are divided by large numbers (rounding dozens of small values down to exactly 0).
- At Quality = 20: All divisors are inflated dramatically. High and mid-range frequencies are crushed to zero, and even low frequencies lose significant precision, causing visible distortion.
After quantization, the resulting matrix looks like this:
Quantized Block (Look at all the zeros!):
┌────┬────┬────┬────┬────┬────┬────┬────┐
│-26 │ -3 │ -6 │ 2 │ 2 │ -1 │ 0 │ 0 │
│ 0 │ -2 │ -4 │ 1 │ 1 │ 0 │ 0 │ 0 │
│ -3 │ 1 │ 5 │ -1 │ -1 │ 0 │ 0 │ 0 │
│ -4 │ 1 │ 2 │ -1 │ 0 │ 0 │ 0 │ 0 │
│ 1 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │
│ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │
│ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │
│ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │
└────┴────┴────┴────┴────┴────┴────┴────┘6. Step 5: Zig-Zag Scanning & Run-Length Encoding (RLE)
Notice the sea of zeros in the bottom-right of the quantized matrix. To exploit these consecutive zeros, JPEG traverses the 8×8 matrix diagonally in a zig-zag pattern:
Zig-Zag Scanning Order:
(0,0) ──► (0,1) (0,2) ──► (0,3)
╱ ╱ ╲
(1,0) (1,1) (1,2)
│ ╱ │
▼ ▼ ▼
(2,0) ──► (2,1) (3,0) ... ──► (7,7)
Because low frequencies are in the top-left and high frequencies are in the bottom-right, zig-zag ordering organizes non-zero values first, followed by long continuous runs of zeros.
JPEG encodes these runs using Run-Length Encoding (RLE). When the scan hits the point where all remaining values are zero, it emits a single special byte: EOB (End of Block).
Instead of recording 40 individual zeros, the encoder writes just one EOB symbol!
7. Step 6: Huffman Entropy Encoding
The final step is completely lossless information theory: Huffman Coding.
In an uncompressed data stream, every character or symbol is stored using a fixed number of bits (such as 8 bits per byte). Huffman coding assigns variable-length bit codes based on statistical frequency:
- Frequently occurring symbols (like zero runs and common small amplitudes) receive ultra-short bit strings (e.g., 2 or 3 bits).
- Rarely occurring large amplitudes receive longer bit strings (e.g., 12 to 16 bits).
Modern encoders like MozJPEG also employ trellis quantization—an optimization pass that evaluates whether tweaking a coefficient by ±1 will produce a significantly cheaper Huffman code without harming visual similarity.
The resulting bitstream is packaged into standard JFIF markers (such as 0xFFD8 for Start of Image and 0xFFD9 for End of Image), producing the final .jpg file.
8. Why Do JPEG Artifacts Appear?
Now that you understand the mathematical mechanics of JPEG, the causes of common compression flaws become immediately obvious:
1. Blocking Artifacts (Grid Patterns)
Because JPEG processes images in strictly independent 8×8 pixel blocks, the DC coefficients (average block brightness) of adjacent blocks can drift apart when quantization is severe. When the boundary between two adjacent blocks no longer matches smoothly, visible 8×8 grid squares appear across what should be a smooth gradient (such as a blue sky or soft shadow).
2. Ringing Artifacts / "Mosquito Noise"
When an 8×8 block contains a high-contrast knife-edge (such as black text on a clean white page, or the sharp roofline of a building against the sky), the DCT requires high-frequency cosine waves to simulate that sharp jump. When quantization rounds those high-frequency coefficients to zero, the reconstructed image exhibits mathematical oscillation—a phenomenon known in signal processing as the Gibbs Phenomenon. This manifests as shadowy ripples, halos, or buzzing specks around sharp edges.
3. Color Bleeding and Banding
Aggressive 4:2:0 chroma subsampling groups color into 2×2 pixel blocks. On vibrant saturated edges (such as bright red text on a blue background), the color will visually bleed outside the border by 1 to 2 pixels. Furthermore, heavy quantization of low-frequency coefficients removes subtle transitional shades, converting smooth sky gradients into stepped, staircased bands of color.
9. Key Takeaways for Web Developers & Creators
- 80–85% is the golden sweet spot: Above 85%, JPEG files balloon in size because the encoder preserves microscopic high frequencies that human eyes cannot perceive. Below 75%, blocking and ringing artifacts begin to emerge.
- Never compress text or vector graphics with JPEG: For UI screenshots, logos, and illustrations with crisp contrast, use PNG or WebP to eliminate ringing artifacts. Check out our comprehensive comparison: JPEG vs PNG vs WebP: Which Format Should You Use in 2026?.
- Avoid multiple lossy saves: Every time you open a JPEG, edit it, and save it again as a JPEG, the image undergoes another round of DCT, quantization, and rounding. Artifacts compound exponentially with each generational save.
- Compress client-side for speed and privacy: With modern WebAssembly and Canvas APIs, you don't need to upload sensitive photos to remote servers for compression. Tools like CompJPG execute these exact mathematical transformations right inside your browser in milliseconds.