QOI

出典: フリー百科事典『ウィキペディア(Wikipedia)』
Quite OK Image
拡張子.qoi
マジック
ナンバー
qoif(4バイト、ASCII)
開発者ドミニク・シャブレフスキ
初版2021年11月24日 (2年前) (2021-11-24)
最新版
1.0
(2022年1月5日 (2年前) (2022-01-05))
種別可逆ビットマップ画像ファイルフォーマット
国際標準仕様
オープン
フォーマット
Yes
ウェブサイトqoiformat.org ウィキデータを編集

QOIQuite OK Image Format)は、ドミニク・シャブレフスキ(ポーランド語: Dominic Szablewski)によって開発され2021年11月24日に初めて発表された24ビット[注釈 1]または32ビット[注釈 2]カラービットマップ(ラスター)画像の可逆画像圧縮の仕様である[1]

概要[編集]

計画された目標は、PNGよりも実装が簡単で高速に処理ができるオープンソース可逆圧縮方式を作成することであった。第三者によるYouTubeの動画では、PNGとQOIの圧縮がどのように行われるかについて説明している[2]。作者による最初の発表とこの動画では、同様のファイルサイズのPNGと比較した場合、エンコードは20倍から50倍速く、デコードは3倍から4倍速いと主張している[1]。作者はQOIの仕様をパブリックドメインCC0)であると宣言した。

ソフトウェアとプログラミング言語の対応[編集]

QOIはImageMagick[3]IrfanView(バージョン4.60以降)[4]FFmpeg(バージョン5.1以降)[5]及びGraphicconverter(バージョン11.8以降)[6]がネイティブに対応している。

コミュニティが作成したプラグインGIMPPaint.NET及びXnViewで利用することができる[7]

RustPythonJavaC++C#などのプログラミング言語向けの実装も存在する[注釈 3][8]

ファイルフォーマット[編集]

ヘッダ[編集]

QOIファイルは14バイトのヘッダと、それに続く任意の数のデータチャンクと8バイトの終端マーカーで構成される。

