深掘り

PNGの誕生:特許戦争が生んだ、Webで最も愛される可逆圧縮フォーマット

koboshiCo-founder
·4 分で読めます
PNGの誕生:特許戦争が生んだ、Webで最も愛される可逆圧縮フォーマット
要約

PNGは1995年のGIF特許危機から生まれた。ボランティアによって4ヶ月で構築され、フィルター前処理とDEFLATE圧縮を組み合わせてGIFを置き換えた。Unisysの訴訟からhexエディタで読めるファイル署名まで、技術的な全容を解説する。

PNGファイルをhexエディタで開く。先頭8バイト:

89 50 4E 47 0D 0A 1A 0A

これがPNGファイル署名だ。すべてのPNGデコーダーはこれを確認する。先頭バイト0x89は意図的に高い値に選ばれている——単純なテキストエディタがこのファイルをASCIIとして扱うのを防ぐためだ。50 4E 47はASCIIで「PNG」と綴る。0D 0AはDOSの改行、1AはDOSのEOFマーカー、0AはUnixのラインフィードだ。設計者はこれらの改行文字を埋め込んだ——テキストモードでのFTP転送が即座にファイルを破損させ、バイナリモードでの転送を強制するためだ。特許で縛られたフォーマットを目の当たりにしたばかりの開発者たちが取った過剰な用心だった。

PNGは今やどこにでもある。スクリーンショット、UIアセット、図解、ロゴ、何度保存し直してもピクセルがまったく同じままでなければならないすべての画像を支えている。Googleより古く、iPodより古い。可逆圧縮が重要な場合のデフォルト選択肢であり続けている。だが、もともとPNGはフォーマットとして生まれたわけではない。当面のつなぎとして生まれたのだ。標準としてではない。

新しいフォーマットを強いた訴訟

1995年1月、UnisysはLZW圧縮特許——米国特許第4,558,302号——をGIFフォーマットを使用する開発者に対して行使すると発表した。この特許はLempel-Ziv-Welchアルゴリズムをカバーしており、すべてのGIFエンコーダーとデコーダーの核心にあった。

1995年のWebはGIFで回っていた。アニメーションバナー、透過ロゴ、タイル状の背景——GIFがすべてを担っていた。そしてUnisysがロイヤリティを要求した。商用ソフトウェアベンダーはライセンス料に直面した。オープンソースプロジェクトは存続の危機に瀕した。GNU Image Manipulation Program(GIMP)は直接の影響を受けた。Web開発コミュニティは激怒した。

GIFの静的画像用途を何かが置き換える必要があった。要件は明確だった:特許なし、GIFより高い圧縮率、トゥルーカラー対応、そしてGIFの単色透過に代わる正当なアルファチャンネル。週末に1人の開発者がデコーダーを実装できる程度の単純さも必要だった。

1995年4月4日、Thomas BoutellがUsenetニュースグループcomp.graphicsに提案を投稿した。PBF——Portable Bitmap Format——と名付けた。名前は定着しなかった。その後数ヶ月でメーリングリストが形成された。貢献者にはTom Lane(Independent JPEG Groupのリーダー)、Lee Daniel CrockerAlexander Lehmann、そして数十人の開発者が含まれた。1996年10月1日までに、PNG仕様はRFC 2083として確定した。アイデアから標準化まで全体で約18ヶ月だ。比較すると、JPEGには6年かかった。

PNG以前に存在したもの

1995年の画像フォーマット選択肢は限られており、それぞれが重荷を背負っていた:

フォーマット圧縮色深度透過特許リスク一般的用途
GIFLZW256色まで1ビット、1色有り(LZW)Webグラフィック、アニメーション
JPEGDCT + Huffman24ビットトゥルーカラー無しベースライン期限切れ写真
BMP無しまたはRLE最大24ビット無し無しWindows壁紙
TIFFLZW、PackBitsなど最大48ビット有りLZWは任意印刷、スキャン
PCXRLE最大24ビット無し無しDOSゲーム、初期クリップアート

GIFはWebを支配していたが、法的に有毒だった。256色パレットはアイコンや漫画には十分だったが、写真には無力だった。透過は二値的だった:ピクセルは完全に不透明か、完全に透明かのどちらかだった。ソフトな縁も、ドロップシャドウも不可能だった。

JPEGは写真を見事に扱ったが、データを不可逆的に破壊した。JPEGを開き、編集し、再保存すれば画像は劣化した。JPEGには透過機能そのものがない。テクスチャ背景の上にロゴを浮かべたいWebデザイナーにとって、JPEGは無力だった。

BMPPCXは非圧縮、あるいはほぼ非圧縮だった。1995年の640 × 480のBMPは900 KBを消費した。28.8 kbpsモデムでは、ダウンロードに4分以上かかった。

