サンプル値の復元は今回で終わり。
DC成分とAC成分のおさらい
離散コサイン変換で出力された行列の(0,0)成分は周波数が0なのでDC(直流)成分、他は周波数が1以上なのでAC(交流)成分と呼ばれている。
なぜDCとACを分けているのかというと、DC成分は周波数0、つまりユニット(8×8の画像)を一様にベタ塗りした時の値を示していて、全体のサンプル値の傾向を決定していると見ることもできる。8×8の平均値みたいなものだ。そう考えるとDC成分が0になることは少なそうだし、画像は隣合う値がなだらかに変化することが多いので連続するユニットのDC成分の間で差分エンコードするとうまく0付近に偏ったデータを作ることができそう。偏ったデータはハフマン符号の圧縮効果が出やすくなる。
AC成分はほとんどが0なのでランレングス符号で圧縮しやすい。これがDC/AC成分で符号化手順を変えられている理由のようだ。
レベルシフト
A.3.1より、逆DCT変換、逆量子化で復元された値はレベルシフトする必要がある。レベルシフトというのは、サンプル値に 2P-1 を足して 0〜2P-1の値に納めるということらしい。
具体的には、大抵はP=8なので128を足して0〜255の値にするということになる。このとき、0以下の値は0に、255以上の値は255に丸める。この処理で思った以上に丸めなければいけない値がたくさん出てきてちょっと驚いた。
レベルシフトは、エンコードの時に0〜255の値を-128〜127にすることで絶対値を0に近づけてハフマン符号の圧縮率を高める効果があるようだ。EXTEND関数の仕様とも関わってくる。
成分ごとに並べかえる
(7)で書いた通りにユニットが並んでいるので、それぞれY成分、Cb成分、Cr成分ごとに並べなおす。ついでにユニットもバラして左上から右下まで順に並べておくと後の処理が楽になる。
JPEGを読む(7) コンポーネント、サンプリング係数、MCUなど - yunomuのブログ
ここまでで一応全てのサンプル値を復元することはできているんだけど、計算間違いがあってデバッグするのに2ヶ月かかった。余談だけど、原因は変数vとyの書き間違いだった。1文字変数には気をつけよう。