適切な圧縮レベルを選択する

ウェブページ上のダウンロード容量の大半を画像が占めることはよくあり、表示スペースのかなりの部分を画像が占有することも少なくありません。そのため、画像を最適化することでウェブサイトの容量の大幅な削減とパフォーマンスの改善につながることがよくあります。ブラウザでダウンロードする必要がある容量が少ないほど、クライアントの帯域幅における競合は減り、ブラウザで有用なコンテンツをダウンロードして画面にレンダリングするまでの時間も短縮されます。

画像の最適化は芸術でもあり科学でもあります。つまり、個々の画像を最も適切に圧縮する方法について明白な正解がないという点では芸術であり、画像のサイズを大幅に削減できる非常に高度な技術やアルゴリズムがたくさんあるという点では科学なのです。画像に合った最適な設定を見つけるには、フォーマット機能、エンコード データのコンテンツ、画質、ピクセル数など、多くの観点で入念な分析が必要です。

ベクター画像の最適化

最新のブラウザはすべて Scalable Vector Graphics(SVG)をサポートしています。これは、2 次元グラフィック用の XML ベースの画像形式です。SVG マークアップは、ページに直接埋め込むことも、外部リソースとして埋め込むこともできます。ほとんどのベクターベースの描画ソフトウェアで SVG ファイルを作成できます。また、任意のテキスト エディタで直接手作業で作成することもできます。

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.2" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
    x="0px" y="0px" viewBox="0 0 612 792" xml:space="preserve">
<g id="XMLID_1_">
  <g>
    <circle fill="red" stroke="black" stroke-width="2" stroke-miterlimit="10" cx="50" cy="50" r="40"/>
  </g>
</g>
</svg>

上記の例では、シンプルな円形が黒の輪郭線に赤い背景でレンダリングされます。これは Adobe Illustrator からエクスポートされたものです。

<?xml version="1.0" encoding="utf-8"?>

おわかりのように、このファイルには、レイヤ情報、コメント、XML 名前空間など、ブラウザでアセットをレンダリングする際には必要ない多くのメタデータが含まれています。このため、SVGO などのツールを使って SVG ファイルを縮小化することが常に推奨されます。

たとえば、SVGO は、Illustrator によって生成された上記の SVG ファイルのサイズを 58% 削減し、470 バイトから 199 バイトにしました。

<svg version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612 792"><circle fill="red" stroke="#000" stroke-width="2" stroke-miterlimit="10" cx="50" cy="50" r="40"/></svg>

SVG は XML ベースの形式なので、GZIP 圧縮を適用して転送サイズを縮小することもできます。サーバーが SVG アセットを圧縮するように設定されていることを確認してください。

ラスター画像は、単純に個々の「ピクセル」で構成された 2 次元グリッドです。たとえば、100 x 100 ピクセルの画像は 10,000 個のピクセルが並んだものです。そして、各ピクセルには「RGBA」値が格納されています。これは、(R)赤、(G)緑、(B)青、(A)アルファ(透明度)のチャンネルです。

内部処理で、ブラウザはチャンネルごとに 256 の値(シェード)を割り当てます。これは、チャンネルあたり 8 ビット(2^8 = 256)、ピクセルあたり 4 バイト(4 チャンネル x 8 ビット = 32 ビット = 4 バイト)になります。そのため、グリッドの寸法がわかっている場合は、ファイルサイズを簡単に計算できます。

  • 100 x 100 ピクセルの画像は 10,000 ピクセルで構成される
  • 10,000 ピクセル x 4 バイト = 40,000 バイト
  • 40,000 バイト / 1024 = 39 KB
ディメンション ピクセル ファイルサイズ
100 x 100 10,000 39 KB
200×200 40,000 156 KB
300×300 90,000 351 KB
500×500 250,000 977 KB
800 x 800 64 万 2,500 KB