TIFFは強力で柔軟だったが、その柔軟性が呪いになっていた。TIFFファイルは十数種類の圧縮方式、色空間、ビット深度を使用できた。汎用TIFFデコーダーを書くことは、週末のハックではなく学位論文レベルのプロジェクトだった。

PNGは狭い的を狙って設計された:GIFの静的画像用途を置き換え、圧縮を上回り、トゥルーカラーと本物の透過を追加し、永遠に無料であり続ける。

PNGが実際に圧縮する仕組み

PNGの圧縮は2段階のパイプラインだ。どちらの段階も単独では大したことはない。だが組み合わさると驚くほど効果的だ。

段階1:フィルタリング

圧縮が行われる前に、PNGは生のピクセルデータをフィルターに通す。フィルターは何も圧縮しない。データを並べ替えて、次の段階がより良く圧縮できるようにするだけだ。

画像はバイトのグリッドだ。晴れた空の写真では、隣接するピクセルはほとんど同じ値だ。しかし生のバイト列は各チャンネルに対して120, 121, 120, 122, 119を格納している。差分はわずかだ:+1, -1, +2, -3。絶対値ではなく差分を格納すれば、結果の数値はゼロ周辺に集まる。この集まりこそが、圧縮アルゴリズムが好む性質だ。

PNGはスキャンラインごとに5種類のフィルタータイプを定義する:

フィルター名前動作
0None生バイトをそのまま格納
1Sub前のピクセルからの差分を格納
2Up上のピクセルからの差分を格納
3AverageSubとUpの平均からの差分を格納
4Paeth最良予測値(Sub/Up/対角)からの差分を格納

エンコーダーはスキャンラインごとに5つのフィルターをすべて試し、段階2の後に最小出力を生むものを選ぶ。これがPNGエンコーダーが遅くなる理由だ:フィルターの組み合わせに対する力任せの探索を行っている。しかしデコードは高速だ——フィルタータイプはファイル内に格納されているので、デコーダーは逆演算を適用するだけだ。

段階2:DEFLATE

フィルタリング後、データはDEFLATEで圧縮される。これはgzipやZIPファイルが使用するのと同じアルゴリズムだ。DEFLATEはLZ77(スライディングウィンドウによる重複文字列の除去)とハフマン符号化(頻出シンボルへの可変長プレフィックスコード)の組み合わせだ。

結果:典型的なスクリーンショットやUIグラフィックは、非圧縮BMPに比べて3–5倍小さくなる。PNGとして圧縮された写真は通常JPEGの5–10倍のサイズになるが、すべてのピクセルが復元可能だ。圧縮は構造的に可逆だ:データは一切破棄されず、冗長性だけが除去される。

文脈を示すと、1920 × 1080のスクリーンショットを生のRGBで保存すると6.2 MBだ。同じスクリーンショットをPNGにすると通常800 KB – 1.5 MBに縮まる。同じ画像をJPEG品質90で保存すると300–500 KBだが、10回再保存すれば可視のアーティファクトが入る。

重要だった機能

PNGは単なる特許フリーのGIFクローンではなかった。Webデザイナーが1993年から求めていた機能が追加された。

トゥルーカラー:PNGは24ビットRGB(1670万色)と48ビットディープカラーをサポートする。パレット制限はない。PNGの写真は、人間の目が区別できるすべての色を表示できる。

アルファチャンネル:PNGは8ビットアルファ——ピクセルごとに256段階の透過——をサポートする。影は不透明から透明へ滑らかにフェードできる。角丸ボタンはあらゆる背景に対してアンチエイリアスできる。GIFが提供したのは1ビット透過だった:1色が完全オンか完全オフかのどちらかだった。視覚的な差は月と鼈ほどある。

Adam7インターレース:PNGは7パスのインターレース順序でピクセルを格納できる。ブラウザはファイルの1/64を受信した時点で粗いプレビューを描画し、段階的に精細化していく。GIFの行ごとのインターレースとは異なり、Adam7は最初のパスから画像全体にディテールを分散する。3パス目までには画像が認識可能になる。7パス目で完全になる。

ガンマ補正:PNGはメタデータにガンマ値を格納する。Mac(ガンマ1.8)で作成された画像が、Windows PC(ガンマ2.2)上で正しく表示される。手動の色補正は不要だ。これは1990年代、クロスプラットフォームの一貫性が稀だった時代の本当の問題だった。

CRCチェックサム:すべてのPNGチャンクはCRC-32チェックサムを持つ。破損したダウンロードは、中途半端に描画された画像を生成する代わりに即座に検出される。

ファイル署名を読んでPNGを検出する

.png拡張子を信頼するな。先頭8バイトを読み、署名を確認する。

正確なバイトレイアウト:

Bytes 0–7:  Signature 89 50 4E 47 0D 0A 1A 0A
Bytes 8–11: Chunk length (big-endian uint32)
Bytes 12–15: Chunk type: "IHDR" (image header)
Bytes 16–19: Image width (big-endian uint32)
Bytes 20–23: Image height (big-endian uint32)
Byte 24:    Bit depth
Byte 25:    Color type
Byte 26:    Compression method (always 0)
Byte 27:    Filter method (always 0)
Byte 28:    Interlace method (0 or 1)

ブラウザでのTypeScript:

async function isPng(file: File): Promise<boolean> {
  const buffer = await file.slice(0, 8).arrayBuffer()
  const bytes = new Uint8Array(buffer)

  const signature = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]
  return bytes.length === 8 && bytes.every((b, i) => b === signature[i])
}

Python

def is_png(path: str) -> bool:
    with open(path, "rb") as f:
        header = f.read(8)

    return header == b"\x89PNG\r\n\x1a\n"

標準ライブラリを使う高レベルな選択肢:

import imghdr

if imghdr.what("image.png") == "png":
    pass

Pillowを使う場合:

from PIL import Image

try:
    with Image.open("image.png") as img:
        is_png = img.format == "PNG"
except Exception:
    is_png = False

Go

func isPng(path string) bool {
	f, err := os.Open(path)
	if err != nil {
		return false
	}
	defer f.Close()

	buf := make([]byte, 8)
	if _, err := f.Read(buf); err != nil {
		return false
	}

	return bytes.Equal(buf, []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a})
}

PHP

function isPng(string $path): bool {
    $header = file_get_contents($path, false, null, 0, 8);
    return $header === "\x89PNG\r\n\x1a\n";
}

fileinfoを使う場合:

$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file('image.png');
// image/png

ImageMagick CLI

magick identify -verbose image.png | grep "Format:"
# Format: PNG (Portable Network Graphics)

または単純に:

file image.png
# image.png: PNG image data, 1200 x 675, 8-bit/color RGBA, non-interlaced

PNGの限界

PNGは完璧ではない。設計上の選択はトレードオフであり、そのいくつかは今も我々にコストを支払わせている。

組み込みのアニメーションなし:PNGワーキンググループは明示的にアニメーションを拒否した。複雑性を追加する前に静的画像の問題を完全に解決したかった。結果:アニメーションGIFはその後20年間生き残った。APNG(Animated PNG)は2004年に最終的に標準化されたが、ブラウザサポートは2010年代後半まで断片的なままだった。今でも、アニメーションGIFはAPNGを桁違いに上回る数で存在する。

写真のファイルサイズが大きい:12 MPの写真をPNGにすると通常15–25 MBになる。JPEG品質90では3–5 MBだ。PNGの可逆圧縮は、JPEGのDCTベースのサイコビジュアル破棄と競争できない。写真にはPNGは間違った道具だ。

CMYK非対応:PNGはRGBのみだ。CMYK分離を必要とする印刷ワークフローでは、PNGをTIFFまたはJPEGに変換しなければならない。これは意図的な選択だった——設計者は印刷ではなく画面表示に焦点を当てた——が、プロの出版におけるPNGの有用性を制限する。

JPEGより遅いデコード:PNGデコードはスキャンラインごとの逆フィルタリングとDEFLATE展開を必要とする。JPEGデコードは高度に並列化でき、ハードウェアで大幅に最適化されている。モバイルデバイスでは、大きなPNGは同じ解像度のJPEGの2–3倍の時間を要してレンダリングでき、Largest Contentful Paintを遅らせる。

プログレッシブ品質なし:JPEG 2000やJPEG XLとは異なり、PNGは切り詰められたファイルから低品質のプレビューを生成できない。ファイル全体を持つか、何も持たないかだ。Adam7インターレースは粗いプレビューには役立つが、総ファイルサイズは削減しない。

PNGがJPEGを置き換えられなかった理由

これは画像フォーマットについての最も一般的な誤解だ。PNGとJPEGは、決して同じ仕事を奪い合っていたわけではない。

JPEGはロッシー・サイコビジュアル圧縮器だ。目に気づかれにくいデータを破棄する。連続階調の写真——滑らかなグラデーション、繊細なテクスチャ、自然光——向けに設計された。三十三年経った今も、その仕事に関してJPEGはサイズ-品質曲線で未だに打ち破れない。

PNGは可逆データ圧縮器だ。すべてのビットを保存する。スクリーンショット、UI要素、図解、ロゴ、テキストオーバーレイ——鋭いエッジと正確な色が重要な離散階調画像——向けに設計された。その仕事において、PNGは標準だ。

2つのフォーマットは別々の領域を占めた:

用途正しいフォーマット理由
写真JPEG/AVIFロッシー圧縮が5–10倍小さい
スクリーンショットPNG/WebP可逆でテキストの鮮明さを保存
透過付きロゴPNG/WebPアルファチャンネル+可逆エッジ
UIアイコンPNG/SVG小さなサイズ、正確な色合致
科学データの可視化PNGグラデーション凡例にアーティファクトなし
印刷用画像TIFF/JPEG XLCMYK対応、高ビット深度

PNGは当初からJPEGを置き換えるつもりはなかった。ただ別の役割を見つけただけだ。

今のPNGの立ち位置

2025年Web Almanacによると、PNGはWebで配信されるすべての画像の**約22%**を占める。ピーク時からは減少している——WebPとAVIFがシェアを奪っている——が、PNGはすべてのブラウザ、すべての画像エディタ、すべてのOSが迷わず開けるフォールバックフォーマットであり続けている。

WebP(Google、2010年)はロッシーとロスレスの両モードに加え、アニメーションと透過をサポートする。ロスレスWebPは同等のPNGより通常20–30%小さい。ブラウザサポートは2020年以降普遍的だ。新規プロジェクトでは、ほとんどの場合、WebPロスレスがPNGの実用的な後継だ。

AVIF(AOM、2019年)はさらに優れた圧縮率を達成するが、ロスレスモードはPNGよりエンコードとデコードが遅い。AVIFはまた、16ビットチャンネルや埋め込みガンマ補正など、PNGの一部の高度な機能に対するブラウザサポートが不完全だ。

SVGは単純なベクターグラフィックのアイコンとロゴ領域を支配しているが、ラスタライズされた複雑なグラフィックには依然としてPNGが必要だ。

実際的な現実:PNGは消えない。安全なデフォルトだ。受信者がファイルを開けることを保証したいときにエクスポートするフォーマットだ。画像フォーマットのQWERTY——最適ではないが、普遍的に理解されている。

PNGの将来

PNGは完成した標準だ。仕様は2003年以降、実質的に変更されていない。その安定性は欠陥ではなく機能だ。1997年に作成されたPNGを現代のブラウザで開けば、同一にレンダリングされる。

しかし、PNGの周辺エコシステムは進化し続けている:

APNGが勢いを増している。Safariは2014年からサポートしている。ChromeとFirefoxも続いた。Discord、Slack、TwitterはすべてAPNGをネイティブにレンダリングする。短いUIアニメーション——ローディングスピナー、リアクション絵文字、ステータスインジケーター——において、APNGはアニメーションGIFをより小さなファイルとより良い色忠実度で置き換えている。

PNG最適化ツールは改善を続けている。oxipngpngcrushzopfliは、より良いフィルター組み合わせとDEFLATEパラメーターを力任せに探索することで、PNGファイルサイズをさらに10–30%削減できる。高トラフィックサイトでは、すべてのPNGをoxipngに通すことが標準的な実践だ。

PNG as a container:一部の現代ワークフローは、ICCカラープロファイル、EXIFメタデータ、さらにはXMPデータをPNGチャンク内に埋め込む。PNGは軽量なアーカイブフォーマットになっている——TIFFほど豊かではないが、はるかにポータブルだ。

長期的な見通し:PNGはWebP、AVIF、JPEG XLと今後も共存する。他のどのフォーマットも完全には所有していないニッチを埋めている:可逆、特許フリー、普遍的にサポートされ、仕様から1人の開発者が週単位でデコーダーを書けるほど単純だ。この組み合わせは簡単には置き換えられない。

結論

PNGは開発者たちがうんざりした結果生まれた。特許訴訟がオープンなWebを脅かし、開発者のグループが余暇を使って代替品を構築した。三十年の標準を作り出そうとしたわけではない。1つの問題を解決しようとした:ライセンス料を支払うことなく、Webページに透過ロゴを置く方法。

結果は誰が想像したよりもはるかに良かった。PNGはWebにトゥルーカラーグラフィック、滑らかな透過、破損に強いファイル完全性を与えた。ボランティアによって構築されたオープン標準が、大企業がバックアップする独自フォーマットを上回りうることを証明した。

最小のフォーマットではない。デコードが最速のフォーマットでもない。アニメーションはうまくいかず、写真には無力だ。しかし保存したすべてのピクセルが、取り戻すピクセルであることを確かめたいとき——PNGが依然として頼れるツールだ。

すべての画像が最初からPNGというわけではない。JPG画像を透過や可逆編集が必要な形に変えたいなら、ブラウザ上で直接変換できる——追加のソフトウェアは不要で、データが外に出ることもない。JPG to PNGはそのままローカルで処理する。Web制作でファイルサイズが気になる場合、JPG to WebPは画質を損なわずにファイルを軽くできる。faviconアイコンが必要なときは、JPG to ICOが写真から複数サイズのICOファイルを作り出す。

その他のおすすめ記事