深掘り

WebPの誕生:VP8が画像フォーマットになるまで

koboshiCo-founder
·9 分で読めます
WebPの誕生:VP8が画像フォーマットになるまで
要約

WebPはVP8 video frameをstill imageに転用したRIFF-based containerである。Googleは2010年にJPEGとPNGより25-34%のファイルサイズ削減を謳って発表した。ファイルシグネチャから実世界の採用格差まで、完全な技術的解説をここに示す。

WebPファイルを十六進エディタで開く。最初の12バイトは:

52 49 46 46 ?? ?? ?? ?? 57 45 42 50

これはRIFF/WAVE スタイルのコンテナヘッダーだ。52 49 46 46はASCIIで"RIFF"を表す。次の4バイトはリトルエンディアンの符号なし32ビット整数(uint32)によるファイルサイズ。57 45 42 50はASCIIで"WEBP"を表す。WebPファイルは生ビットストリームではない。コンテナであり、WAV オーディオやAVI ビデオと同じように、1991年にMicrosoftが発表したRIFF 仕様書から構築されている。そのコンテナの内部には、静止画像に転用されたVP8 動画フレームが収まっている。この設計選択——動画コーデックを写真に用いること——は、WebPを理解する上で最も重要な点である。

Googleは2010年9月30日にWebPを発表した。売り文句は単純だった:JPEGと同等の画質で、25-34%のファイルサイズ削減。PNGに対してはさらに大胆な主張——可逆画像で26%のサイズ削減——であった。画像データが転送量の約半数を占めるウェブにおいて、これらの数字は広汎な採用を引き起こすには十分なはずだった。そうはならなかった。

WebPを生んだ買収

WebPは画像研究所から生まれたわけではない。動画コーデックから生まれたのだ。

2010年2月、GoogleはOn2 Technologiesを約1億2,400万ドルで買収した。On2は長い歴史を持つ動画圧縮企業であり、同社のコーデックはFlash video、Skypeのビデオ通話、AOLのストリーミングを支えていた。同社の主力製品はVP8であり、特許使用料なしでH.264と競合するよう設計された動画コーデックであった。

Googleは2010年5月にVP8をWebMという名前でオープンソース化し、Vorbis オーディオコーデックおよびMatroska コンテナとバンドルした。目標は明確だった:特許フリーの動画スタックを構築し、ウェブ動画ストリーミングから使用料を要求し始めていたMPEG-LAのH.264 ライセンスプールに対抗すること。

しかしGoogleは2つ目のユースケースも考えていた。VP8のイントラフレーム圧縮——他のフレームを参照せずに単一の動画フレームを圧縮すること——は、本質的には静止画像コーデックであった。動画を効率的にしたものと同じ予測モード、変換符号化、エントロピー符号化が、写真にも機能した。Googleはイントラフレームモードを抽出し、RIFF コンテナでラップして、それをWebPと名付けた。

名前はマーケティング上の選択だった。"Web"はウェブ向けに設計されたから。"P"は画像フォーマットがPで終わるから——JPEG、PNG、BMP、TIFF。結果として生まれたのは、技術的には動画フレームでありながら静止画像として振る舞うフォーマットであった。

なぜ新しいフォーマットを作る必要があったのか

2010年時点で、JPEGは18歳、PNGは14歳だった。両者とも盤石だった。なぜわざわざ?

JPEGの限界は実在し、周知の事実だった:

  • 透過がない。JPEGのピクセルは完全に不透明か、別のマスクが必要だ。
  • アニメーションがない。アニメーション JPEGは標準として存在しない。
  • 非可逆のみ。JPEGのベースライン仕様には可逆モードがない。(JPEG-LSとJPEG 2000は存在するが、いずれもウェブ互換ではない。)
  • チャンネルあたり8ビットの色深度。ベースラインでは広色域やHDRをサポートしない。
  • 低品質時のブロッキングノイズ。8×8 DCT グリッドは画質設定75未満で目立つ。

