高圧縮画像フォーマット webp と avif の両方に対応する .htaccess


はじめに

でかい画像で入稿されて悲しいの。

webp と avif は?

いずれも後進の高圧縮画像フォーマットです。

webpは瞬間で圧縮できるのが特徴ですが、
avifは圧縮するのに非常に時間がかかります。

webp と avifの対応ブラウザは?

Can I use より
https://caniuse.com/avif
Firefox93以降、Chrome85以降、Opera71以降

https://caniuse.com/webp
Edge18以降、Firefox65以降、Chrome32以降、Opera19以降
Safari(iOS)14以降

webp と avif の圧縮率は?

具体的な圧縮率は申し上げにくいものの、
webpの圧縮率(pngロスレス→webpロス)がおおむね1/10~1/1.2
avifの圧縮率(pngロスレス→avifロス)がおおむね1/10~1/1.5 程度で
平均的にはavifのが圧縮率が高いのですが、
ファイルによってはavifよりwebpのがサイズが小さいことがあります。

avifのがファイルサイズが大きい場合、圧縮した avif ファイルを削除すれば、webpで問題なく配信できます。

更に場合によっては、webpやavifよりもpngのがサイズが小さいことがあります。
SDGSの透過画像がそれにあたることを確認していますが、webpもavifファイルも削除すれば、問題なくpngで配信できます。

ちなみに、データ速報を出してみました。

以下の条件の画像を圧縮した際の平均データとなります。

おおむね4KのJPEG画像(デジカメもしくはスキャナ)からImage::Magickで
・横解像度(normal) 450
・横解像度(normal800) 800
・横解像度(big) 1600
・横×縦(mini)  70

に自動加工・リサイズしたものをソースファイルとする

これをmozjpeg、guetzli、webp、avifで圧縮すると
733ファイルの
オリジナル平均容量:865502byte
mozjpeg平均容量:271144byte (31.32%)
guetzli平均容量(有効ファイルのみ)204075byte (23.57%)
webp平均容量:99257byte (11.46%)
avif平均容量:66925byte (7.73%)

になりました。

コマンドラインで一括圧縮する

avif.sh
for loop in `ls *.png`
do
avifenc -j 16 -s 0 $loop $loop.avif
done

for loop in `ls *.jpg`
do
avifenc -j 16 -s 0 $loop $loop.avif
done

-j 16 の数字は、論理CPUの数に合わせて下さい。
かなり時間がかかりますのでご注意ください。

-s 0 は 最も低速で高圧縮するオプションとお考え下さい。
テスト目的以外で、この数値をあげる理由はまずありません。

webp.sh
for loop in `ls *.png`
do
cwebp -q 80 $loop -o $loop.webp
done

for loop in `ls *.jpg`
do
cwebp -q 80 $loop -o $loop.webp
done

たぶん、ここが一番みんなが知りたい .htaccess の設定

これで http:// 環境のWordpressで動作していますので、提示してみます。

なお、これは、/wp-content/themes/テーマ名/.htaccess に
設置して動作しています。

.htaccess
<IfModule mod_rewrite.c>
	RewriteEngine On

	RewriteCond %{HTTP_ACCEPT} image/avif
	RewriteCond %{REQUEST_URI} (?i)(.*)(\.jpe?g|\.png|\.gif)$
	RewriteCond %{DOCUMENT_ROOT}%1%2.avif -f
	RewriteRule (?i)(.*)(\.jpe?g|\.png|\.gif)$ %1$2\.avif [L,T=image/avif,R]

	RewriteCond %{HTTP_ACCEPT} image/webp
	RewriteCond %{REQUEST_URI} (?i)(.*)(\.jpe?g|\.png|\.gif)$
	RewriteCond %{DOCUMENT_ROOT}%1%2.webp -f
	RewriteRule (?i)(.*)(\.jpe?g|\.png|\.gif)$ %1$2\.webp [L,T=image/webp,R]

</IfModule>

<IfModule mod_mime.c>
	AddType	image/webp	.webp
	AddType	image/avif	.avif
</IfModule>

<IfModule mod_headers.c>
	Header append Vary Accept env=REDIRECT_accept
</IfModule>

先にavifファイルが表示可能であることを処理してから、次にwebpファイルの処理を行います。

もし先にwebpファイルの処理を行うと、webp非対応でavif対応のブラウザはまずないと思いますので、webpだけで配信されてしまいます。

ちなみに、HTMLは旧来の画像のURLを指定します。

test.html
<img src="test.png">
<img src="test.jpg">

Wordpressのプラグインの中に、Webpに自動圧縮するプラグインがありますが、
/wp-content/themes/テーマ名/ 以下に .htaccess を記述するものでなければ、
こちらの .htaccessが優先され、avifも利用可能となります。

きちんと対応しているか確認する

一般的にはデベロッパーコンソールで確認するのですが、

もっとも簡単な方法としては
最新バージョンのブラウザ、(もしくは適度に古いブラウザ)で
画像を右クリックして、ダウンロードしてみてください。

webp もしくは avif 画像のいずれかでダウンロードされようとします。