Experts.jp日本に、もっとエキスパートを。(2)画像は、サイズが大きい(大きくなりがちな)コンテンツの一つです。最近は画像を使わないページはほとんどなく、むしろ使う量はどんどん増えているんじゃないでしょうか。HiDPI対応などでサイズも増えつつあるでしょう。Googleの調査では、現在Web上のトラフィックの65%を画像が占めているそうです。Introで解説したように、パフォーマンスを考えるとファイルサイズは「なるべく小さく」が望ましいため、画像は通常圧縮された形式で使用されます。WebPは、Googleが開発した圧縮形式で、従来の形式よりもファイルサイズを小さくすることを目的としています。今回はそんなWebPの概要と使い方、注意点を取り上げます。画像圧縮とは?ここで対象としているのはピクセル形式の画像で、ざっくり言うと「1pxごとにそこが何色なのか」という情報を持つ形式です。Windowsのペイントなどで作れるBitmap(.bmp)という形式がなじみ深いでしょうか。ところが、例えば以下の画像を見て下さい、同じ色が連続している場所があります。そこで、「このピクセルは赤、このピクセルも赤...」と繰り返す情報を、「ここからここまで赤」と置き換えると、同じ情報を小さく表せるはずです。このように、同じ情報を小さく表現する方法を圧縮といいます。これを画像に適用したのが画像圧縮です。上の図の方法は逆の計算をすれば元の画像が完全に復元できるため、「可逆圧縮(lossless)」といいます。写真などにはものすごく細かい色の変化もあり、なくなっても人間は気づかれない場合が多いので、こうしたデータを捨てることで圧縮率を上げる方法もとられます。代わりに、完全には元に戻せなくなるため、この方法は「非可逆圧縮」と呼ばれます。この例は、あくまでもイメージで、実際には同じ情報を小さく表わす方法はいろいろとあり、それにより圧縮形式が異なります。次によく使われる圧縮形式を見てみましょう。圧縮形式Webの世界では、現在以下の三つがよく使われています。色数が少ないアイコンなどに有効、アニメーションが可能。これらの形式を場合に応じて使い分けているわけですが、Googleは多くの場合にこれらの形式よりも小さく圧縮でき、透過やアニメーションなどの機能もそろった新しい圧縮形式を開発しました。それが、WebPです。WebP読み方は、Weppy=ウェッピーです。ファイルの構造としては、同じくGoogleが持つVP8コーデックを用いたWebMという動画フォーマットをベースとしており、WebMの1フレームだけを切り出したものがWebPで、それをRIFFという軽量なコンテナに格納した形式になっています。https://developers.google.com/speed/webp/WebPは以下のような特徴があります。写真の圧縮にも向いているアニメーションが可能カラープロファイル対応メタデータを持たせることができる画像に求められる基本的な機能をひと通り備えており、一つのフォーマットで幅広い用途で利用できるように作られていることがわかります。Storeなどがサポートしており、Facebookもサポートを始めました。現在、以下のブラウザがWebPに対応*2しています。AndroidFirefoxでは議論中で、IEやSafariは対応していません。したクライアントを対象とする場合は、後ほど説明するフォールバックが必要になります。http://caniuse.com/webpツールWebPは以下のような公式のライブラリ、オーサリングツールなどで生成することができます。Pluginimg2webp.netしかし、FacebookがWebPをサポートしたところ、ユーザから「画像をダウンロードしたら、編集ソフトで編集できなかった」というクレームがあったというニュースがありました。これは、上記のようなメジャーなものを除いて、まだWebPに対応していないオーサリングツールが多くあることを意味しています。OSのデフォルトのプレビューでは見れないため、Webから落とした後のことも考えるのであれば、代替手段として同じ画像のPNGやJPEGをダウンロードする手段を用意することが望ましいでしょう。Library今回はWebP公式ライブラリに同梱されたCLIツールを用いて、実際に画像をWebPに変換してみます。公式ライブラリは以下のページで公開されています。WebPここには以下のツールと、開発用のライブラリが含まれます。変換これらのツールはかなりたくさんのオプションがあります。詳細はドキュメントを参照ください。ここでは、使い方の解説を兼ねてPNG、JPEG、GIFとの簡単な比較をしてみます。PNGファイルと比べてみます。対象はPNGがよく使われるWebのUIアイコンとして、下記のPNGをもとにWebPに変換したものを比較します。JEPGファイルと比べてみます。対象はJPEGがよく使われる写真として、おなじみlennaさんのPNGをもとに、ImageMagickでJPEGに変換したものとWebPに変換したものを比較します。KBアニメーション5つのJPEG画像をもとに、500msごとに切り替えるアニメーションをGIFとWebPで作って比較します。KB残念ながら執筆時点では、WebPアニメーションを表示できるブラウザはないため、上記は表示されてないかもしれません。その場合はvwebpコマンドで表示できます。animation.webpGIFは色数が少ないため、写真を元にするとざらついた画質になりますが、WebPは比較して綺麗なアニメになっていることが分かると思います。圧縮解凍の速度WebPは圧縮率を上げるために、以下の追加コストがかかります。倍程度のコスト特に圧縮は大きな差に感じます。画像は一般的に一度作られたら更新されることが少ないリソースであり、圧縮が必要なのは一回ですが、参照される機会が多いのが特徴です。WebPは多少時間をかけて、じっくりと小さく圧縮することを選択しています。CPU資源は、サーバ側はサービスの規模に応じて投資してコントロールできますし、クライアント側は最近はモバイル端末ですらそれなりの処理性能を持っています。ネットワーク資源は、サーバとクライアント間で状況により変わり、サービス側の投資だけではコントロールしきれないという特徴があります。したがって、圧縮/解凍にかかる時間よりも、ファイルを小さくすることを選択するほうが、現在のWebを取り巻く環境を考えると妥当な場合が多いと考えられます。動的に画像を生成するようなサービスでは、従来のフォーマットと比べるなどの検証が必須になるでしょう。(P.13)フォールバック執筆時点では対応するブラウザは限られています。従ってWebP非対応のブラウザのためにはPNGなどへのフォールバックを検討する必要があります。対応方法は主に以下があります。判別クライアント・サーバ間での対応フォーマットの確認は、通常HTTP1.1のコンテントネゴシエーションという機能を用いて行います。具体的には、WebPに対応したブラウザは、画像のリクエストのAcceptヘッダにimage/webpを付与することが求められており、サーバはこの値をもとにクライアントの対応を知ることができます。手元のChrome29では、HTML中のimgタグのリクエストに以下のヘッダが確認できました。この方法は、クライアントとサーバの間にキャッシュサーバが入る場合に注意が必要です。同じURLから取得できるコンテンツがクライアントによって異なるので、キャッシュが共有されることで問題が起こる可能性があるためです。これを防ぐためには、キャッシュに「Acceptヘッダによって、配信するソースが違う」ということを教えるためにVaryヘッダを付与します。(この情報はGoogleのBotなどがコンテンツ内容を把握する上でも重要です。Acceptコンテントネゴシエーションをサーバに設定する例は、webp-detectが参考になります。User-Agentでの判別Chrome29は先のように、imgタグに対してimage/webpを送っていましたが、直接画像のURLにアクセスした場合は送っていません。送信するブラウザもあり、Acceptヘッダだけで判別するのは難しい場合があります。画像サイズを減らしているのに、Acceptヘッダに新しい情報を追加してしまっては、クライアントからサーバへ送信する情報を増やします。その理由から全てのブラウザが、今後Acceptヘッダを対応をするかどうかはまだ分かりません。*3こうしたブラウザ場合は、対応をUser-Agentから判断することもできます。ソースが参考になります。HTTP/2.0では、HPACKというヘッダの送受信を効率化する方式が採用される見通しであり、ヘッダへの情報追加によるオーバーヘッドは、HTTP/1.1に比べて減らせる可能性があります。サンプル以下は、ここまでの判別方法を元に、Nginxでブラウザの対応に応じて切り替える例です。対応している場合はlogo.webpを、非対応の場合はlogo.pngをレスポンスしています。last;}実際に以下のリンクで動作を確認できます。(対応ブラウザはWebP、非対応はPNG画像が返ってきます)https://jxck.io/labs/webp/logoHTMLごと切り替えるlogo.webpとlogo.pngのURLを明示的に分けたい場合は、それらを含むHTMLをまるごと切り替える方が良い場合もあります。src="/logo.png"></html>この場合も、User-Agentによって切り替え、Varyヘッダを付与するとよいでしょう。以下のヘッダを付与することでキャッシュの共有を限定してしまう方法もあります。WebPに対応しないクライアントでそれを開くと中身を見ることはできません。した状況を想定するならUser-Agentも併用する必要があるでしょう。JavaScriptでフォールバックする方法まず、Modernizr.jsには、ブラウザのWebPサポートを調べる機能があります。これを用いて、読み込む画像をJavaScriptで動的に切り替えることができます。いうライブラリもあります。これを用いると、WebMに対応したFireFoxでもWebPが表示できます。width="500">より強力なライブラリとして、WebPのデコードをJSでやってしまうwebp.jsというライブラリもあります。こちらは、なんとIE6以降でほぼ全てのブラウザに対応しています。src="js/webpjs-0.0.2.min.js"></script>まとめ画像を効率よく圧縮できれば帯域を節約でき、特にモバイル対応の場合は全体のパフォーマンスに大きく影響が出ます。WebPはこの点を解消するために生まれ、圧縮率等に関しては一定の成果を出していると言えるでしょう。普及しきっていないため、フォールバックなど考慮すべき点もあります。フォールバックのために施した対策のために、WebPで得られた以上のオーバーヘッドが生じては、パフォーマンスの観点からは台無しです。(全てWebP対応を考えた上での暫定策であれば別ですが)また、圧縮効果が高いかどうか、不可逆でも画質を維持できるかどうかは、全てどういう画像をどういう用途で配布するかにかかります。パフォーマンスの向上も、今回解説したことを踏まえて、「推測するな測定せよ」を忘れずに実施してください。