CR2ファイルのRawデータを読み取ってみる その9 Lossless JPEGのデコード3 - 実データのデコード

since:2014-5-18
last update:2014-8-31
前のページへ  







4.5 実データのデコード

やっとデコードの準備が整いました。実データのデコードに入ります。
JPEGでは0xFFはマーカーの意味合いがあるため、実データで0xFFを用いるときは、その後ろに必ず0x00をつけてやる必要があります。
またRSTのようなマーカーが途中にある場合は、その規定に従わなければなりません。ただCR2内のLossless JPEGは、 終端の0xFFD9まで途中にマーカーがあることなくエンコードされている様子ですので、ここでもその前提でデコードします。



それでは実際にデコードしていきます。
前述したとおり、0xFF 0x00 の並びは単なる0xFFを意味するので、実際のデータ列は

0xFF 0x00 0xFF 0xFC 0x00 0xEF 0xF7 0x00 0x3F 0x98 0xC7 ......

となります。
エンコード/デコードのルールの概要は以下の通りです。
初期値は2の(ビット精度-1)乗からスタートします。サンプルでは2の13乗なので、0x2000 (8192)です。
最初の1行目の予測アルゴリズムは必ず1番を使います。すなわち左の値との差分が記録されています。
今回はPredictorは1ですので、すべての行でこのアルゴリズムを使用します。
改行した場合の最初の値のアルゴリズムは必ず2番を使います。つまり上の値との差分が記録されます。

それでは最初の6byteをbit表示してデコードしてみます。

1111 1111  0000 0000  1111 1111  1111 1100  0000 0000  1110 1111

コンポーネント番号1からはじめます。
コンポーネント番号1のDCハフマンテーブルは0ですので、それを参照します。
上位bitから照合していき、葉にたどり着く値を取得します。
この場合は 1111 1111 0 が該当します。

1111 1111  0 000 0000  1111 1111  1111 1100  0000 0000  1110 1111

ハフマンテーブルから、値は0x0Dです。

次に、先ほど取得した0x0D=13bit分の値をデータ列から取得します。

1111 1111  0000 0000  1111 1111  1111 1100  0000 0000  1110 1111

取得した値の最上位ビットが0の場合は、負数を意味しますので、ビット反転させた値を前の値から引き算します。

111 1111 0000 00 =0x1FC0 (8128)なので、8192 - 8128 = 64 (0x0040)になります。
なお最上位ビットが1の場合はその値をそのまま加算すればOKです。

なお、この部分は以下のようにも計算できます。
取得した値の最上位ビットが0の場合は負数と判断し、まず全体に1を加算します。

000 0001 0000 00

値を16bit長とし、不足する上位ビットを1で埋めます。

111 000 0001 0000 00

16bit長の2の補数表現として値を扱います。
値は-8128になりますので、前の値8192に加算して 64 (0x0040)を得ます。

続けてコンポーネント番号2を計算します。
コンポーネント番号2のDCハフマンテーブルは1ですので、それを参照します。
コンポーネント番号1の続きから、上位bitから照合していき、葉にたどり着く値を取得します。
この場合は 1111 1111 0 が該当します。

1111 1111  0000 0000  1111 1111  1111 1100  0000 0000  1110 1111

ハフマンテーブルから、値は0x0Dです。
次にここで取得した0xD=13bit分の値を取得します。

1111 1111  0000 0000  1111 1111  1111 1100  0000 0000  1110 1111

取得した値の最上位ビットが0ですので、上記と同様に値を取得します。
値は-8177になりますので、前の値である初期値8192に足します。
結果値は15 (0x000F) が得られます。

ここでこれらの値の正しさを確認してみます。
以下はこのCR2ファイルを非圧縮でDNGに変換し、RAWデータ部分を切り出したものです。
(IMG_2026_RAW_Data_from_DNG.bin 参照)



確かに最初の2byteが0x0040、次の2byteが0x000Fとなっています。(リトルエンディアンです)

この後コンポーネント番号3番および4番に対応する値をそれぞれ計算します。
それが終われば再びコンポーネント番号1番を計算します。その場合前回算出した値である(0x0040)との差分が記録されていますので 得られた値と0x0040を加算することで、値を求めます。

あとはこれの繰り返しです。
改行した際は前述の通り、上の値との差分が記録されていますので、それに応じて算出します。

なお先ほど照合に使ったDNGから抽出したデータと、LosslessJPEGから抽出した値はあるポイントから後ろは合致しません。
IFD3の項目で記述したcr2_sliceの配置があるためです。
実際の画像センサーの配列と同じようにするためには、このcr2_sliceの並び替えを行なう必要があります。

Lossless JPEGをデコードした直後のデータは以下の図のようになっています。


これを下図のように並べ替えます。


この並び替えで、画像センサーの配列と同じRAWデータが取得できます。

ここから実画像を取得するには、実効画素範囲の情報から、それを抜き出し処理します。

(おわり)



前のページ  [1] [2] [3] [4] [5] [6] [7] [8] [9]