100 x 100 ピクセルの画像で 39 KB であればたいしたことはないと思えるかもしれませんが、画像が大きくなるとファイルサイズは急激に肥大化し、画像アセットのダウンロードに時間も通信コストもかかるようになります。ここまでは「非圧縮」の画像形式についてのみ説明してきました。幸い、画像ファイルのサイズを縮小するための方法はたくさんあります。

シンプルな戦略の 1 つは、画像の「ビット深度」をチャンネルあたり 8 ビットからさらに小さいカラーパレットに縮小することです。チャンネルあたり 8 ビットでは、1 つのチャンネルに 256 の値が割り当てられ、合計で 16,777,216(256 ^ 3)色になります。パレットを 256 色に減らすとどうなるでしょうか。RGB チャンネルには合計 8 ビットのみで済むため、ピクセルあたり即座に 2 バイト削減できます。つまり、元のピクセルあたり 4 バイトの形式からすると 50% の圧縮となります。

圧縮によるアーティファクト
左から右に(PNG): 32 ビット(1,600 万色)、7 ビット(128 色)、5 ビット(32 色)。

徐々に色が変わる複雑なシーン(グラデーションや空など)では、5 ビット アセットの場合に空にピクセルが出現するなど、圧縮による画像の乱れを避けるためには大きいカラーパレットが必要です。逆に、限られた色しか使用していない画像に大きいパレットを使うと、貴重な容量を浪費することになります。

次に、個々のピクセルに保存されているデータを最適化したら、巧みに近接ピクセルも調べてみましょう。つまり、多くの画像、特に写真には、空や繰り返されるテクスチャなど、類似した色の近接ピクセルが多数あることがわかっています。コンプレッサーでは、この情報を利用してデルタ エンコーディングを適用できます。ピクセルごとに個々の値を保存する代わりに、隣接するピクセルの差分を保存できます。隣接するピクセルが同じ場合、デルタは「ゼロ」になり、1 ビットを格納すれば済みます。しかし、これで終わりではありません。

人間の目の感度は色ごとに異なっています。色のパレットを増減することにより、感度の違いを考慮して色のエンコードを最適化することができます。「隣接する」ピクセルは 2 次元のグリッドを構成します。これは、各ピクセルに複数の近傍があることを意味します。この事実を利用して、デルタ エンコードをさらに改善できます。直接隣接するピクセルのみに注目するのではなく、隣接するピクセルで構成されたより大きなブロックに注目し、それぞれのブロックを異なる設定でエンコードします。

ご存じのとおり、画像の最適化はすぐに複雑になり(視点によっては面白いということも)、学術研究や商業研究が盛んに行われています。画像が占める容量は大きいため、優れた画像圧縮技術の開発には大きな価値があります。詳しくは、Wikipedia のページをご覧ください。また、実践例については、WebP 圧縮技術に関するホワイトペーパーをご覧ください。

繰り返しになりますが、どの方法も優れている反面、非常に学術的です。これらは、サイト上の画像を最適化するうえで、どのように役立つのでしょうか。重要なのは、問題の形(RGBA ピクセル、ビット深度、さまざまな最適化手法)を理解することです。各種ラスター画像形式の詳細な説明に入る前に、こうした概念をすべて理解し、留意することが大切です。

可逆画像圧縮と非可逆画像圧縮

ページのソースコードや実行可能ファイルなど、特定の種類のデータでは、圧縮ツールが元の情報を変更したり、失ったりしないことが重要です。データのビットが 1 つ欠落したり、間違っていたりすると、ファイルの内容の意味が完全に変わったり、最悪の場合はファイルが完全に破損したりする可能性があります。画像、音声、動画など、他のタイプのデータについては、元のデータの「概算」表現を提供してもまったく許容されない場合があります。

実際、人間の目の仕組み上、画像のファイルサイズを縮小するために各ピクセルの情報を一部省いてしまっても、通常はまったく差し支えがありません。たとえば、人間の目は色によって感度が異なるため、色によってはわずかなビット数でエンコードできます。そのため、一般的な画像最適化パイプラインは、大きく分けて次の 2 つのステップで構成されます。

  1. 一部のピクセルデータを除去する非可逆フィルタで画像を処理する。
  2. ピクセルデータを圧縮する可逆フィルタで画像が処理されます。

