JPEG圧縮の仕組みを図解で解説
DCT変換、量子化テーブル、画像によって圧縮率が違う理由をビジュアルで解説。JPEG圧縮の仕組みを一緒に見ていきましょう。

JPEGはファイル形式のゴキブリだ。1992年に標準化され、Webブラウザより古く、置き換えようとするあらゆる試みを生き延びてきた。WebP、AVIF、HEIC——どれも圧縮効率は上だが、それでもJPEGはインターネットで最も広く使われている画像形式であり続けている。慣性が大きいのは確かだ。しかし、JPEGの圧縮パイプラインは本当に優れている。エンコーダを書く予定がなくても理解する価値のある、応用信号処理の傑作だ。
ほとんどの開発者はJPEGをブラックボックスとして扱っている。画像を入れて、小さくなったファイルを取り出し、見た目が許容できるまで品質スライダーを上げ下げする。しかし箱の中で何が起きているかを理解すると、画像、圧縮、そしてファイルサイズと見た目の品質のトレードオフについての考え方が変わる。
パイプラインの全体像
JPEG圧縮は5つの段階からなるパイプラインで、それぞれが巧妙な処理を行っている。面白いのは、これらが組み合わさることだ。各段階が次の段階をより効果的に働けるように準備している。
- 色空間変換 — RGBからYCbCrへ(明るさと色を分離)
- クロマサブサンプリング — 色チャンネルの解像度を下げる
- 離散コサイン変換(DCT) — 空間データを周波数データに変換
- 量子化 — 高周波の細部を捨てる(ここが非可逆の工程)
- エントロピー符号化 — 量子化されたデータの可逆圧縮
最初の2つのステップは人間の視覚の仕組みを利用している。3つ目と4つ目は自然画像の性質を利用している。5つ目は標準的なデータ圧縮だ。どのステップ自体もシンプルだ。肝心なのはその順番である。
ステップ1:色空間変換
カメラは画像をRGB(赤・緑・青の各チャンネル、ピクセルあたり8ビット)で取得する。JPEGの最初の処理は、これをYCbCrに変換することだ。輝度(明るさ)チャンネル1つと、色差(色)チャンネル2つに分ける。これはまだ圧縮ではなく、データは失われていない。軸を回転させるような座標変換である。
なぜそうするのか?人間の目は色よりも明るさに対してはるかに敏感だからだ。白黒写真の極めて細かいディテールは見分けられるが、色の解像度に対する知覚はずっと粗い。明るさと色を分離することで、JPEGは両者を別々に扱える。明るさの細部は保ちつつ、色の細部は思い切って削減できる。
RGB to YCbCr conversion (simplified):
Y = 0.299R + 0.587G + 0.114B (luminance — brightness)
Cb = -0.169R - 0.331G + 0.500B (blue chrominance)
Cr = 0.500R - 0.419G - 0.081B (red chrominance)
Note: green dominates the luminance calculation because
human eyes have far more green-sensitive cone cells.
This isn't arbitrary — it matches the physiology.
ステップ2:クロマサブサンプリング
ここで最初の本格的なデータ削減が起きる。人間は色をフル解像度で知覚できないため、JPEGはCbとCrチャンネルの解像度を縦横とも通常半分に下げる。これは4:2:0サブサンプリングと呼ばれる。輝度ピクセル4つに対して、色差サンプルは1つだけになる。
結果として、生データを半分ほどに減らせる(フル解像度の3チャンネルから、フル1つと4分の1解像度2つへ)。しかも画像は元とほぼ見分けがつかない。試してみるといい。任意の写真で色チャンネルの解像度を4分の1にしてみると、違いを見つけるのに苦労するはずだ。脳が輝度情報から色の細部を補完してくれる。
この手法はすべての画像に同じように効くわけではない。写真は自然の風景が滑らかな色のグラデーションを持つため、非常にうまく圧縮できる。しかし、色の境界がシャープな画像——例えば色付き背景の上の文字、白地の赤い円、ドット絵など——では、クロマサブサンプリング後に色のにじみ(カラーフリンジ)が目立つ。JPEGが文字を苦手とする理由はここにある。シャープな色のエッジが滲んでしまうのだ。
ステップ3:離散コサイン変換
DCTこそJPEGが面白くなる部分だ。画像は8×8ピクセルのブロックに分割され、各ブロックは空間領域(ピクセルの明るさの値)から周波数領域(各空間周波数がどれだけ含まれているか)へと変換される。
こう考えるとわかりやすい。8×8のピクセルブロックは、64個の基底パターンの重み付き和として表現できる。最初のパターンは平坦なブロック(平均値)だ。次のパターンは水平方向と垂直方向の勾配を加えていく。番号が大きいパターンほど、より細かいディテール——明るさの急速な振動——を加えていく。
An 8x8 DCT block conceptually:
DC ──► Low frequency ──────────────► High frequency
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ AVG │ → │ → │ → │ → │ → │ → │ → │ Low freq
│ │ │ │ │ │ │ │ │ ↓
│ ↓ │ ↘ │ │ │ │ │ │ │
│ │ │ ↘ │ │ │ │ │ │
│ │ │ │ ↘ │ │ │ │ │
│ │ │ │ │ ↘ │ │ │ │
│ │ │ │ │ │ ↘ │ │ │
│ │ │ │ │ │ │ ↘ │ │
│ │ │ │ │ │ │ │ FINE │ High freq
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
Top-left = low frequency (smooth gradients)
Bottom-right = high frequency (sharp edges, fine detail)
Natural images: most energy concentrated in top-left
Text/line art: significant energy in bottom-right
DCT自体は可逆だ。64個のDCT係数から、元の8×8ブロックを完全に復元できる。しかし重要なのはここからだ。自然画像(写真、グラデーション、有機的なテクスチャ)では、エネルギーの大部分が低周波の係数に集中する。細部を表す高周波の係数は小さくなりがちだ。これが次のステップを機能させている。
なぜ8×8なのか?それは妥協の産物だ。16×16や32×32のような大きいブロックならエネルギーをより集中させられるが、計算コストが高く、低品質設定では目に見える「ブロックノイズ」が出る。4×4のような小さいブロックならブロックノイズは減るが、エネルギーの集中度は下がる。8×8は、30年以上も使われ続けてきたスイートスポットだったということだ。
ステップ4:量子化——データが消える場所
ここが非可逆の工程だ。各DCT係数は、量子化テーブルの対応する値で割られ、最も近い整数に丸められる。大きな除数(高周波係数用)は小さな値をゼロに丸める。そのゼロは二度と戻らない。ここで情報が恒久的に捨てられるのだ。
Example quantization (quality ~50):
DCT coefficient: 42.7 Quantization divisor: 16 Result: round(42.7/16) = 3
DCT coefficient: 8.3 Quantization divisor: 40 Result: round(8.3/40) = 0
DCT coefficient: -2.1 Quantization divisor: 99 Result: round(-2.1/99) = 0
The quality slider in your image editor controls the quantization table.
Quality 100: divisors close to 1 (almost no rounding, huge file)
Quality 75: moderate divisors (good balance, typical web use)
Quality 50: large divisors (noticeable artifacts, small file)
Quality 10: very large divisors (blocky mess, tiny file)
量子化テーブルは、JPEGの品質を決める最も重要な要素だ。JPEG規格ではデフォルトのテーブルが定義されているが、エンコーダは好きなテーブルを使える。MozJPEGのような最新のエンコーダは、人間の知覚感度に合わせて除数を調整した最適化テーブルを使い、同じファイルサイズでより高い品質を引き出している。人間が感度の低い周波数に対しては、より積極的に圧縮するのだ。
量子化の後、中程度の品質での典型的な8×8ブロックには、64個のうち非ゼロの係数が6〜10個程度しか残らない。残りはゼロだ。この非ゼロ値の劇的な減少こそが、最終的な圧縮ステップを効果的にしている。
ステップ5:エントロピー符号化
最後のステップは、量子化された係数の可逆圧縮だ。JPEGはランレングス符号化(RLE)とハフマン符号化を組み合わせて使う。係数は8×8ブロックからジグザグのパターンで読み出される。左上のDC係数から始めて、周波数が高くなる方向へジグザグに進む。これにより末尾のゼロがまとめられ、RLEが効率よく処理できる。「0, 0, 0, 0, 0, 0, ..., 0」と保存する代わりに、「ゼロが47個」と保存するのだ。
次にハフマン符号化が、出現頻度の高い値には短いビット列を、珍しい値には長いビット列を割り当てる。非ゼロ係数のほとんどは小さな整数(1, -1, 2, -2)なので、非常に短い符号になる。結果として、64個の値で始まった量子化された8×8ブロックは、画像の内容と品質設定によって通常20〜40バイトまで圧縮される。
なぜ画像によって圧縮率が違うのか
パイプラインを理解すると、そうでなければ不可解に見える圧縮の挙動が説明できる。
- 写真はよく圧縮できる。滑らかな色のグラデーションがあり(クロマサブサンプリングが効果的)、エネルギーの大部分が低周波のDCT係数に集中しているため(量子化で多くの係数を目に見える影響なしにゼロにできる)。
- 文字や線画は圧縮が苦手。シャープなエッジは大きな高周波DCT係数を生み出し、目に見えるアーティファクトなしにはゼロにできない。文字のエッジ周辺にリンギングが出て、8×8ブロックの境界が目立つようになる。
- ノイズは圧縮を台無しにする。センサーノイズはランダムな高周波データだからだ。ノイズのあるピクセルはそれぞれ非ゼロの高周波係数を追加し、量子化に抵抗する。同じ被写体を同じ品質80で撮影した場合、ノイズのある写真はクリーンな写真の3〜5倍のサイズになることもある。
- グラデーションはほぼタダ。8×8ブロック内の滑らかなグラデーションは、わずか2〜3個のDCT係数で表現できる。量子化しなくても、残りはゼロになる。
- 再保存で画質が劣化する。保存のたびに量子化が再び適用され、丸め誤差が蓄積するからだ。品質75で10回保存したJPEGは、品質75で1回保存したものよりはっきりと劣化する。だから編集は必ず元のソースファイルから行うべきなのだ。
品質スライダーは線形ではない
多くの開発者はJPEGの品質スライダーを線形のトレードオフだと思っている。品質50は品質100の半分の品質で、ファイルサイズも半分になる、と。しかしどちらも正しくない。
品質100は「ロスレス」ではない。依然として量子化を適用しており、ただ除数が小さいだけだ。ファイルは巨大になり(PNGより大きくなることも多い)、見た目は品質95とほぼ区別がつかない。写真の場合、品質95は品質90と見分けがつかない。品質85と75の知覚的な差は、100と85の差より大きい。品質50を下回るとアーティファクトが深刻になり、ファイルサイズの削減も鈍くなる。
Web画像のスイートスポットは通常、品質75〜85だ。75未満では、通常の表示サイズでもアーティファクトが見える。85を超えると、知覚的な改善はわずかなのにファイルサイズは大きく増える。MozJPEGのデフォルト品質75は、ほとんどの写真で品質とサイズのカーブの「膝」に当たるので、よく選ばれている。
最新のJPEGエンコーダは思った以上に賢い
JPEG規格が定義しているのはデコード形式であって、エンコーダではない。つまり、エンコーダの実装によって圧縮効率は大きく異なりうるが、どれも規格に準拠したファイルを出力する。Mozillaが開発したMozJPEGは、いくつかの手法によって、同じ見た目の品質でlibjpegより5〜15%小さいファイルを生成する。
- トレリス量子化 — 各DCT係数を独立に丸めるのではなく、丸めの判断がエントロピー符号化の段階にどう影響するかを考慮し、全体としてより良い選択をする。
- 最適化されたハフマンテーブル — JPEGのデフォルトのハフマンテーブルは汎用的なものだ。MozJPEGは、各画像の実際の係数分布に合わせてカスタムテーブルを生成する。
- プログレッシブエンコーディング — プログレッシブJPEGは、係数を複数のパス(まず粗く、次に精細化)に分けて保存する。粗いパスの係数分布は予測しやすいため、順次エンコーディングより圧縮効率が高くなることが多い。
- 適応的量子化テーブル — 画像全体に1つの量子化テーブルを使うのではなく、適応型エンコーダは領域ごとに量子化を調整する。アーティファクトが目立ちにくい複雑な領域では積極的に、滑らかな領域では控えめにする。
Web上で画像を配信しているなら、デフォルトのlibjpegエンコーダからMozJPEGに切り替えるのは、最も手軽なパフォーマンス改善の一つだ。多くの画像CDNや画像処理ライブラリがすでに対応している。エンコードは遅くなるが(事前処理された静的画像なら問題にならない)、同じ品質でファイルは小さくなる。
JPEGと新しい形式の比較
WebP、AVIF、HEICはいずれも、より新しい圧縮技術を使っている。大きな変換ブロック、ループ内デブロッキングフィルタ、イントラ予測(隣接ブロックを使って現在のブロックを予測する)などだ。同じ見た目の品質でJPEGより20〜50%小さく圧縮できる。特にAVIFはAV1動画コーデックをベースにしており、驚くほど効率が良い。
では、なぜJPEGは今でもどこにでもあるのか?それは普遍的なサポートがあるからだ。すべてのブラウザ、すべての画像ビューア、すべてのOS、すべてのカメラ、すべてのスマートフォン、画像を扱うすべてのソフトウェアがJPEGに対応している。WebPはブラウザではほぼ普遍的だが、OSのネイティブサポートが不足している。AVIFのサポートはまだばらつきがある。HEICは主にAppleのエコシステムのものだ。どこでも動く必要がある形式として、JPEGは今でも唯一の安全な選択肢なのだ。
実践的なアドバイスとしては、配信基盤が対応しているなら(ほとんどのCDNはコンテンツネゴシエーションで対応している)、JPEGフォールバック付きでAVIFやWebPを使おう。一つの形式しか使えないなら、MozJPEGで品質80にエンコードしたJPEGは写真に対してなかなか勝てない。スクリーンショット、図表、テキストの多い画像には、PNGが依然として良い選択だ。画像表現へのもっと創造的なアプローチも覗いてみてほしい。
世界を征服した8×8ブロック
JPEGの圧縮パイプラインは、人間の知覚に逆らうのではなく、それに寄り添って設計されたエンジニアリングの教科書的な例だ。各段階は特定の性質を利用している——色への鈍感さ、自然画像の周波数分布、量子化ノイズの知覚的マスキング——そして、それらが組み合わさって、目立つ影響をほとんど与えずにファイルを10〜20分の1に減らすシステムになっている。34年経った今でも、1992年のハードウェアで動いていた同じ8×8 DCTブロックが、インターネット上の画像の大部分を支えている。基礎をきちんと押さえた設計の証だ。


