画像をWebPにすると軽くなると言われるが、どれだけ小さくなるかは設定と画像の中身で変わる。
変換の方式には、元の画素をそのまま保つものと、情報を捨てて小さくするものがある。
ここでは、実際に手元で変換して測った数値をもとに、どちらを選ぶかの考え方を整理する。
測定は2026年9月20日にPython 3.13とPillow 12.3.0で実行した。
実際に測った数値
同じ画像をPNGとWebPで保存し、大きさと、元の画素との差を比べた。
1枚目は文字と単色の面が多い画像(1280×720)である。
| 保存の仕方 | 大きさ | PNG比 | 元と一致 | 画素の平均差 | 最大差 |
|---|---|---|---|---|---|
| PNG | 82,785 バイト | 100% | — | — | — |
| WebP 可逆 | 45,614 バイト | 55.1% | 一致する | 0 | 0 |
| WebP 品質90 | 14,908 バイト | 18.0% | 一致しない | 1.08 | 19 |
| WebP 品質80 | 10,986 バイト | 13.3% | 一致しない | 1.14 | 35 |
| WebP 品質75 | 9,700 バイト | 11.7% | 一致しない | 1.17 | 38 |
2枚目は別の図版(1280×720)で、傾向は同じだった。
| 保存の仕方 | 大きさ | PNG比 | 画素の平均差 | 最大差 |
|---|---|---|---|---|
| PNG | 91,319 バイト | 100% | — | — |
| WebP 可逆 | 51,652 バイト | 56.6% | 0 | 0 |
| WebP 品質90 | 15,454 バイト | 16.9% | 0.99 | 16 |
| WebP 品質80 | 11,356 バイト | 12.4% | 1.07 | 23 |
| WebP 品質75 | 9,966 バイト | 10.9% | 1.10 | 31 |
平均差と最大差は、0から255までの値としての差である。
平均が1前後でも最大が30を超える箇所があり、差は画像全体に均等ではない。
2つの方式の違い
| 方式 | 画素 | 小ささ | 向いている画像 |
|---|---|---|---|
| 可逆 | 対応する画素を保持(透明部分のRGBは設定を確認) | この2枚ではPNGの約55% | 図版、スクリーンショット、透過が要るもの |
| 非可逆 | 設定と画像によって画素が変わる | この2枚ではPNGの1〜2割 | 写真、細かい階調が多いもの |
9月20日の2枚では、可逆でPNGの半分程度になった。ただし画像やメタデータによって大きくなる場合もあるため、出力サイズを確認する。
この2枚では非可逆で1割台になったが、すべての画像で同じ比率になるわけではない。
この差をどう受け取るかは、その画像が何に使われるかで変わる。
どちらを選ぶかの決め方
画像の中身より先に、その画像に求める性質を決めるほうが早い。
| 求める性質 | 選ぶ方式 | 理由 |
|---|---|---|
| 文字がにじんでは困る | 可逆 | 非可逆は輪郭の周りに差が出る |
| 色を正確に伝えたい | 可逆 | 画素に加えICCの保持と表示環境も確認する |
| 読み込みを軽くしたい | 非可逆 | この2枚では1割台。必ず小さくなるわけではない |
| 元画像として保管する | 可逆またはPNGのまま | あとから作り直せる |
| 透過が要る | どちらも可 | WebPは透過に対応している |
スクリーンショットや図版で文字が入っているものは、非可逆にすると輪郭の周りに差が出やすい。
実測でも、文字と単色の面が多い画像のほうが最大差が大きかった。
オンラインの変換を使うときに見るところ
ブラウザーで変換できるサービスは多いが、確かめておきたい点がいくつかある。
- 可逆と非可逆を選べるか(選べない場合は実際の出力方式を仕様で確認する)
- 品質の数値を指定できるか
- 元のファイルがどこへ送られるか(手元で処理するものと、送信するものがある)
- 変換後にサイズを確かめられるか
- 透過が残るか
公開前の資料や、他人から預かった画像を扱う場合は、送信の有無を先に確かめる。
「ブラウザー内で処理」という表示だけで送信がないと断定せず、データの扱いと通信仕様を確認してください。
手元で変換する
同じ設定で何枚も変換するなら、ローカルで一括処理する方法があります。処理速度はPCや設定によって異なります。
PythonのPillowを使う場合はこう書ける。
from pathlib import Path
from PIL import Image, features
source = Path("png-source").resolve(strict=True)
output = source.parent / "webp-new"
if output.exists():
raise FileExistsError(output)
if not features.check("webp"):
raise RuntimeError("PillowにWebP対応が必要です")
files = sorted(source.glob("*.png"))
if not files:
raise ValueError("PNGがありません")
# 全入力を先に確認。通常の8bit RGB/RGBA・静止画が対象。
for src in files:
if src.is_symlink() or src.read_bytes()[24] != 8:
raise ValueError(f"対象外のPNG: {src.name}")
with Image.open(src) as im:
if im.format != "PNG" or im.mode not in ("RGB", "RGBA") or getattr(im, "n_frames", 1) != 1:
raise ValueError(f"対象外のPNG: {src.name}")
im.load()
output.mkdir()
for src in files:
with Image.open(src) as im:
options = {k: im.info[k] for k in ("icc_profile", "exif") if k in im.info}
dest = output / (src.stem + ".webp")
with dest.open("xb") as stream:
im.save(stream, "WEBP", lossless=True, exact=True, **options)
print(src.name, src.stat().st_size, dest.stat().st_size)
変換したあと、元と一致しているかを確かめたい場合は次のようにする。
from PIL import Image, ImageChops, ImageStat
with Image.open("png-source/alpha.png") as original, Image.open("webp-new/alpha.webp") as converted:
a, b = original.convert("RGBA"), converted.convert("RGBA")
if a.size != b.size:
raise ValueError("寸法が違います")
d = ImageChops.difference(a, b)
extrema = [band.getextrema() for band in d.split()]
print("RGBA全チャンネル一致:", all(high == 0 for low, high in extrema))
print("R/G/B/Aの平均差:", ImageStat.Stat(d).mean)
RGBAの差をgetbbox()の標準設定だけで調べると、RGBの差を見落とす場合がある。
改訂した比較例では差分をR・G・B・Aの4バンドに分け、各バンドの最大値を確認する。
透過画像ではRGBだけで比較すると透明度の変化を見落とすため、アルファも比較する。
置き換えるときに気をつけること
- 元のPNGを消す前に、変換後の見た目を実際に開いて確かめる
- 差し替えるならURLも変わるため、参照している場所をすべて直す
- 印刷や再編集に使う元データは、PNGのまま残しておく
- 同じ設定で全部を変換せず、文字の多い画像だけ可逆にするなど分ける
容量を削ることだけを目的にすると、あとから作り直せない画像を非可逆にしてしまう。
透明部分の画素と上書きを確認する練習
練習用PDF・PNG・検証スクリプトをダウンロード(ZIP)。
2026年10月2日に作った架空の文字と模様で、個人情報や実務の資料は含みません。
PythonとWebP対応のPillowが導入済みであることを前提に、展開先でconvert-webp.pyを実行し、続けてcompare-webp.pyを実行する。
未作成のwebp-newへ出力し、元PNGを残す。
対象は8bit RGB/RGBAの静止PNGで、16bitやアニメーションPNGは処理前に拒否する。
lossless=Trueだけでは、完全に透明な画素のRGB値を保持しない場合がある。
exact=Trueを加え、ICCプロファイルとEXIFがあれば渡す。
PNG固有の文字チャンクなどすべての付随情報を保持する例ではないため、元PNGも保管する。
| 2026年10月2日の練習用入力 | PNG | 可逆WebP | 確認結果 |
|---|---|---|---|
| 透明度とsRGBプロファイルを持つalpha.png | 574バイト | 800バイト | RGBAの全画素、ICC、EXIFの向きが一致 |
| 単色のopaque.png | 77バイト | 38バイト | RGBAへ展開した全画素が一致 |
Python 3.12.14・Pillow 12.3.0で実行した。
alpha.pngは可逆WebPのほうが大きくなったため、可逆なら常に半分になるとは扱わない。
同じ透過入力をexactなしで保存すると、完全に透明な部分のRGB値が元と異なることも確認した。
出力フォルダーが存在すると変換前に止まり、既存WebPと元PNGが保持されることを確認した。
途中の失敗では新しいフォルダーが未完成の可能性があるため、原因を確認して別の未作成の出力先でやり直す。
元へ戻すときは保持したPNGと参照URLを使う。
画素が一致しても、表示環境やICCの扱いまで同じとは限らない。
実際の掲載先で透過の縁、文字、小さな図形、色を確認してから差し替える。
設定の仕様はPillowの公式WebP説明で確認できる。
画像の用途から圧縮方式を選ぶ手順
画像に求める性質から順に当てはめると、可逆と非可逆のどちらで変換するかを決められます。2026年9月20日の実測(Python 3.13・Pillow 12.3.0)にもとづく目安です。
- 文字がにじんでは困る、色を正確に伝えたい画像は、元の画素を保つWebPの可逆を選ぶ。
- 読み込みを軽くしたい画像は、非可逆を選ぶ。実測ではPNG比で1割台まで小さくなった。
- 元画像として保管するものは、可逆かPNGのままにして、あとから作り直せるようにする。
- 透過が必要な画像は、WebPが透過に対応しているので可逆・非可逆のどちらでも選べる。
- スクリーンショットや文字入りの図版を非可逆にするときは、輪郭の周りの差を拡大して確認する。
- オンラインの変換を使うなら、可逆と非可逆を選べるか、品質を指定できるか、元のファイルがどこへ送られるかを先に確認する。
置き換える前に、変換後のファイルの見た目とサイズを確かめてください。
まとめ
- 実測では、可逆でPNGの約55%、品質80で約13%まで落ちた
- 9月20日の入力では可逆の画素が一致した。透明部分のRGBまで保持するにはexactなどの設定も確認する。非可逆の差は画像と設定によって変わる
- 文字や図版は可逆、写真は非可逆という分け方が扱いやすい
- オンラインの変換は、ファイルが送信されるかどうかを先に確かめる
- 透過画像はRGBとアルファを別々に確認する。RGBAのgetbbox()の標準設定だけで一致を判定しない
測定は2026年9月20日にPython 3.13とPillow 12.3.0で実行したものである。
画像の中身によって数値は変わるため、自分が扱う画像で測り直してほしい。
WebPの仕様はGoogleの技術資料にまとまっている。
作業を楽にする道具はPCメソッドのまとめにも置いている。
この改訂の練習データとコードは、記事内のZIPから取得できます。
よくある質問:PNGからWebPへの変換で迷ったときのチェックリスト
WebPにすると必ず小さくなりますか?
画像の中身と設定で変わります。実測した文字と単色の面が多い画像(1280×720)では、PNGの82,785バイトに対し、WebP可逆が45,614バイト(55.1%)、品質80が10,986バイト(13.3%)でした。
可逆と非可逆の違いは?
可逆は対応する画素を保持する方式ですが、Pillowで透明部分のRGBまで保持するにはexact=Trueも指定します。ICCなどの付随情報は別途確認が必要です。非可逆は情報を減らして圧縮します。実測では、品質90でも元と一致せず、画素の平均差が1.08、最大差が19でした。
文字入りのスクリーンショットは非可逆でよいですか?
輪郭の周りに差が出やすいため注意が必要です。実測でも、文字と単色の面が多い画像のほうが最大差が大きくなりました。
オンラインの変換サービスで気をつけることは?
元のファイルがどこへ送られるかです。公開前の資料や他人から預かった画像を扱う場合は、送信の有無を先に確かめてください。選択肢がない場合も方式を推測せず、仕様を確認してください。
何枚も変換するときは?
ローカルで一括処理する方法があります。記事のPillowコード自体には画像を外部送信する処理はありません。処理速度はPCや設定によって異なります。
透過のあるPNGもWebPにできますか?
WebPは透過に対応しています。可逆・非可逆のどちらでも変換できますが、変換後に透過が残っているかを確認してください。