1 つ目の手順は省略可能です。具体的なアルゴリズムは特定の画像形式によって異なりますが、重要なのは、どの画像も非可逆圧縮手順を実施してサイズを圧縮できる、ということです。実際、GIF、PNG、JPEG などのさまざまな画像形式の違いは、非可逆ステップと可逆ステップを適用する際に使用する(または省略する)特定のアルゴリズムの組み合わせにあります。

では、非可逆最適化と可逆最適化の「最適な」設定とはどのようなものでしょうか。答えは、画像の内容と、ファイルサイズと非可逆圧縮によって生じるアーティファクトのトレードオフなど、独自の基準によって異なります。場合によっては、非可逆圧縮をスキップして、複雑なディテールを忠実に伝えることもできます。場合によっては、非可逆最適化を積極的に適用して、画像アセットのファイルサイズを削減できます。その場合は、独自の判断とコンテキストが必要になります。普遍的な設定は存在しません。

実践的な例として、JPEG などの非可逆形式を使用する場合、通常、コンプレッサーはカスタマイズ可能な「品質」設定(Adobe Photoshop の「Save for Web」機能によって提供される品質スライダーなど)を公開します。これは通常、非可逆アルゴリズムと可逆アルゴリズムの特定のコレクションの内部動作を制御する 1~100 の数字です。最良の結果を得るには、画像でさまざまな画質の設定を試し、思い切って画質を下げてみましょう。多くの場合、表示される結果は非常に良好で、ファイルサイズも大幅に削減されます。

画像圧縮が Core Web Vitals に与える影響

画像は Largest Contentful Paint の候補となることが多いため、画像のリソース読み込み時間を短縮すると、ラボ現場の両方で LCP が改善されます。

ラスター画像形式で圧縮設定を試すときは、WebP 形式と AVIF 形式を試して、古い形式と比べて同じ画像を小さなフットプリントで配信できるかどうかを必ず確認してください。

ただし、ラスター画像を過剰に圧縮しないように注意してください。画像最適化 CDN を使用して最適な圧縮設定を見つけるのが良い方法ですが、Butteraugli などのツールを使用して視覚的な違いを推定することで、画像を過度に圧縮して品質を大幅に損なうことを防ぐこともできます。

画像の最適化チェックリスト

以下に、画像の最適化に取り組むうえで留意すべきおすすめの方法やテクニックを紹介します。

  • ベクター形式を優先する: ベクター画像は解像度やスケールに依存しないため、複数端末、高解像度の環境に最適です。
  • SVG アセットを縮小して圧縮する: ほとんどの描画アプリケーションでは、多くの場合、削除可能な不要なメタデータを含んだ XML マークアップを生成します。SVG アセットの GZIP 圧縮を適用するようにサーバーが設定されていることを確認してください。
  • 古いラスター形式よりも WebP または AVIF を優先する: 通常、WebP 画像と AVIF 画像は、古い画像形式よりもはるかに小さくなります。
  • 最適なラスター画像形式を選ぶ: 機能要件を定義し、個々のアセットに適した形式を選択します。
  • ラスター形式の最適な品質設定を試す: ためらわずに「画質」設定を下げると、多くの場合、結果は非常に良好で、バイトも大幅に削減されます。
  • 不要な画像メタデータを削除する: 多くのラスター画像には、地理情報、カメラ情報など、アセットに関する不要なメタデータが含まれています。適切なツールを使用してこのデータを取り除いてください。
  • スケーリングした画像を提供する: 画像のサイズを変更し、「表示」サイズが画像の「自然」サイズにできるだけ近くなるようにします。大きい画像はサイズ変更に伴うオーバーヘッドの大半を占めているため、特に注意してください。
  • 自動化、自動化、自動化: すべての画像アセットが常に最適化されるよう、自動化ツールとインフラストラクチャに投資します。