0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JPEG画像のリスタートマーカー

Posted at

これまでのJPEGシリーズ

今回やること

JPEG画像におけるリスタートマーカーの使われ方を観察し、処理方法を確認する。

リスタートマーカーに関する情報

file - Jpeg restart markers - Stack Overflow
より、リスタートマーカーについて以下のことがわかる。

  • エラーからの復帰を目的に設計された
  • マーカー FFDD でリスタートの間隔 (MCU何個ごとにリスタートマーカーを入れるか) を定義する
  • 圧縮データ中にリスタートマーカー (FFD0FFD7) があったら、以下を行う
    • 各チャンネルの「前のブロックの DC 成分」を 0 にリセットする
    • 圧縮データの読み取りをマーカーの次のデータ境界から始める
  • FFD0 から FFD7 を順に使っていき、FFD7 の次は FFD0 に戻る
    • これにより、リスタートマーカー自体の欠落の検出を狙う
  • マルチスレッドでデコードを行う際、スレッドへのデコードする範囲の割り当てにも活用できる

リスタートマーカーの観察

GIMP 2.10.38 で真っ白な画像を作り、JPEGにエクスポートを行った。

シンプルな画像 (グレースケール)

32×32 のグレースケールで、リスタートマーカーをオン、「間隔 (MCU 数)」を 1 に設定してエクスポートを行うと、以下の DRI (リスタートマーカーの間隔の定義) が出力された。(TSXBIN で観察を行った)

93  ★DRI[0]            FF DD
95  SizeOfThis[0]       00 04
97  RestartInterval[0]  00 04

ここから、リスタート間隔は 4 となったことが読み取れる。

なぜか、設定した間隔に1行あたりの「まとまり」の数を掛けた値が、実際のリスタート間隔になるようである。

また、圧縮データは以下のようになった。

A3  圧縮データ(18B)[0]  AA 60 3F FF D0 AA 60 3F FF D1 AA 60 3F FF D2 AA
B3  圧縮データ(18B)[16] 60 3F

AA 60 3F が4回現れ、その間にリスタートマーカー (FF Dx) が挟まっている。