qoi_header {
    char magic[4]; // マジックナンバー(qoif)
    uint32_t width; // 画像の幅(ビッグエンディアン)
    uint32_t height; // 画像の高さ(ビッグエンディアン)
    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
  • 直前のピクセルのRGB値に基づく差分符号化QOI_OP_DIFFまたはQOI_OP_LUMA
  • 完全なRGB値またはRGBA値(QOI_OP_RGBまたはQOI_OP_RGBA

カラーチャンネルはアルファチャンネルと乗算済みでないと想定される。エンコーダとデコーダは過去に出現したピクセル値をゼロ値で初期化されたarray[64]にバッファとして保持する。このバッファの添え字は、ピクセルのRGBA値にハッシュ関数を適用して得られた値を使用する。

エンコーダでは、インデックスのピクセル値が現在のピクセルと一致する場合、このインデックスの位置はQOI_OP_INDEXとしてストリームに書き込まれる。添え字を計算するハッシュ関数は次の通り:

index_position = (r * 3 + g * 5 + b * 7 + a * 11) % 64

各チャンクは2ビットまたは8ビットのタグで始まり、それにデータビットが続く。全てのチャンクはバイトアライメントされている。これらのデータビットに符号化された全ての値は左端に最上位ビットがある。8ビットのタグは2ビットのタグよりも優先される。デコーダは最初に8ビットのタグの存在を確認する必要がある。バイトストリームの終端は7個の0x00とそれに続く1個の0x01でマークされる。

チャンクの種類は次の通り:

QOI_OP_RGB[編集]

Byte[0] Byte[1] Byte[2] Byte[3]
7 6 5 4 3 2 1 0 7 .. 0 7 .. 0 7 .. 0
1 1 1 1 1 1 1 0
  • 8ビットタグ b11111110(254)
  • 8ビット赤チャンネル値
  • 8ビット緑チャンネル値
  • 8ビット青チャンネル値

アルファ値は前のピクセルから変更されない。

QOI_OP_RGBA[編集]

Byte[0] Byte[1] Byte[2] Byte[3] Byte[4]
7 6 5 4 3 2 1 0 7 .. 0 7 .. 0 7 .. 0 7 .. 0
1 1 1 1 1 1 1 1 アルファ
  • 8ビットタグ(b11111111、255)
  • 8ビット赤チャンネル値
  • 8ビット緑チャンネル値
  • 8ビット青チャンネル値
  • 8ビットアルファチャンネル値

QOI_OP_INDEX[編集]

Byte[0](範囲: 0 .. 63)
7 6 5 4 3 2 1 0
0 0 インデックス
  • 2ビットタグ(b00
  • 6ビット添え字(0..63

有効なエンコーダは同じインデックスに対して2個以上の連続したQOI_OP_INDEXチャンクを出してはならない。代わりにQOI_OP_RUNを使用する必要がある。

QOI_OP_DIFF[編集]

Byte[0](範囲: 64 .. 127)
7 6 5 4 3 2 1 0
0 1 赤チャンネル値の差分 緑チャンネル値の差分 青チャンネル値の差分
  • 2ビットタグ(b01
  • 直前のピクセルの赤チャンネルとの差分値(2ビット、-2..1
  • 直前のピクセルの緑チャンネルとの差分値(2ビット、-2..1
  • 直前のピクセルの青チャンネルとの差分値(2ビット、-2..1

現在のチャンネルとの差分の計算にはラップアラウンド演算英語版が使用されているので、1 - 2の結果は255となり、255 + 1の結果は0となる。

値はエクセス2で表現される符号無し整数として保存される。例えば、−2は0(b00)として保存され、1は3(b11)として保存される。アルファ値は前のピクセルから変更されない。

QOI_OP_LUMA[編集]

Byte[0](範囲: 128 .. 191) Byte[1]
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
1 0 緑チャンネル値の差分 赤チャンネル値 - 緑チャンネル値 青チャンネル値 - 緑チャンネル値
  • 2ビットタグ(b10
  • 直前のピクセルの緑チャンネルとの差分値(6ビット、-32..31
  • 赤チャンネルと緑チャンネルとの差分値(4ビット、-8..7
  • 青チャンネルと緑チャンネルとの差分値(4ビット、-8..7

緑チャンネルは一般的な変化の方向を示すために使用され、6ビットで符号化される。赤チャンネルと青チャンネルはこれらと緑チャンネルとの差分に基づいて符号化される。つまり:

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 + 7の結果は1となる。

値は緑チャンネルはエクセス32、赤チャンネルと青チャンネルがエクセス8で表現される符号無し整数として保存される。アルファ値は前のピクセルから変更されない。

QOI_OP_RUN[編集]

Byte[0](範囲: 192 .. 253)
7 6 5 4 3 2 1 0
1 1 ランレングス
  • 2ビットタグ(b11
  • 直前のピクセルを繰り返すランレングス(6ビット)

ランレングスはエクセス−1で保存される。ランレングス63と64(b111110b111111)はQOI_OP_RGBタグとQOI_OP_RGBAタグによって占有されているので、不正であることに注意[9]

脚注[編集]

注釈[編集]

  1. ^ 各色がそれぞれ8ビットの色深度を持つRGB
  2. ^ 8ビットのアルファチャンネルと各色がそれぞれ8ビットの色深度を持つRGBA。
  3. ^ 完全な一覧はプロジェクトのリポジトリのREADMEを参照。

出典[編集]

  1. ^ a b Lossless Image Compression in O(n) Time”. Phoboslab.org (2021年11月24日). 2022年5月1日閲覧。
  2. ^ Reducible (2022年3月3日). “How PNG Works: Compromising Speed for Quality”. YouTube.com. 2022年5月1日閲覧。
  3. ^ ImageMagick - Image Formats”. 2022年5月4日閲覧。
  4. ^ History of IrfanView Changes/Versions”. www.irfanview.com. 2022年5月10日閲覧。
  5. ^ FFmpeg Changelog - Gitweb”. ffmpeg.org. 2022年7月13日閲覧。
  6. ^ GraphicConverter Release Notes version 11.8 (build 5762)”. Lemke Software. 2023年2月21日閲覧。
  7. ^ James Hein. “Moving images to the next level”. Bangkok Post. https://www.bangkokpost.com/tech/2279999/moving-images-to-the-next-level 2022年4月1日閲覧。 
  8. ^ Simon Sharwood. “Developer creates ‘Quite OK Image Format’ – but it performs better than just OK”. The Register. https://www.theregister.com/2021/12/21/quite_ok_image_format/ 
  9. ^ Szablewski, Dominic (2022年1月5日). “The Quite OK Image Format Specification”. 2022年6月5日閲覧。 この記事には現在パブリックドメインとなった次の出版物からの記述が含まれています。

外部リンク[編集]