
Chrome 155でJPEG XLを表示する。picture要素のフォールバックとJPEGからの可逆変換を確かめた
どうも!オペ部の西村祐二です!
Chrome 155で、画像形式JPEG XL(.jxl)のデコードに対応しました。フラグを有効にしなくても、<img>で.jxlを指定すれば表示されます。
ただ、すべての閲覧者が新しいChromeを使っているわけではありません。そこで、次の3点を実際に確かめました。
- Chrome 155で
.jxlがそのまま表示されるか - 非対応のブラウザーで
<picture>要素がJPEGへフォールバックするか - 手元の既存JPEGを、画質を変えずにJPEG XLへ変換するとどのくらい小さくなるか
Chrome 155で変わったこと
Chrome for DevelopersのブログとChrome Platform Statusに書かれている要点は次のとおりです。
- Chrome 155から
image/jxlをデコードできるようになりました。Chrome Platform Statusでは、デスクトップ・Android・WebView・iOSのいずれも155から対応と記載されています - デコーダーには、Rustで書かれたjxl-rsが使われています。画像デコーダーは攻撃を受けやすい部分のため、Chromeチームはメモリ安全な実装を選んだと説明しています
- JPEG XLの利点として、JPEGより30〜50%高い圧縮効率、可逆圧縮、HDR対応、JPEGからの可逆トランスコードが挙げられています
- 公式が挙げる向いている用途は、高画質な画像や可逆圧縮、特に写真や細かいプログレッシブデコードを使いたい場面です
今回の対応は、ブラウザーで表示するデコード側の対応です。JPEG XLファイルを作るには、別途エンコーダーが必要です。
picture要素で並べておけば非対応版でも壊れない
試した範囲では、次の書き方でChrome 155以降は.jxl、非対応のブラウザーは.jpgを表示しました。
<picture>
<source type="image/jxl" srcset="photo.jxl">
<img src="photo.jpg" alt="写真" width="768" height="512">
</picture>
また、Chrome 155以降は画像リクエストのAcceptヘッダーにimage/jxlが入りました。サーバーやCDNでこのヘッダーを見れば、同じURLで配信する画像を出し分ける判断材料に使えます。出し分けの設定そのものは、今回は試していません。
試した環境とサンプル画像
- Google Chrome 155.0.8059.79(macOS、headlessモードで使い捨てのプロファイルを使用)
- Chromium 156.0.8078.4(Playwright 1.64.0同梱、Linuxコンテナ)
- 比較用の非対応版: Chromium 153.0.8010.12(Playwright 1.63.0同梱、Linuxコンテナ)
- エンコーダー: libjxl v0.12.0の
cjxl/djxl - 元画像: Wikimedia Commonsの写真「Loquat fruit tree.jpg」(撮影: Sabalo22、CC0 1.0)を768×512に縮小したPNG。libjpeg-turboの
cjpeg -quality 85でJPEGにしたものを「既存のJPEG」として扱いました
確認用のページには、JPEG、JPEG XL、<picture>要素の3つを並べました。各画像についてimg.decode()の成否、naturalWidthとnaturalHeight、実際に読み込まれたファイル(currentSrc)を表示しています。
Chrome 155ではjxlがそのまま表示された
Chrome 155で確認用ページを開いた結果です。

<img src="photo-from-jpeg.jxl">はdecode()が成功し、768×512で表示されました。<picture>要素も.jxl側が選ばれています。headlessモードのため、画面上のUA表記はHeadlessChrome/155.0.0.0と短縮されていますが、実行したバージョンは155.0.8059.79です。
コンテナのChromium 156でも、同じページで同じ結果になりました。
非対応のChromium 153ではpicture要素がJPEGに切り替わった
同じページを、JPEG XLに対応する前のChromium 153で開きました。

.jxlを<img>で直接指定した中央の画像は表示されず、decode()は失敗し、サイズは0×0でした。一方、右側の<picture>要素はcurrentSrcがphoto.jpgになり、JPEGが表示されています。
非対応のブラウザーからの閲覧が残るうちは、.jxlを<img>へ直接書くより、<picture>要素で従来形式と並べるほうが安全そうです。
Acceptヘッダーにimage/jxlが追加された
確認用ページを配信したローカルサーバーで、画像リクエストのAcceptヘッダーを記録しました。
# Chrome 155 / Chromium 156
image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
# Chromium 153
image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Chrome 155とChromium 156では先頭にimage/jxlが入り、Chromium 153には含まれていませんでした。
既存のJPEGを画質を変えずにJPEG XLへ変換する
JPEG XLの特徴の1つが、既存のJPEGを画素を変えずに変換できる可逆トランスコードです。cjxlにJPEGを渡すと、この変換が既定で行われました。
cjxl photo.jpg demo.jxl
djxl demo.jxl back.jpg && cmp photo.jpg back.jpg && echo identical

cjxlはImplicit-default for JPEG is lossless-transcodingと表示し、JPEGを可逆トランスコードしました。djxlで戻したJPEGは元のファイルとバイト単位で一致し、SHA-256も同じでした。
ファイルサイズは次のとおりです。
| ファイル | サイズ |
|---|---|
| 元のJPEG(quality 85) | 96,118 bytes |
| JPEGから可逆変換したJPEG XL | 74,816 bytes(約22%減) |
画像の見た目を変えずに、約22%小さくなりました。必要になれば元のJPEGへ完全に戻せるので、既存の画像資産を置き換えるときも元ファイルを失いません。
公式の「30〜50%高い圧縮効率」とは条件が違う点に注意が必要です。今回の約22%は、すでにJPEGで圧縮された画像を、画素を変えずに詰め直した結果です。画質を指定して新たにエンコードした場合の数値ではありません。結果は元のJPEGの品質や画像の内容によっても変わります。
参考として、可逆圧縮でも比べました。元のPNG(806,139 bytes)をcjxl -d 0で可逆のJPEG XLにすると302,875 bytesになり、約62%小さくなりました。背景のぼけが大きく、なだらかな領域が多い写真なので、可逆圧縮で縮みやすい条件だったと考えられます。
試し始めるならJPEGの可逆変換から
新しく使い始めるなら、既存JPEGの可逆変換から試すのが手軽だと感じました。画質を決め直す必要がなく、元のJPEGにも戻せるためです。
今回確認していないこと
次の点は確認していません。
- Android・WebView・iOS版Chrome、WindowsとLinuxのデスクトップ版Chromeでの表示
- アニメーション、HDR・広色域の表示、プログレッシブデコードの見え方
- CSSの
background-imageやimage-set()でのJPEG XL指定 - FirefoxとSafariでの表示
- CDNでの
Acceptヘッダーによる出し分け - AVIFなど他形式との、画質をそろえた容量比較
まとめ
Chrome 155では、.jxlを<img>や<picture>要素でそのまま表示できました。非対応のChromium 153では.jxlを直接指定した画像は表示されませんでしたが、<picture>要素はJPEGへフォールバックしました。Chrome 155以降はAcceptヘッダーにimage/jxlが入るため、サーバー側での出し分けにも使えます。
既存のJPEGはcjxlで可逆変換でき、今回の写真では元に戻せる状態のまま約22%小さくなりました。導入するなら、既存JPEGを可逆変換し、<picture>要素で元のJPEGと並べて配信する形から試すのが良さそうです。
誰かの参考になれば幸いです。
参考リンク