PNGの限界も同様に実在した:

  • 非可逆モードがない。PNGは常に可逆である。1200万画素の写真をPNGで保存すると15-25MBになる。
  • 写真ではファイルサイズが大きい。PNGのDEFLATE圧縮は、DCTベースの心理視覚的破棄と競合できない。
  • 基本仕様にアニメーションがない。APNGは存在するが、ブラウザサポートを得るには数年を要した。

Googleは空隙を見出した:非可逆および可逆圧縮、透過、アニメーションを単一のフォーマットで実現し、既存フォーマットより小さいファイルサイズで。それがWebPの売り文句だった。

WebPの実際の動作

WebPには、根本的に異なる2つの内部フォーマットがある:非可逆 WebP(VP8 イントラフレーム)と可逆 WebP(別のコーデックであり、VP8の研究からも派生している)。

非可逆 WebP: VP8 イントラ

非可逆 WebPはRIFF コンテナ内にVP8 ビットストリームを格納する。エンコーディングパイプラインは概念的にはJPEGと似ているが、重要な違いがある:

段階JPEG非可逆 WebP
変換8×8 DCT4×4 または 16×16 整数 DCT 類似変換
予測なし(イントラのみ)4×4 ブロックあたり4つのイントラ予測モード
クロマサブサンプリング4:2:0 デフォルト4:2:0 デフォルト
エントロピー符号化ハフマンバイナリ算術符号化
ビット深度8ビット8ビット

イントラ予測が最大の利点だ。JPEGは各8×8 ブロックを独立してエンコードする。WebPは各4×4 ブロックを、既にエンコードされた隣接ブロック——上、左、あるいは両方——から予測し、予測誤差のみをエンコードする。滑らかなグラデーションや大きな平坦領域では誤差は極めて小さく、圧縮率は大幅に改善する。

算術符号化器はJPEGのハフマン符号化よりも効率的であり、同じ画質で通常5-10%さらに削減できる。

Google自身の2010年のベンチマークは以下を主張した:

指標WebP vs JPEG
平均ファイルサイズ削減同等SSIMで25-34%
エンコード速度libjpegより約8倍遅い
デコード速度libjpegと同等

エンコード速度は見えにくいコストだった。WebPファイルを生成するにはJPEGより大幅に多くのCPUを必要とした。数百枚の画像を書き出す写真家にとって、それは重大な問題だった。

可逆 WebP

可逆 WebPは完全に異なるコーデックを使用する。VP8ではない。以下を組み合わせた独自フォーマットだ:

  • 予測符号化: ピクセルあたり14の異なる空間予測モード。
  • カラーキャッシュ: 局所的な繰り返しを利用するため、最近表示された色のハッシュテーブル。
  • LZ77 後方参照: PNGのDEFLATEのようだが、2次元の空間認識型マッチングを持つ。
  • ハフマン+算術ハイブリッド: エントロピー符号化が局所統計に適応する。

Googleは平均でPNGより26%のファイルサイズ削減を主張した。実際には削減率は大きく異なる——大きな平坦領域を持つ単純なグラフィックではほとんど効果がないが、細かいテクスチャを持つ写真では30-40%の削減が見られる。

拡張 WebP (VP8X)

VP8X チャンクはWebPに以下の追加機能を提供する:

  • アルファチャンネル: 8ビットアルファが別途エンコードされ、可逆 WebPのエントロピー符号化器で圧縮される。
  • アニメーション: タイミングメタデータを持つ複数のフレーム。本質的には簡略化されたVP8 動画。
  • EXIF メタデータ: カメラおよび位置情報データ。
  • XMP メタデータ: Adobe形式の処理命令。
  • ICC カラープロファイル: 広色域およびHDRのカラーマネジメント。

VP8XファイルはVP8X チャンクヘッダーで始まり、どの拡張機能が存在するかを示すフラグが続く。

ファイルフォーマット

