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

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

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

ベクター画像の最適化

最新のブラウザはすべて 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 x 500 250,000 977 KB
800 x 800 640,000 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 形式をテストして、古い形式と比較して同じ画像を小さいフットプリントで配信できるかどうかを確認してください。

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

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

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

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