gifがどのように機能するのか疑問に思ったことはありませんか? この記事では、 GIF形式の内部構造とLZW圧縮方式を理解しようとします。
GIF構造
GIFファイルは、ファイルの先頭にある固定領域とそれに続く可変数のブロックで構成され、ファイルは画像ターミネータで終わります。
GIF形式の主な特徴:
- GIFイメージは行ごとに保存され、インデックス付きカラーパレットを使用した形式のみがサポートされます。
- 256色パレットをサポート。
- この形式では、単一のファイルに複数の画像を保存できます。
- GIFはアニメーション画像をサポートしています。
このような画像は、いくつかの静的フレームのシーケンスと、各フレームを画面に表示する時間に関する情報です。 アニメーションを循環的にすることができ、最後のフレームの後、最初のフレームの再生が開始されます。
- 「透明性」をサポート。
パレットの色の1つを「透明」と宣言できます。 この場合、GIF透明度をサポートするプログラム(たとえば、ほとんどの最新のブラウザー)では、「透明な」色でペイントされたピクセルを介して背景が表示されます。 GIFアニメーションは、次のフレーム全体を保存せず、前のフレームとの相対的な変更のみを保存するために透明度を使用できます。
- ユニバーサルロスレス圧縮アルゴリズムLZWが使用されます。
解析の例
2つのフレームで構成される4x4ピクセルのアニメーションGIF画像のダンプ分析を検討してください。 そして、ここにフレーム自体があり、数十倍に拡大されています。
ソース画像
見出し
各GIFファイルの先頭にはヘッダーがあります。 バージョンに応じて、テキスト「GIF87a」または「GIF89a」で構成されます。 GIF87a形式では、変数領域には画像の説明のみが含まれ、GIF89a形式では、拡張ブロックを含めることもできます。
論理画面記述子
[04 00] [04 00]-ピクセル単位の仮想画面の幅と高さ
[A2]-
(1)-フラグMはグローバルカラーテーブルを使用します。 1の場合、ファイルにはグローバルカラーテーブルが含まれます。
(010)= 2-フラグCR。 カラー解像度のビット数= CR + 1。
(0)-フラグS(ソートフラグ)。 1の場合、グローバルカラーマップの色は重要度の高い順に並べられます。
(010)= 2-ピクセルフラグ。 一般的なカラーテーブルのサイズ。 グローバルカラーテーブルのエントリ数:2 ^(N + 1)。
[00]-背景色インデックス。
[00]-アスペクト比。 デフォルトは1です。1。
グローバルカラーチャート
[0A B2 5D]-
[C8 A6 2D]-
[F3 ED 63]-
[BA 60 A5]-
[00 80 C8]-
[F1 60 22]-
[00 00 00]-
[FF FF FF]-
グローバルカラーテーブルがGIFの可変部分になった後。 ファイルには、ブロックの先頭にある1バイトコードで識別される一連のブロックが含まれています。
ブロックコード:
0x21-拡張
0x2C-画像ブロック
0x3B-GIFファイルの完成
拡張ユニット
拡張コード:
0x1-プレーンテキスト拡張子
0xF9-グラフィック管理拡張
0xFE-コメント拡張
0xFF-プログラム拡張
[FF]は拡張コードです。 この場合、プログラムの拡張機能があります。
[0B]-後続のブロックのサイズ(バイト単位)。
[4E 45 54 53 43 41 50 45]-(NETSCAPE)この拡張機能が属するアプリケーションの識別子。
[32 2E 30]-(2.0)アプリケーションコード。 その助けを借りて、アプリケーションはこの拡張機能が本当に彼のものであるかどうかをチェックします。
[03]-次のブロックのサイズ(バイト単位)。
[01]は固定値です。
[00 00]-値は0..65535です。 リトルエンディアン形式の符号なし整数。 ループを繰り返す回数を決定します。
0-無限に。
[00]はブロックの終わりです。
[F9]-拡張コード(グラフィック管理拡張機能)。
[04]-後続のブロックのサイズ(バイト単位)。
[04]-
(000)-予約済み。 ゼロで埋めることをお勧めします。
(001)-処理方法。 表示後の処理を決定します。
0-画像に処理は適用されません
1-画像は変更されません
2-画像は背景によって消去されます
3-画像の下の画像が復元されます
4-7-定義されていません
(0)-ユーザー入力フラグ。 1の場合、画像処理を続行するにはユーザーの応答が必要です。
(0)-透明度の色のフラグ。 任意の色を透明として使用するかどうかを示します。
[32 00]-アニメーションの遅延時間。 = 50/100秒= 0.5秒
[00]-透明色のインデックス。
[00]はブロックの終わりです。
画像ブロック
[00 00] [00 00]は行と列の番号です。 ロジック画面の左上隅の座標を定義します。 (0、0)。
[04 00] [04 00]-画像の幅と高さ(ピクセル単位)。
[00]-
(0)-ローカルカラーテーブルを使用するためのフラグ
(0)-インターレースフラグ。 画像内のピクセルが読み取られる順序を示します。
0-左から右、上から下
1-順序:0番目。 8、16、...、4、12、24 ...
(0)-ローカルカラーテーブルのソートフラグ。 1の場合、ローカルカラーマップの色は重要度の高い順にソートされます。
(00)-予約済み。
(000)-PIXELフラグ。 ローカルカラーテーブルのサイズ(ある場合)。
[03]-LZWの最小コードサイズ。
[08]-後続のブロックのサイズ(バイト単位)。
[08 0A D2 42 90 94 59 12]は、LZWアルゴリズムによって圧縮されたデータのブロックです。 長さ[min。 コードサイズ] + 1
[00]-データストリームの終わり。
LZWアルゴリズムの解析
フレーム1
辞書/コード表
辞書は、色の数とコード{clear}および{end}によって初期化されます。 現在のサイズの長さでコードを取得し、その値を辞書から取得します。 値がディクショナリにある場合、現在のピクセルの完成したカラーインデックスを取得し、次の値をディクショナリに追加します。前の値+現在の最初の値。 辞書にそのような値がまだない場合、このインデックスによって前の+から前の+を追加します。 最初のコードは{clear}、最後の{end}に一致する必要があります。
逆問題を解きます。 元の画像データを取得し、LZWアルゴリズムを使用してエンコードします。 初期データとは、各ピクセルに対応する辞書のカラーインデックスのシーケンスを意味します。 ピクセルを上から下、左から右に見ていきます。
ステップ | アクション | インデックスストリーム | 新しいコード表の行 | コードストリーム |
---|---|---|---|---|
1 | 初期化 | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8 | |
2 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8 | |
3 | 見つかりません | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #10-0 0 | #8#0 |
4 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0 | |
5 | 見つかった | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0 | |
6 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0 | |
7 | 見つかりません | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #11-0 0 0 | #8#0#10 |
8 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10 | |
9 | 見つかりません | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #12-0 2 | #8#0#10#0 |
10 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0 | |
11 | 見つかりません | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #13-2 2 | #8#0#10#0#2 |
12 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2 | |
13 | 見つかった | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2 | |
14 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2 | |
15 | 見つかりません | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #14-2 2 2 | #8#0#10#0#2#13 |
16 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2#13 | |
17 | 見つかりません | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #15-2 4 | #8#0#10#0#2#13#2 |
18 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2#13#2 | |
19 | 見つかりません | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #16-4 4 | #8#0#10#0#2#13#2#4 |
20 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2#13#2#4 | |
21 | 見つかった | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2#13#2#4 | |
22 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2#13#2#4 | |
23 | 見つかりません | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #17-4 4 4 | #8#0#10#0#2#13#2#4#16 |
24 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2#13#2#4#16 | |
25 | 見つかりません | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #18-4 5 | #8#0#10#0#2#13#2#4#16#4 |
26 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2#13#2#4#16#4 | |
27 | 見つかりません | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5
| #19-5 5 | #8#0#10#0#2#13#2#4#16#4#5 |
28 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2#13#2#4#16#4#5 | |
29日 | 見つかった | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2#13#2#4#16#4#5 | |
30 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2#13#2#4#16#4#5 | |
31 | 見つかりません | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #20 –5 5 5 | #8#0#10#0#2#13#2#4#16#4#5#19 |
32 | 読む | 0 0 0 0 2 2 2 2 4 4 4 4 5 5 5 5 | #8#0#10#0#2#13#2#4#16#4#5#19#5#9 |
次に、エンコード結果をダンプに保存されている圧縮データと比較します。 このブロックのGIF形式は、最初に最下位バイトを持つマルチバイト整数を格納します(直接バイト順)。
[08 0A D2 42 90 94 59 12]は、LZWアルゴリズムによって圧縮されたデータのブロックです。
2番目のフレームでも同じことを行います。
フレーム2
辞書/コード表
ステップ | アクション | インデックスストリーム | 新しいコード表の行 | コードストリーム |
---|---|---|---|---|
1 | 初期化 | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8 | |
2 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8 | |
3 | 見つかりません | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #10-3 6 | #8#3 |
4 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3 | |
5 | 見つかりません | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #11-6 1 | #8#3#6 |
6 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6 | |
7 | 見つかりません | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #12-1 7 | #8#3#6#1 |
8 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1 | |
9 | 見つかりません | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #13-7 3 | #8#3#6#1#7 |
10 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7 | |
11 | 見つかった | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7 | |
12 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7 | |
13 | 見つかりません | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #14-3 6 1 | #8#3#6#1#7#10 |
14 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10 | |
15 | 見つかった | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10 | |
16 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10 | |
17 | 見つかりません | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #15-1 7 3 | #8#3#6#1#7#10#12 |
18 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12 | |
19 | 見つかった | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12 | |
20 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12 | |
21 | 見つかった | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12 | |
22 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12 | |
23 | 見つかりません | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #16-3 6 1 7 | #8#3#6#1#7#10#12#14 |
24 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12#14 | |
25 | 見つかった | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12#14 | |
26 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12#14 | |
27 | 見つかりません | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #17-7 3 6 | #8#3#6#1#7#10#12#14#13 |
28 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12#14#13 | |
29日 | 見つかった | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12#14#13 | |
30 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12#14#13 | |
31 | 見つかりません | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #18-6 1 7 | #8#3#6#1#7#10#12#14#13#11 |
32 | 読む | 3 6 1 7 3 6 1 7 3 6 1 7 3 6 1 7 | #8#3#6#1#7#10#12#14#13#11#7#9 |
[38 16 A7 EC 6D 9D 04]-LZWアルゴリズムによって圧縮されたデータのブロック。
GIFファイル完了ブロック
おわりに
それだけです この記事がお役に立てば幸いです(まあ、少なくとも興味深い)。
便利なリンク:
www.w3.org/Graphics/GIF/spec-gif89a.txt
home.onego.ru/~chiezo/gif.htm
著者: kolyadkodarya blueberry24 anna_shunko