WebPはRIFF コンテナである。RIFFを知っていれば、バイトレイアウトを理解するのは簡単だ。

RIFF コンテナ構造

Bytes 0-3:   "RIFF" (0x52 0x49 0x46 0x46)
Bytes 4-7:   File size - 8 (little-endian uint32)
Bytes 8-11:  "WEBP" (0x57 0x45 0x42 0x50)
Bytes 12-15: Chunk FourCC — "VP8 ", "VP8L", or "VP8X"
Bytes 16-19: Chunk size (little-endian uint32)
Bytes 20+:   Chunk data

VP8X 拡張ヘッダー

バイト12-15のFourCCが"VP8X" (0x56 0x50 0x38 0x58)の場合:

Bytes 20-23: Chunk size = 10 (little-endian uint32)
Bytes 24:    Flags byte
             Bit 0: Animation present
             Bit 1: XMP metadata present
             Bit 2: EXIF metadata present
             Bit 3: Alpha channel present
             Bit 4: ICC profile present
             Bits 5-7: Reserved
Bytes 25-27: Canvas width - 1 (little-endian uint24)
Bytes 28-30: Canvas height - 1 (little-endian uint24)

キャンバスサイズはwidth - 1およびheight - 1として格納される。したがって1200×675の画像は1199674を格納する。最大キャンバスサイズは16,777,215×16,777,215ピクセルである。

チャンク種別

FourCC内容圧縮方式
VP8 VP8 ビットストリーム(非可逆)VP8 イントラ
VP8LVP8L ビットストリーム(可逆)独自可逆
VP8X拡張ヘッダー+フラグなし
ALPHアルファチャンネルデータ可逆 WebP エントロピー
ANMFアニメーションフレームフレームごとにVP8/VP8L
ICCPICC カラープロファイルなし
EXIFEXIF メタデータなし
XMP XMP メタデータなし

ファイルシグネチャの読み取りによるWebPの検出

.webpファイル拡張子を信頼するな。最初の16バイトを読み取り、RIFF ヘッダーを解析する。

単純な非可逆 WebPの正確なバイトレイアウト:

Bytes 0-3:   "RIFF"
Bytes 4-7:   File size (little-endian uint32)
Bytes 8-11:  "WEBP"
Bytes 12-15: "VP8 " (lossy) or "VP8L" (lossless) or "VP8X" (extended)

ブラウザでのTypeScript:

interface WebPInfo {
  valid: boolean
  type: "lossy" | "lossless" | "extended" | "unknown"
  width?: number
  height?: number
  hasAlpha?: boolean
  isAnimated?: boolean
}

async function inspectWebP(file: File): Promise<WebPInfo> {
  const buffer = await file.slice(0, 30).arrayBuffer()
  const bytes = new Uint8Array(buffer)

  if (bytes.length < 12) return { valid: false, type: "unknown" }

  const riff = String.fromCharCode(...bytes.slice(0, 4))
  const webp = String.fromCharCode(...bytes.slice(8, 12))
  if (riff !== "RIFF" || webp !== "WEBP") {
    return { valid: false, type: "unknown" }
  }

  const type = String.fromCharCode(...bytes.slice(12, 16))

  if (type === "VP8 ") {
    // Lossy: width/height at bytes 26-29
    const w = bytes[26] | (bytes[27] << 8)
    const h = bytes[28] | (bytes[29] << 8)
    return { valid: true, type: "lossy", width: w, height: h, hasAlpha: false }
  }

  if (type === "VP8L") {
    // Lossless: dimensions packed in bits of bytes 21-24
    const bits =
      bytes[21] | (bytes[22] << 8) | (bytes[23] << 16) | (bytes[24] << 24)
    const w = (bits & 0x3fff) + 1
    const h = ((bits >> 14) & 0x3fff) + 1
    const alpha = ((bits >> 28) & 0x01) !== 0
    return {
      valid: true,
      type: "lossless",
      width: w,
      height: h,
      hasAlpha: alpha,
    }
  }

  if (type === "VP8X") {
    const flags = bytes[20]
    const w = (bytes[24] | (bytes[25] << 8) | (bytes[26] << 16)) + 1
    const h = (bytes[27] | (bytes[28] << 8) | (bytes[29] << 16)) + 1
    return {
      valid: true,
      type: "extended",
      width: w,
      height: h,
      hasAlpha: (flags & 0x10) !== 0,
      isAnimated: (flags & 0x02) !== 0,
    }
  }

  return { valid: false, type: "unknown" }
}

