Quite OK Image Format ( QOI ) は、Dominic Szablewski によって考案され、2021 年 11 月 24 日に初めて発表された、 24ビット(8ビット/色RGB ) または 32 ビット (8 ビット/色、8 ビットアルファチャネルRGBA ) カラーラスタ(ビットマップ) 画像のロスレス画像圧縮の仕様です。[ 1 ]
これはオープンソースのロスレス圧縮方式で、 PNGよりも高速で実装も容易です。このフォーマットを発表したブログ記事に記載されている数値によると、ファイルサイズが同程度の場合、エンコード速度はPNGと比較して20~50倍、デコード速度は3~4倍高速です。[ 1 ]作者は仕様をパブリックドメイン(CC0)に寄贈しました。[ 2 ] 2022年に、ローザンヌ連邦工科大学の研究者らが、この圧縮方式がロスレスであることを検証しました。[ 3 ]
QOI はFFmpeg (v5.1+) [ 4 ] GIMP (v3.0+) [ 5 ] GraphicConverter (v11.8+) [ 6 ] ImageGlass (v8.5+、読み取り専用) [ 7 ] ImageMagick (v7.1.0-20+) [ 8 ] Imagine (v1.3.9+) [ 9 ]およびIrfanView (v4.60+、プラグイン付き) [ 10 ] でサポートされています。 Windows 10および 11 用のMicrosoft PowerToys (v0.76+)は、ファイル エクスプローラーに QOI 画像のプレビュー機能を追加します。[ 11 ] [ 12 ]コミュニティが作成したプラグインは、 GIMP、Paint.NET、およびXnView MPで利用できます。[ 13 ]
ゲームエンジンGameMakerは、バージョン2022.1.0.609以降、テクスチャグループのデフォルトの保存形式としてbzip2とQOIの組み合わせを使用しています。この形式のファイルはサイズが小さいにもかかわらず、以前のPNG形式のファイルよりも高速に解凍されます。エンジンは、解凍パフォーマンスを向上させるためのプレーンQOIと、ツールやWebプラットフォームとの互換性のためのPNGも提供しています。[ 14 ] [ 15 ]
Rust、Python、Java、C++、C#など、さまざまな言語の実装もあります。[ 16 ]プロジェクトのGit(Hub)リポジトリのREADMEに完全なリストがあります。[ 17 ]
QOIファイルは、14バイトのヘッダー、それに続く任意の数のデータ「チャンク」、そして8バイトの終了マーカーで構成されます。
qoi_header { char magic [ 4 ]; // マジックバイト "qoif" uint32_t width ; // 画像の幅 (ピクセル単位) (BE) uint32_t height ; // 画像の高さ (ピクセル単位) (BE) uint8_t channels ; // 3 = RGB、4 = RGBA uint8_t colorspace ; // 0 = sRGB (線形アルファ付き) // 1 = 全チャンネル線形};色空間とチャンネルのフィールドは、純粋に情報を提供するものであり、データチャンクのエンコード方法を変更するものではありません。
画像は行ごとに、左から右、上から下の順にエンコードされます。デコーダとエンコーダは、前のピクセル値をとして開始します。で指定されたすべてのピクセルがカバーされると、画像は完了します。ピクセルは次のようにエンコードされます。{r:0, g:0, b:0, a:255}width * height
QOI_OP_RUN( )QOI_OP_INDEX)QOI_OP_DIFFまたはQOI_OP_LUMA)QOI_OP_RGBまたはQOI_OP_RGBA)カラーチャンネルはアルファチャンネルと乗算されていない(「非乗算アルファ」)ものと想定されます。エンコーダとデコーダは、以前に検出されたピクセル値の履歴(ゼロ初期化)を保持します。エンコーダとデコーダが検出した各ピクセルは、カラー値のハッシュ関数array[64]によって生成される位置にこの配列に格納されます。
エンコーダでは、インデックスのピクセル値が現在のピクセルと一致する場合、このインデックス位置がとしてストリームに書き込まれますQOI_OP_INDEX。インデックスのハッシュ関数は次のとおりです。
index_position = ( r * 3 + g * 5 + b * 7 + a * 11 ) % 64各チャンクは2ビットまたは8ビットのタグで始まり、その後に複数のデータビットが続きます。チャンクのビット長は8で割り切れます。つまり、すべてのチャンクはバイト境界に揃っています。これらのデータビットにエンコードされたすべての値は、最上位ビットが左端にあります。8ビットタグは2ビットタグよりも優先されます。デコーダはまず8ビットタグの存在を確認する必要があります。バイトストリームの末尾は、70x00バイトとそれに続く10x01バイトで示されます。
考えられるチャンクは次のとおりです。
QOI_OP_RGBb11111110(254)アルファ値は前のピクセルから変化しません。
QOI_OP_RGBAb11111111(255)QOI_OP_INDEXb000..63有効なエンコーダーは、QOI_OP_INDEX 同じインデックスに対して 2 つ以上の連続したチャンクを発行してはなりません。QOI_OP_RUN代わりに を使用する必要があります。
QOI_OP_DIFFb01-2..1-2..1-2..1現在のチャネル値との差はラップアラウンド演算を使用しているため、1 - 2は 255 となり、 は255 + 10 となります。
値はバイアス2の符号なし整数として格納されます。例えば、 -2は0(b00)として格納されます。1は3(b11)として格納されます。アルファ値は前のピクセルから変更されません。
QOI_OP_LUMAb10-32..31-8..7-8..7緑色のチャンネルは変化の一般的な方向を示すために使用され、6ビットでエンコードされます。赤色と青色のチャンネル(drとdb)は、緑色のチャンネルの差分に基づいて差分を計算します。例:
dr_dg = ( cur_px . r - prev_px . r ) - ( cur_px . g - prev_px . g ) db_dg = ( cur_px . b - prev_px . b ) - ( cur_px . g - prev_px . g )現在のチャネル値との差はラップアラウンド演算を使用しているため、10 - 13は 253 となり、 は250 + 71 となります。
値は符号なし整数として格納され、緑色チャンネルにはバイアス32、赤色および青色チャンネルにはバイアス8が付与されます。アルファ値は前のピクセルから変更されません。
QOI_OP_RUNb11ランレングスは−1のバイアスで保存されます。ランレングス 63 と 64 (b111110と) は、とタグb111111によって占有されているため、不正であることに注意してください。[ 18 ]QOI_OP_RGBQOI_OP_RGBA
開発者のDominic Szablewski氏は、従来のファイル形式は複雑で、経済的な動機に基づいており、有料である一方、他のファイル形式は依然として非常に複雑であったり、独自仕様であったりすることを認識していました。彼は、パフォーマンスのために圧縮率を下げる、よりシンプルなファイル形式を作成する必要があると感じ、当初は新しいビデオコーデックの作成を試みましたが、代わりにQOIの初期バージョンを作成しました。[ 1 ]ファイル形式がGitHubユーザーから精査を受けている間、作成者は形式をより複雑にする提案を積極的に拒否しました。[ 20 ]ファイル形式は最終決定されたため、これ以上の改良は行われません。[ 21 ]