これを JPEGsnoop で見ると、圧縮データの冒頭は以下のようになった。

    Lum (Tbl #0), MCU=[0,0]
      [0x000000A3.0]: ZRL=[ 0] Val=[  339] Coef=[00= DC] Data=[0x AA 60 3F FF = 0b (10101010 011----- -------- --------)] 
      [0x000000A4.3]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 3F FF D0 = 0b (---0---- -------- -------- --------)] EOB
                      DCT Matrix=[ 1017     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]


    Lum (Tbl #0), MCU=[1,0]
      [0x000000A4.4]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 60 3F FF D0 = 0b (----0--- -------- -------- --------)] EOB
      [0x000000A4.5]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 3F FF D0 = 0b (-----0-- -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]


    Lum (Tbl #0), MCU=[2,0]
      [0x000000A4.6]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 60 3F FF D0 = 0b (------0- -------- -------- --------)] EOB
      [0x000000A4.7]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 3F FF D0 = 0b (-------0 -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]


    Lum (Tbl #0), MCU=[3,0]
      [0x000000A5.0]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 3F FF D0 AA = 0b (0------- -------- -------- --------)] EOB
      [0x000000A5.1]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 3F FF D0 AA = 0b (-0------ -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]


    Lum (Tbl #0), MCU=[0,1]
      [0x000000A5.2]: ZRL=[ 0] Val=[  339] Coef=[00= DC] Data=[0x 3F FF D0 AA = 0b (--111111 11111--- -------- --------)] 
      [0x000000A9.3]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 3F FF D1 = 0b (---0---- -------- -------- --------)] EOB
                      DCT Matrix=[ 1017     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

最初のブロックで大きい値 1017 が現れたあと、続く3ブロックでは 0 ばかりが現れ、その次のブロックでまた 1017 が現れている。
これは、リスタート間隔が 4 であるため、4 ブロックごとに「前回の値」のリセットが行われることに対応する。

リスタートマーカーの後では、なぜかデータの表示がおかしくなっている。

縦長画像 (グレースケール)

なぜか画像の横幅に応じて設定した値より大きいリスタート間隔が用いられてしまうことがわかったので、今度は 8×1024 の画像を作成した。

DRI は以下のようになり、リスタート間隔は 3 であることがわかる。

093  ★DRI[0]              FF DD
095  SizeOfThis[0]         00 04
097  RestartInterval[0]    00 03

圧縮データは、以下のようになった。

0A3  圧縮データ(170B)[0]   AA 60 FF D0 AA 60 FF D1 AA 60 FF D2 AA 60 FF D3
0B3  圧縮データ(170B)[16]  AA 60 FF D4 AA 60 FF D5 AA 60 FF D6 AA 60 FF D7
0C3  圧縮データ(170B)[32]  AA 60 FF D0 AA 60 FF D1 AA 60 FF D2 AA 60 FF D3
0D3  圧縮データ(170B)[48]  AA 60 FF D4 AA 60 FF D5 AA 60 FF D6 AA 60 FF D7
0E3  圧縮データ(170B)[64]  AA 60 FF D0 AA 60 FF D1 AA 60 FF D2 AA 60 FF D3
0F3  圧縮データ(170B)[80]  AA 60 FF D4 AA 60 FF D5 AA 60 FF D6 AA 60 FF D7
103  圧縮データ(170B)[96]  AA 60 FF D0 AA 60 FF D1 AA 60 FF D2 AA 60 FF D3
113  圧縮データ(170B)[112] AA 60 FF D4 AA 60 FF D5 AA 60 FF D6 AA 60 FF D7
123  圧縮データ(170B)[128] AA 60 FF D0 AA 60 FF D1 AA 60 FF D2 AA 60 FF D3
133  圧縮データ(170B)[144] AA 60 FF D4 AA 60 FF D5 AA 60 FF D6 AA 60 FF D7
143  圧縮データ(170B)[160] AA 60 FF D0 AA 60 FF D1 AA 63

FF D0FF D7 が順番に繰り返し使われていることがわかる。
また、リスタートマーカーの間のデータは、最後以外は AA 60 であるが、最後は AA 63 となっている。
今回のブロック数は 128 なので、3 ブロックずつ格納していくと最後に 2 ブロック余ることになる。
最後のデータでは、この 2 ブロックが格納され、余計なブロックは格納されていないことがわかる。
[Python] JPEG Encoderを実装しながら追うJPEGのファイル仕様 | henatips
より、最後のバイトの余ったビットは 1 で埋めることがわかり、それが反映されている。

この「枠が余っても余計なブロックは格納されない」というのは、画像から完全にはみ出す部分があったとしてもはみ出さない場合と同様に全部のブロックを格納する「まとまり」とは異なる動作である。

縦長カラー画像

画像のサイズは同じく 8×1024 とし、今度はカラー画像にしてみた。

DRI は以下のようになり、リスタート間隔は 3 である。

10A  ★DRI[0]              FF DD
10C  SizeOfThis[0]         00 04
10E  RestartInterval[0]    00 03

圧縮データは、以下のようになった。

11E  圧縮データ(255B)[0]   AA 60 00 0F FF D0 AA 60 00 0F FF D1 AA 60 00 0F
12E  圧縮データ(255B)[16]  FF D2 AA 60 00 0F FF D3 AA 60 00 0F FF D4 AA 60
13E  圧縮データ(255B)[32]  00 0F FF D5 AA 60 00 0F FF D6 AA 60 00 0F FF D7
14E  圧縮データ(255B)[48]  AA 60 00 0F FF D0 AA 60 00 0F FF D1 AA 60 00 0F
15E  圧縮データ(255B)[64]  FF D2 AA 60 00 0F FF D3 AA 60 00 0F FF D4 AA 60
16E  圧縮データ(255B)[80]  00 0F FF D5 AA 60 00 0F FF D6 AA 60 00 0F FF D7
17E  圧縮データ(255B)[96]  AA 60 00 0F FF D0 AA 60 00 0F FF D1 AA 60 00 0F
18E  圧縮データ(255B)[112] FF D2 AA 60 00 0F FF D3 AA 60 00 0F FF D4 AA 60
19E  圧縮データ(255B)[128] 00 0F FF D5 AA 60 00 0F FF D6 AA 60 00 0F FF D7
1AE  圧縮データ(255B)[144] AA 60 00 0F FF D0 AA 60 00 0F FF D1 AA 60 00 0F
1BE  圧縮データ(255B)[160] FF D2 AA 60 00 0F FF D3 AA 60 00 0F FF D4 AA 60
1CE  圧縮データ(255B)[176] 00 0F FF D5 AA 60 00 0F FF D6 AA 60 00 0F FF D7
1DE  圧縮データ(255B)[192] AA 60 00 0F FF D0 AA 60 00 0F FF D1 AA 60 00 0F
1EE  圧縮データ(255B)[208] FF D2 AA 60 00 0F FF D3 AA 60 00 0F FF D4 AA 60
1FE  圧縮データ(255B)[224] 00 0F FF D5 AA 60 00 0F FF D6 AA 60 00 0F FF D7
20E  圧縮データ(255B)[240] AA 60 00 0F FF D0 AA 60 00 0F FF D1 AA 60 03

JPEGsnoop で見ると、圧縮データの冒頭は以下のようになっていた。

    Lum (Tbl #0), MCU=[0,0]
      [0x0000011E.0]: ZRL=[ 0] Val=[  339] Coef=[00= DC] Data=[0x AA 60 00 0F = 0b (10101010 011----- -------- --------)] 
      [0x0000011F.3]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 00 0F FF = 0b (---0---- -------- -------- --------)] EOB
                      DCT Matrix=[ 1017     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Chr(0) (Tbl #1), MCU=[0,0]
      [0x0000011F.4]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 60 00 0F FF = 0b (----0--- -------- -------- --------)] EOB
      [0x0000011F.5]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 00 0F FF = 0b (-----0-- -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Chr(0) (Tbl #1), MCU=[0,0]
      [0x0000011F.6]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 60 00 0F FF = 0b (------0- -------- -------- --------)] EOB
      [0x0000011F.7]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 00 0F FF = 0b (-------0 -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]


    Lum (Tbl #0), MCU=[0,1]
      [0x00000120.0]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 00 0F FF D0 = 0b (0------- -------- -------- --------)] EOB
      [0x00000120.1]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 00 0F FF D0 = 0b (-0------ -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Chr(0) (Tbl #1), MCU=[0,1]
      [0x00000120.2]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 00 0F FF D0 = 0b (--0----- -------- -------- --------)] EOB
      [0x00000120.3]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 00 0F FF D0 = 0b (---0---- -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Chr(0) (Tbl #1), MCU=[0,1]
      [0x00000120.4]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 00 0F FF D0 = 0b (----0--- -------- -------- --------)] EOB
      [0x00000120.5]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 00 0F FF D0 = 0b (-----0-- -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]


    Lum (Tbl #0), MCU=[0,2]
      [0x00000120.6]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 00 0F FF D0 = 0b (------0- -------- -------- --------)] EOB
      [0x00000120.7]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 00 0F FF D0 = 0b (-------0 -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Chr(0) (Tbl #1), MCU=[0,2]
      [0x00000121.0]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 0F FF D0 AA = 0b (0------- -------- -------- --------)] EOB
      [0x00000121.1]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 0F FF D0 AA = 0b (-0------ -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Chr(0) (Tbl #1), MCU=[0,2]
      [0x00000121.2]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 0F FF D0 AA = 0b (--0----- -------- -------- --------)] EOB
      [0x00000121.3]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 0F FF D0 AA = 0b (---0---- -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]


    Lum (Tbl #0), MCU=[0,3]
      [0x00000121.4]: ZRL=[ 0] Val=[  339] Coef=[00= DC] Data=[0x 0F FF D0 AA = 0b (----1111 1111111- -------- --------)] 
      [0x00000125.3]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 00 0F FF = 0b (---0---- -------- -------- --------)] EOB
                      DCT Matrix=[ 1017     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

「Lum 1個とChr 2個のセット」3個ごとにリスタートマーカーが入り、「前のブロックの値」がリセットされていることがわかる。

サブサンプリングを行う画像

画像のサイズを再び 32×32 とし、「間隔 (MCU 数)」は 1、サブサンプリングを「4:2:2 水平 (1/2 クロマ)」にして画像を出力した。

DRI は以下のようになり、リスタート間隔は 2 である。

10A  ★DRI[0]            FF DD
10C  SizeOfThis[0]       00 04
10E  RestartInterval[0]  00 02

圧縮データは以下のようになった。

11E  圧縮データ(22B)[0]  AA 60 00 3F FF D0 AA 60 00 3F FF D1 AA 60 00 3F
12E  圧縮データ(22B)[16] FF D2 AA 60 00 3F

JPEGsnoop で圧縮データを見ると、冒頭は以下のようになった。

    Lum (Tbl #0), MCU=[0,0]
      [0x0000011E.0]: ZRL=[ 0] Val=[  339] Coef=[00= DC] Data=[0x AA 60 00 3F = 0b (10101010 011----- -------- --------)] 
      [0x0000011F.3]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 00 3F FF = 0b (---0---- -------- -------- --------)] EOB
                      DCT Matrix=[ 1017     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Lum (Tbl #0), MCU=[0,0]
      [0x0000011F.4]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 60 00 3F FF = 0b (----0--- -------- -------- --------)] EOB
      [0x0000011F.5]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 00 3F FF = 0b (-----0-- -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Chr(0) (Tbl #1), MCU=[0,0]
      [0x0000011F.6]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 60 00 3F FF = 0b (------0- -------- -------- --------)] EOB
      [0x0000011F.7]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 00 3F FF = 0b (-------0 -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Chr(0) (Tbl #1), MCU=[0,0]
      [0x00000120.0]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 00 3F FF D0 = 0b (0------- -------- -------- --------)] EOB
      [0x00000120.1]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 00 3F FF D0 = 0b (-0------ -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]


    Lum (Tbl #0), MCU=[1,0]
      [0x00000120.2]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 00 3F FF D0 = 0b (--0----- -------- -------- --------)] EOB
      [0x00000120.3]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 00 3F FF D0 = 0b (---0---- -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Lum (Tbl #0), MCU=[1,0]
      [0x00000120.4]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 00 3F FF D0 = 0b (----0--- -------- -------- --------)] EOB
      [0x00000120.5]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 00 3F FF D0 = 0b (-----0-- -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Chr(0) (Tbl #1), MCU=[1,0]
      [0x00000120.6]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 00 3F FF D0 = 0b (------0- -------- -------- --------)] EOB
      [0x00000120.7]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 00 3F FF D0 = 0b (-------0 -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

    Chr(0) (Tbl #1), MCU=[1,0]
      [0x00000121.0]: ZRL=[ 0] Val=[    0] Coef=[00= DC] Data=[0x 3F FF D0 AA = 0b (0------- -------- -------- --------)] EOB
      [0x00000121.1]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 3F FF D0 AA = 0b (-0------ -------- -------- --------)] EOB
                      DCT Matrix=[    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]


    Lum (Tbl #0), MCU=[0,1]
      [0x00000121.2]: ZRL=[ 0] Val=[  339] Coef=[00= DC] Data=[0x 3F FF D0 AA = 0b (--111111 11111--- -------- --------)] 
      [0x00000125.3]: ZRL=[ 0] Val=[    0] Coef=[01..01] Data=[0x 60 00 3F FF = 0b (---0---- -------- -------- --------)] EOB
                      DCT Matrix=[ 1017     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]
                                 [    0     0     0     0     0     0     0     0]

今回は、Lum 2個と、Chr 1個×2要素=2個で1個の「まとまり」となる。
リスタート間隔が、リスタートマーカー間のこの「まとまり」の数に反映されることがわかる。

細かい検証

「間隔 (MCU 数)」を 4 にして 32×32 のJPEG画像を出力すると、リスタート間隔は 16 となり、圧縮データ中にリスタートマーカーはみられなかった。
これにより、リスタート間隔が「まとまり」の数の約数のときも、最後の「まとまり」の後にリスタートマーカーは入れないことがわかる。

4096×4096 のJPEG画像を (リスタートマーカーなしで) 出力し、リスタート間隔 0 を表す DRI を手動で挿入しても、加工後の画像ファイルは ImageMagick で正常に読み込めた。
このような画像ファイルのブロック数は 65,536 を超えているため、リスタート間隔 0 は「リスタートマーカーなし」を表すらしいことがわかる。

まとめ

  • リスタートマーカーを用いる場合、圧縮データ (SOS) より前に、DRI (FF DD) により何個の「まとまり」に対応するデータを記録するごとにリスタートマーカーを挟むか (リスタート間隔) を定義する
    • この数が 0 の場合、「リスタートマーカーを用いない」ことを表す
  • リスタートマーカーは、FF D0FF D7 を順に繰り返し用いる
  • リスタートマーカーを挟んだ時、「前のブロックの DC 成分」は全チャンネルで 0 にリセットする
  • 「まとまり」の数がリスタート間隔の整数倍のときでも、最後の「まとまり」のデータの後にリスタートマーカーは挟まない
  • 「まとまり」の数がリスタート間隔の整数倍でないときでも、パディングはしない
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?