Python

import struct
from typing import TypedDict

class WebPInfo(TypedDict):
    valid: bool
    type: str
    width: int | None
    height: int | None
    has_alpha: bool | None
    is_animated: bool | None

def inspect_webp(path: str) -> WebPInfo:
    with open(path, "rb") as f:
        header = f.read(30)

    if len(header) < 12:
        return {"valid": False, "type": "unknown"}

    if header[:4] != b"RIFF" or header[8:12] != b"WEBP":
        return {"valid": False, "type": "unknown"}

    chunk_type = header[12:16]

    if chunk_type == b"VP8 ":
        w, h = struct.unpack("<HH", header[26:30])
        return {"valid": True, "type": "lossy", "width": w, "height": h,
                "has_alpha": False, "is_animated": None}

    if chunk_type == b"VP8L":
        bits = struct.unpack("<I", header[21:25])[0]
        w = (bits & 0x3FFF) + 1
        h = ((bits >> 14) & 0x3FFF) + 1
        alpha = ((bits >> 28) & 0x01) != 0
        return {"valid": True, "type": "lossless", "width": w, "height": h,
                "has_alpha": alpha, "is_animated": None}

    if chunk_type == b"VP8X":
        flags = header[20]
        w = struct.unpack("<I", header[24:27] + b"\x00")[0] + 1
        h = struct.unpack("<I", header[27:30] + b"\x00")[0] + 1
        return {"valid": True, "type": "extended", "width": w, "height": h,
                "has_alpha": bool(flags & 0x10), "is_animated": bool(flags & 0x02)}

    return {"valid": False, "type": "unknown"}

Pillowを使う高レベルな方法:

from PIL import Image

with Image.open("image.webp") as img:
    print(img.format)      # WEBP
    print(img.mode)        # RGB or RGBA
    print(img.size)        # (width, height)
    print(img.is_animated) # True if animated

またはwebpライブラリを使う方法:

import webp

info = webp.WebPInfo("image.webp")
print(info.width, info.height, info.has_alpha)

Go

package main

import (
	"encoding/binary"
	"fmt"
	"os"
)

type WebPInfo struct {
	Valid       bool
	Type        string
	Width       int
	Height      int
	HasAlpha    bool
	IsAnimated  bool
}

func inspectWebP(path string) (WebPInfo, error) {
	f, err := os.Open(path)
	if err != nil {
		return WebPInfo{}, err
	}
	defer f.Close()

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

	if string(buf[:4]) != "RIFF" || string(buf[8:12]) != "WEBP" {
		return WebPInfo{Valid: false, Type: "unknown"}, nil
	}

	typeStr := string(buf[12:16])
	switch typeStr {
	case "VP8 ":
		w := int(binary.LittleEndian.Uint16(buf[26:28]))
		h := int(binary.LittleEndian.Uint16(buf[28:30]))
		return WebPInfo{Valid: true, Type: "lossy", Width: w, Height: h, HasAlpha: false}, nil
	case "VP8L":
		bits := binary.LittleEndian.Uint32(buf[21:25])
		w := int(bits&0x3FFF) + 1
		h := int((bits>>14)&0x3FFF) + 1
		alpha := ((bits >> 28) & 0x01) != 0
		return WebPInfo{Valid: true, Type: "lossless", Width: w, Height: h, HasAlpha: alpha}, nil
	case "VP8X":
		flags := buf[20]
		w := int(binary.LittleEndian.Uint32(append(buf[24:27], 0))) + 1
		h := int(binary.LittleEndian.Uint32(append(buf[27:30], 0))) + 1
		return WebPInfo{
			Valid: true, Type: "extended", Width: w, Height: h,
			HasAlpha: (flags & 0x10) != 0, IsAnimated: (flags & 0x02) != 0,
		}, nil
	}

	return WebPInfo{Valid: false, Type: "unknown"}, nil
}

