そろそろ webp でいいかな
Page No.1
Contents
サイトの表示速度をよくするための画像の最適化というかサイズのダイエットは欠かせないこと。そして、画像を読み込むリクエストをへらすためのデータ化としての BASE64 も、またとても有効な手段。でも、BASE64 化するとそのデータサイズは、もとのサイズの1.3 倍になってしまうので、そういう意味でも元データのサイズを少しでも小さくしておくことは意味のあることだと思う。
そこで思いつくのは、より画像サイズを小さくできるはずの新しい画像フォーマットである webp ってわけだ。でも、せっかく webp でサイズを小さくしたのに、それをまた BASE64 で大きくして、というとなんだかちょっと妙というか疑問という感じもするのではあるのだけれど、それによって元のサイズとほとんど変わらないまま、リクエストは減らせるということになるのだから、これはこれで意味のあることなのではないかと思うわけなのである。
ところで、いざ webp を使うことにしたとして、各ブラウザのサポート状況というのはどうなっているのだろうか、というのが気になるというかとても重要なこと。
この記事を書いているのは、2021年ももうあとわずかという2021年12月のなかば。IE のことを考える必要がほとんどなくなって、主要なブラウザならほぼ大丈夫なのだろうと思いきや、Mac OS はちょっと遅れているよう。その webp が対応となったという Big Sur へのアップデート状況というのが今ひとつよくわからない。 実際に Mac を使用したことがないので状況がよくわからないのだけれど、Big Sur へのアップデートはほとんどのマシンが可能なのだろうか。その前の Catalina というバージョンは 80% ほどということではあるが。
で、じつは webp よりもサイズを小さくできるという規格で AVIF というのがすでに存在するよう。でも、webp においても Mac はやっとという感じなので、もうちょっと時間がかかりそうではある。
まぁ、よくわからないので、とりあえずブラウザで判断することにして、Firefox と Chrome 系において webp を表示させることにした。
と、いうことでそれでは本題へと入ることにしませう。
php で jpg or png を webp or AVIF へ変換
webp を使うにはなにはともあれ、持っている画像を webp へとコンバートしないとはじまらない。
コンバートするには、Googleが開発した Squoosh というサイトを使うとか、Google Developers からダウンロードできる cwebp というコマンドツールを使うとかがあるけれど、php にもちゃんとそれ用の imagewebp という関数が備わっている。慣れ親しんでいる php にあるなら、それのほうが色々と応用がきくということで自ずとそれを使うことになる。ちなみに php においては、AVIF においても 8.1 から imageavif という関数を備えている。
php の imagewebp という関数は、引数に画像のファイル名を渡せばいいというわけではなく、GdImage オブジェクトを渡せとのことで、めんどうってほどでもないけれどちょっとひとてまが必要。
ネットを調べ回ってみてためしたところ、jpg は以下のような感じのものでうまくいった。
imagewebp の返り値として得られる $result の値は、成功した場合に true、失敗すると false であり、第二引数にファイル名を渡している下のような場合は、コンバートされた webp 画像ファイルが作成されていて、その引数を省略したり null にした場合は、画像ストリームを直接出力されるとある。そこで直に表示されるということである。
ちなみに逆 ( webp -> jpg )も同じようなもので、それは page2 にて。
png の方も同じようにできるかとおもいきや、そうは簡単にはいかなかった。png の場合はもうひとてま必要なようで、php: imagewebp – Manual を参考にしてやってみたところ、imagecreatefrompng に以下のように追加することでうまくいった。
jpg or png -> webp or AVIf and BASE64 converter page application
と、いうことで作ったものが下。
このファイルがあるディレクトリ直下の targets フォルダ内、全ての jpg、png を webp もしくは AVIF に変換する php によるブラウザにて動作するページ。
文字列を指定することで、その文字列をファイル名に含むファイルだけに限定できるし、webp or AVIFのクォリティー指定が可能。あと、webp or AVIF にコンバートした後、それを BASE64 化することも可能。
仮にこのコードを使用する場合、このコードを使用しての一切の責任は負いませんから完全自己責任にて使用して下さい。
後日追記:実はこの下のコード、簡単なケアレスミスがあって、2023年3月24日に訂正しています。
と、いうのは 66 – 70 行目と 88 – 92 行目の条件式のところで、生成するファイルを webp か avif かで判別させてるわけですが、これ、生成するものが逆でした。
$ope に 1 をビットアンドさせてるので、奇数の場合に true になるわけで、そのときは webp を生成しなくてはいけない。それが逆になっていたので、拡張子は .webp なのにファイルの実態は avif という、へんてこりんなことになっていたわけです。しかし、ブラウザでも windows10 のエクスプローラーでも普通に表示されていたから気が付かなかったと。ちなみにファイル名の拡張子を正式な .avif に変更してやっても、もちろん普通に表示されることになる。
で、これ、なにゆえに気がついたのかというと、その拡張子が .webp の avif ファイルを、いざ WordPress にアップロードしようとしたら「権限がない」と拒否されてしまったから。下のプログラムでクオリティを変えたりしていろいろと試してみたけれど、全くだめ。疑問に思いつつ、WordPess のアップロードの工程における関数をじっくり見ていくと、アップロードファイルのチェックにおいて、wp-includes/functions.php の wp_get_image_mime() で、 php の exif_imagetype() 関数を使っている。試しに、その関数を使って例のファイルをチェックしてみたところ、19 を返してきた。webp ならば 18 じゃないとおかしい。この 19 という数字は php.net/exif_imagetype のページを見ても、2023年3月24日時点では記載されていないけれど、php 8.2.4 において image_type_to_mime_type() 関数の戻り地で試してみると image/avif である。と、いうことで、これはっ!と思い、プログラムを見直してみて気がついたというわけです。
しかし、画像ファイルの拡張子なんて、ただ人間が判別できるようになっているだけのもので、たいして重要ではないってことがわかった。
なお、BASE64 化した場合の webp or AVIFを表示させる場合も、jpg、png と同様。jpg の部分を webp or AVIF に変えるだけのこと。たとえば css なら。
php の imagewebp でやってみたり、cwebp でやってみたり、あるいは Squoosh でと、色々な画像であれこれ試してみたが、クォリティーが同じでも全く同じデータサイズになることはなかったがそんなに違いもなかった。全く同じにならないのは、細かいところのオプションのデフォルトの違いによるものだろうか。
あと、png においては、元画像よりもサイズが大きくなってしまうものもあった。これはすでにサイズが圧縮されていて小さくなっているもので、透明部分が多いものの傾向に思えた。これは逆にいえば、png において、透明部分が多い画像によっては、TinyPNG などのサイトによってダイエットしたもののほうが、webp にするよりもサイズは小さくできるということなのかもしれない。というか、それほど TinyPNG での圧縮はクォリティーが下がるということなのだろうか。
png においては、そのあたりの事を確認しつつ、どちらを使用するかを決めていく必要があるようだ。
そして次ページでは、逆のコンバート。webp or AVIF を jpg へと戻す方の変換を。
Post : 2021/12/18 16:15
Comments feed
Trackback URL : https://strix.main.jp/wp-trackback.php?p=169324