HN 日本語サマリー

← 一覧へ戻る
Web開発

Handsum: LQIP画像ファイルフォーマット

Handsum: An LQIP Image File Format (nigeltao.github.io)

38 pointsby dmit5 コメント

要約

Handsumは、低品質画像プレースホルダー(LQIP)のための新しいカスタム画像ファイルフォーマットです。このフォーマットは、48バイトから147バイトという固定サイズで、ディスク容量の節約やデータベースでの扱いやすさを実現します。離散コサイン変換(DCT)を基盤としており、既存のBlurhashやThumbhashといったフォーマットと比較して、同程度のファイルサイズで同等以上の視覚的品質を提供することを目指しています。

全文翻訳

Handsum: LQIP画像ファイルフォーマット 低品質画像プレースホルダー(LQIP)は、非常に小さい(ファイルサイズとピクセル寸法の両方で)画像であり、非常に速くロードされ、高解像度画像がバックグラウンドで遅くロードされる間に即座の視覚的フィードバックを提供します。それらはファイルサイズが十分に小さいため、Webページにbase64エンコードしてインライン化することが可能であり、ネットワークの往復回数を最小限に抑え、ページロード時間を改善します。既存のLQIP技術には、BlurhashとThumbhashのカスタム画像ファイルフォーマット、あるいは単に低品質のJPEGやWebPと非常に小さいピクセル寸法を使用することが含まれます。このブログ記事では、別のLQIPカスタム画像ファイルフォーマットであるHandsumを紹介します。 Handsumファイルも固定バイトサイズです。最低品質設定で48バイト、最高品質設定で147バイトです。デスクトップ、ネイティブ、またはコマンドラインアプリで、サムネイル画像をデータベースに保存している場合、これにより固定サイズの列を使用でき、イテレーションがより高速かつシンプルになります。Handsumは、Blurhashアルゴリズム、Thumbhashアルゴリズム、およびJPEG自体でも使用される離散コサイン変換(DCT)に基づいています。比較的シンプルなHandsumフォーマットがどのように機能するかを理解することは、比較的複雑なJPEGフォーマットがどのように機能するかを理解したい場合に役立つでしょう(JPEG仕様は186ページのPDFファイルです。Handsumはよりシンプルです)。 Webページ例 Handsum Webページデモのアノテーション付きスクリーンショットを以下に示します。これはC言語で書かれ、WasmにコンパイルされたHandsumデコーダーを使用しています。 比較 HandsumとPNG、Thumbhash(Blurhashと非常に似ています)、WebP、ETC2、JPEGとの比較を以下に示します。この画像は独自のタブで開き、ズームインしてパンすることをお勧めします。多くのことが行われています。分解してみましょう。各行は、Wikipediaで見られる有名な画像(earthrise、la-grande-jatte、lincoln、mona-lisa、parliament、pearl-earring、starry-night、tsunami、van-eyck、water-lillies)に関連しています。最初の列「Original」は、アスペクト比を維持しながら32×32ピクセルのバウンディングボックス内に収まるようにスケーリングされた画像自体です。たとえば、500×745ピクセルのモナ・リザ画像は21×32にリサイズされます。それ以外の各列は、ある種の損失のあるエンコード、その後デコードというラウンドトリップ後の元の画像です。各セルの上にある数値(1368や615など)は、エンコードされたバイトサイズです。バイト数が多いほど、品質が高いことは明らかです。問題は、許容できる品質を維持しながら、どの程度小さく(バイトサイズで)できるかということです。 2番目の列「PNG 16」は、単に画像を16×16ピクセルのバウンディングボックスに収まるように縮小し、PNGとしてロスレスでエンコードしたものです。(はい、pngcrushedしたり、WebPロスレスを使用したりすると、わずかに小さいバイトサイズが得られる可能性がありますが、おそらくそれほど大きな違いはありません)。デコードすると16×16以内(例: 11×16のモナ・リザ)の画像が得られ、それを32ピクセル幅または高にアップサンプリングします(バイリニアフィルタを使用)。 3番目の列はThumbhash LQIPコーデックを使用しています。これは、わずか24〜27バイトの非常に小さいエンコーディングを生成します。 次の4つの列は、4つの品質設定のそれぞれでのHandsumを使用しています。「Hsum 16 q=1」の「16」は、「PNG 16」と同様に、コーデック自体が16×16のバウンディングボックス内に収まるものを生成するため、32にアップサンプリングして他のセルと比較してより良い画像を得ることを意味します。 その後の4つの列は、VP8に基づいたWebPロスレスを品質0、25、75で使用しています。「WebP 16」の列は16×16以内をエンコード(したがってデコード)し(ここでもアップサンプリングします)。「WebP 32」の列は32×32以内の画像をエンコードし(デコード時にアップサンプリングは不要です)。 次の2つの列は、ETC2(PKM / PACKMANコンテナにラップ)を使用しています。これはEricsson Texture Compressionフォーマットで、OpenGL ES 3.0で必須(リンクされた仕様の付録C.1)であり、BCn / DXTn / S3TCのような他のテクスチャフォーマットに似ています。ETC2はGPUでのデコード(高い並列化で)向けに設計されていますが、他の画像フォーマットと同様にCPUでもデコードできます。ETC2は興味深く過小評価されている画像フォーマットですが、それについての詳細はこのブログ記事の範囲外です。ここでも、「16」は低解像度のソース画像をエンコードし、デコード後にアップサンプリングすることを意味し、「32」は高解像度のソース画像をエンコードすることを意味します。 最後の2つの列はJPEGで、品質75です(これはWebPの「quality = 75」とおおよそ同等ですが、正確には同じではありません)。ここでも、「16」対「32」は、低解像度+アップサンプリング対高解像度を意味します。 Handsumのq=1(最低品質)では、より大きく(ファイルサイズが大きい)、より良い(視覚的品質が高い)Thumbhashとおおよそ同等です。大きいというのは相対的な意味です。絶対的な差はわずか24バイトです。「より良い視覚的品質」とは、サムネイルに基づいて有名な画像を推測するように言われた場合、モナ・リザや真珠の耳飾りの少女の場合、Handsum(q=1)ではもっともらしいが、Thumbhashではありえない、ということです。それでも、WebP 16 q=0が生成する現代のポテトアートよりは良いですが。 Handsumのq=4(最高品質)では、指定されたバイトサイズ予算に対して、WebPロスレス(VP8)およびETC2とおおよそ同等です。ただし、1つの違いは、指定された品質設定(およびc=3の場合、以下を参照)で、すべてのHandsum画像ファイルが同じバイトサイズであることです。q=1ファイルは常に48バイト、q=2ファイルは75バイト、q=3ファイルは123バイト、q=4ファイルは147バイトです。もし、アートワーク(油絵、オーディオレコードなど)のカタログを表示する組み込みアプリを作成したい場合、たとえば、カタログエントリごとに256バイトを予算計上できます。アーティスト名とアートワーク名にそれぞれ50バイト(必要に応じて省略)、その他のメタデータ(タイムスタンプ、トラック長など)にさらに数バイトを割り当てた後、サムネイルに150バイト残すことができます。16×16のサムネイルをエンコードするためにWebPを使用する場合、q=75はほとんどの場合150バイト以下に収まりますが、常にそうとは限りません。WebPエンコーダーは通常、品質設定はありますが、バイト予算設定はないため、十分に小さい(バイトサイズで)WebPを生成するには少し工夫が必要です。対照的に、Handsum q=4を使用すると、毎回確実に147バイトが得られます。 Handsumの仕組み Handsumには3つの色設定があります(c=1はグレースケール、c=3はRGB、または同等にYCbCr、c=4はアルファチャンネルを追加)。このブログ記事ではc=3のみを扱います。参照実装のコードコメントには、c=1およびc=4の詳細があります。このブログ記事は、最も単純なDCT実装を持つq=4(最高)品質設定にも主に焦点を当てています。 任意のソース画像(たとえば、500×745ピクセルのモナ・リザ)に対して、エンコードアルゴリズムはそれを144バイトのピクセルデータ(q=4の場合)に削減します。これに3バイトのヘッダー(15ビットのマジックシグネチャ、2ビットの色、2ビットの品質、5ビットのアスペクト比)を先頭に追加すると、147バイトになります。 Handsumエンコードは、一連のステージに分解できます。デコードは、ステージを逆の順序で単純に逆にするだけでなく、後処理の「ループフィルタ」ステージ(以下を参照)が追加されます。デコードがステージ0(リサイズ)に達すると、完全な逆転ではありません。デコードされた画像の最も長い次元(幅または高さ)は16ピクセルであり、ヘッダーの5ビットのアスペクト比が短い方の次元を与えます。Handsumは汎用画像フォーマットではなく、サムネイル画像フォーマットにすぎません。 ステージ0: リサイズ 1ピクセルあたり3バイトのRGB(赤、緑、青)で16×16にリサイズすることから始めると、768バイトのデータになります。エンコードの後のステージは、元のソース画像のアスペクト比に関係なく、この16×16のワークスペースで動作します。 ステージ1: YCbCr変換 RGBからYCbCrへの変換は、JPEG / BT.601と同じ公式を使用します。Y = (+0.2990 * R) + (+0.5870 * G) + (+0.1140 * B) Cb = (-0.1687 * R) + (-0.3313 * G) + (+0.5000 * B) Cr = (+0.5000 * R) + (-0.4187 * G) + (-0.0813 * B) ピクセルあたり3バイトのRGBからピクセルあたり3バイトのYCbCrへのこの変換は、無限精度の実数ではロスレス(および完全に可逆)であり、有限精度のコンピュータ数値ではわずかにロスが発生します。理論的にはロスレスな変換は、それ自体ではバイトを節約しません。なぜなら、私たちはまだ3×16×16 = 768バイトだからです。線形代数の愛好家は、これを(ロスレスな)基底変換として認識するでしょう。しかし、これは後のステージがより...