PHP

function inspectWebP(string $path): array {
    $header = file_get_contents($path, false, null, 0, 30);
    if (strlen($header) < 12) {
        return ["valid" => false, "type" => "unknown"];
    }

    if (substr($header, 0, 4) !== "RIFF" || substr($header, 8, 4) !== "WEBP") {
        return ["valid" => false, "type" => "unknown"];
    }

    $type = substr($header, 12, 4);

    if ($type === "VP8 ") {
        $w = unpack("v", substr($header, 26, 2))[1];
        $h = unpack("v", substr($header, 28, 2))[1];
        return ["valid" => true, "type" => "lossy", "width" => $w, "height" => $h, "has_alpha" => false];
    }

    if ($type === "VP8L") {
        $bits = unpack("V", substr($header, 21, 4))[1];
        $w = ($bits & 0x3FFF) + 1;
        $h = (($bits >> 14) & 0x3FFF) + 1;
        $alpha = (($bits >> 28) & 0x01) !== 0;
        return ["valid" => true, "type" => "lossless", "width" => $w, "height" => $h, "has_alpha" => $alpha];
    }

    if ($type === "VP8X") {
        $flags = ord($header[20]);
        $w = unpack("V", substr($header, 24, 3) . "\x00")[1] + 1;
        $h = unpack("V", substr($header, 27, 3) . "\x00")[1] + 1;
        return [
            "valid" => true, "type" => "extended",
            "width" => $w, "height" => $h,
            "has_alpha" => (bool)($flags & 0x10),
            "is_animated" => (bool)($flags & 0x02),
        ];
    }

    return ["valid" => false, "type" => "unknown"];
}

fileinfoを使う方法:

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

ImageMagick CLI

magick identify -verbose image.webp | grep "Format:"
# Format: WEBP (WebP Image Format)

完全なメタデータ抽出:

magick identify -verbose image.webp

これは幅、高さ、色深度、アルファ有無、圧縮方式、およびICC プロファイル情報を出力する。

または単純に:

file image.webp
# image.webp: RIFF (little-endian) data, Web/P image

強み

WebPは特定の観点で技術的に優秀だ:

より小さいファイル: Googleの参照コーパスにおいて、非可逆 WebPは同等のSSIMでJPEGより平均25-34%小さかった。可逆 WebPはPNGより平均26%小さかった。高トラフィックサイトにとって、これらの削減は帯域コストと高速なページ読み込みに直接結びつく。

機能の統合: 1つのフォーマットが、ほとんどのユースケースでJPEGとPNGの両方を代替する。写真には非可逆モード、グラフィックには可逆モード、透過にはアルファチャンネル、短いシーケンスにはアニメーション。ウェブ開発者は3つではなく1つのフォーマットを知る必要がある。

ブラウザネイティブデコード: Chrome、Firefox、Safari、Edgeはすべてハードウェアアクセラレーションまたは高度に最適化されたソフトウェア WebP デコーダーを搭載している。デスクトップではデコード速度はJPEGと同等であり、モバイルでは10-20%の範囲内だ。

プログレッシブデコード: WebPはデータ到着に伴う段階的な表示をサポートしており、JPEGのプログレッシブモードと同様だ。遅い接続では、ファイルの約30%を受信した時点で認識可能な画像が表示される。

アニメーション: アニメーション WebPファイルは、同等の視覚品質でアニメーション GIFより通常60-80%小さく、フレームごとにフル24ビットカラーおよび8ビットアルファを持つ。

弱み

WebPの問題は技術的ではない。生態学的なものだ。

エンコード速度: 2010年、WebPのエンコードはlibjpegの約8倍遅かった。差は縮まっている——2026年のlibwebpはlibjpeg-turboの約2-3倍遅い——だが、バッチ処理ワークフローにおいて依然として重要だ。1,000枚の画像を書き出す写真家は、明らかに長く待つことになる。

16ビットやHDR非対応: WebPは厳密にチャンネルあたり8ビットである。広色域写真、医用画像、HDRコンテンツにとって、WebPは使用できない。HEIC、AVIF、JPEG XLはすべてより高いビット深度をサポートしている。

可逆 JPEG 再圧縮なし: JPEG XLは既存のJPEGを取得し、可逆に再圧縮して約20%の削減が可能だ。WebPはできない。JPEGをWebPに変換するには完全な再エンコーディングが必要であり、世代劣化が生じる。

ツールの欠如: PhotoshopがWebPをネイティブにサポートしたのは2022年まで待たなければならなかった。ImageMagickのWebPサポートはlibwebp プラグインのコンパイルを必要とし、多くのディストリビューションがデフォルトで除外していた。多くのコンテンツ管理システムは依然としてデフォルトでJPEG/PNGを生成している。

VP8の特許の曖昧性: Googleは特許補償の約束とともにVP8をリリースしたが、そのコーデックの特許状況はPNGやJPEGほどクリーンではなかった。一部の組織は、Googleの法的保護が裁判で持ちこたえるか信頼できないという理由で、特にWebPを避けた。

なぜ「劣った」フォーマットが勝ったのか

JPEGは34歳だ。透過がなく、アニメーションがなく、可逆モードがなく、画質75で目に見えるノイズがある。WebPはほぼすべての指標でJPEGを上回る。しかし、2025年のWeb Almanacは、すべてのウェブ画像のうちJPEGが約46%、WebPが**19%**としている。

理由は技術的ではない。ネットワーク効果と移行コストだ。

JPEGは画像フォーマットのQWERTYだ。すべてのカメラがデフォルトでJPEGを保存する。すべての電話がJPEGをネイティブに表示する。すべてのプリンターがJPEGを受け入れる。すべてのソーシャルネットワーク、CMS、CDN、メールクライアントが、プラグイン、コーデック、変換なしでJPEGを処理する。このフォーマットはあまりにも普遍的であり、「画像」と「JPEG」はほとんどのユーザーにとって機能的に同義語となっている。

WebPの採用曲線が物語っている:

マイルストーン
2010GoogleがWebPを発表(Chrome 8)
2012Chrome 23が可逆およびアルファサポートを追加
2013Chromeがアニメーション WebPを追加
2014Android 4.0+がネイティブ WebP サポートを追加
2015Facebookがすべてのモバイル写真をWebPに変換
2016Safari 14がWebP サポートを追加
2020全ブラウザ対応の達成
2022Photoshopがネイティブ WebP エクスポートを追加
2025Web AlmanacによるとWebPがウェブ画像の19%に到達

Chromeは積極的にWebPを推進した。Googleがブラウザとフォーマットの両方を支配していたからだ。Facebookはペタバイト単位の帯域を節約できたから採用した。しかしウェブのロングテール——WordPressブログ、小規模eコマースサイト、エンタープライズCMSデプロイメント、メールニュースレター——は遅く動いたか、まったく動かなかった。

決定的な失敗点はAppleのエコシステムだった。iPhoneはデフォルトでHEICを保存し、WebPではない。macOS PreviewはmacOS 11 Big Sur(2020年)までWebPをサポートしなかった。iOSの共有シートはWebP エクスポートを提供しなかった。Appleデバイスを主要に使用する写真家、デザイナー、ソーシャルメディアクリエイターにとって、WebPは存在しないものだった。

AVIFは2019年に登場し、WebPより優れた圧縮率とAlliance for Open Mediaからのロイヤリティフリーライセンスを持っていた。Chrome、Firefox、SafariはすべてAVIFを搭載している。CloudflareとCloudinaryは自動的にAVIFを配信する。WebPは踏み台となった——JPEGより優れているが、すでに次世代に飛び越されている。

現在のWebPの立ち位置

WebPは失敗ではない。部分的な成功だ。

2026年に新しいプロジェクトを構築するウェブ開発者にとって、WebPは透過やアニメーションを必要とする画像にとって実用的なデフォルトである。可逆グラフィックではPNGより小さく、写真ではJPEGより小さい。ブラウザサポートは普遍的だ。エンコードツールは成熟している。

しかしWebPはJPEGを置き換えなかった。JPEGの隣にニッチを切り開いた——PNGがすでに確保していたのと同じニッチだが、より小さいファイルで。「すべての画像に対する1つのフォーマット」というビジョンは実現しなかった。

2026年の現実:

ユースケース最適なフォーマット理由
写真(レガシー)JPEG普遍的、高速エンコード、十分に小さい
写真(新規)AVIFWebPより30%小さい、ロイヤリティフリー
写真(フォールバック)WebPJPEGより25%小さい、ユニバーサルサポート
可逆グラフィックWebPまたはPNGWebPの方が小さい;PNGは安全なフォールバック
透過WebPまたはPNGWebPの方がファイルサイズが小さい;PNGは安全なフォールバック
アニメーションWebPまたはAVIFいずれもGIFより60-80%優位;AVIFはより新しい
広色域/HDRAVIFまたはJPEG XL10ビット以上の色深度、ICC/ICC v4 サポート
印刷ワークフローTIFFまたはJPEG XLCMYK、16ビット、可逆 JPEG 再圧縮

WebPの真の遺産は、主要なブラウザベンダーが十分に推進すればウェブは新しい画像フォーマットを採用できることを証明したことだ。AVIFの道を切り開いた。Appleにnon-JPEG/PNGフォーマットのネイティブサポートを迫った。透過とアニメーションが単一のコンテナに属することを示した。

しかし、技術的優位性だけでは不十分であることも証明した。普遍性、慣性、エコシステムの整合性は、圧縮率より重要だ。JPEGがWebPを生き残るのは、JPEGが優れているからではなく、すでにどこにでもあるからだ。

結論

WebPは帯域問題を解決するために動画コーデックから構築された。その問題は解決した——Googleにとっても、Facebookにとっても、画像パイプラインを変換しようとするあらゆるサイトにとっても。圧縮は本物であり、機能は有用であり、ブラウザサポートは完全だ。

しかし、ウェブはホワイトペーパーが新しいフォーマットが25%小さいと言ったからといってフォーマットを切り替えない。新しいフォーマットが古いものより使いやすくなった時、あるいは古いものがあまりにもひどく失敗して移行が避けられなくなった時に切り替わる。JPEGはあまりにもひどく失敗しなかった。WebPはあまりにも使いやすくならなかった。そしてWebPが使いやすくなった頃には、AVIFがすでに仕様書上でより大きな数字を持って到着していた。

WebPは画像フォーマットのBetamaxだ——技術的に堅実で、十分にサポートされ、最終的にはわずかに遅れて到着した、より優れたマーケティングと広範な支援を持つ後継者に追い越された。消滅することはない。JPEG、PNG、AVIF、そして次に来るものと共存し、今日PNGが果たしているのと同じ役割——どこでも動作する安全で有能なフォールバック——を担うだろう。

ウェブ用により小さいフットプリントが必要なPNGファイルがある場合、PNG to WebPはブラウザ内でローカルに変換する——アップロードなし、サーバー処理なし。透過やアニメーションが必要なJPEGの場合、JPG to WebPが画質管理付きで変換を処理する。そして普遍的なフォールバックが必要な場合、WebP to PNGWebP to JPGはWebPファイルをあらゆるビューアで開けるフォーマットに戻す。

その他のおすすめ記事