画像データの構造 |
JPEGフォーマットでは画像をデータにする時に、一辺が8ピクセルの倍数の小さな画像(MCU)に分割し、個々の画像をデータに変換します。
戻す時は、順番に復元してやり、個々の画像をつなげ合わせて1枚の大きな画像に戻してやります。
以下に、JPEG変換に必要な用語などを説明します。
内容的には、解析リストに出てくる情報を理解出来る所までに留めてありますので、詳細に知りたい方は専門書などを見て下さい。
また、説明は後で出てくる JPEGでは一般的な ベースライン方式を前提に説明しています。
プログレッシブ方式は相違点も多く、ここでの説明は割愛しています。
サンプリングファクタ
コンピュータやデジカメ等のメモリー上に有る元の画像はRGB三原色を使ったデータです。
それをJPEGファイルにする時、通常色差や輝度といった画像成分に分解します。
JPEGが対象としている写真等のフルカラー画像は、輝度より色の変化の度合いが少ない特長を持っています。
その特長を活かし、色の成分を輝度と差分化し、ある間隔で色の成分だけ間引きます。
その間引く割合をサンプリングファクタと言うパラメータで指定します。
サンプリングファクタは通常1または2という値で、成分毎に横(H)と縦(V)の値を持っています。
サンプリング
画像データをJPEGファイルにするとき、画像成分の分解と共に、四角い小さな画像データに分割します。
この小さな画像に分割する事をサンプリングと言い、先に説明したサンプリングファクタを使用します。
具体的には画像成分の中で最大のサンプリングファクタを8倍した値が、小さな画像の一辺の長さになります。
例)
輝度成分(Y)のサンプリングファクタ = 横2:縦1
青色色差成分(Cb)のサンプリングファクタ = 横1:縦1
赤色色差成分(Cr)のサンプリングファクタ = 横1:縦1
上記のサンプリングファクタでは画像を横16ドットx縦8ドットのサイズで分割します。
サンプリング比
上記サンプリングの値を判り易く比率で記載したものを、サンプリング比と呼びます。
サンプル比、サブサンプリング比と呼ぶ場合もあります。
3成分の場合3つの値、最初の値は4で始まるのが慣例で、注意しないといけないのが同じ比率が存在するために、
厳密には各成分の比率では無く比率に対する名前と理解して下さい。
一般的なサンプリング比と成分、間引き率 サンプリング比 Y Cb Cr 間引き 4:4:4 1:1 1:1 1:1 間引き無し 4:2:2 2:1 1:1 1:1 2/3 4:2:0 2:2 1:1 1:1 1/2 4:1:1 4:1 1:1 1:1 1/2(余り使用されない)
MCU
サンプリングファクタ指定のサイズで画像を分割し変換された個々のデータをMCU(Minimum Coded Unit)と呼び、JPEGファイルの画像データの処理単位となります。
また、MCUを成分毎に分解し、8x8ピクセル単位の画像データにしたものをブロックと呼びます。
上図4:2:0のサンプル比では、色差成分は輝度成分に対し4分の1に間引かれており、ブロック数は元のデータの半分になります。
4(Y)+4(Cb)+4(Cr)=12ブロック ⇒ 4(Y)+1(Cb)+1(Cr)=6ブロック
※実際のデータは、さらに量子化、ハフマン圧縮という工程を経て圧縮されているので、間引きによるデータ軽減効果は多少変わります。
パディング
画像はMCUという単位で細かく分けられ保存されますが、画像の横または縦サイズがMCUのサイズで割り切れない場合、画像の右端や下端のデータが余ります。
JPEGでは、この余ったデータとダミーのデータと合わせて、MCUとして完成させデータにします。
このダミーのデータをパディングと言います。
画像表示でパディング部分が見えてしまうと困るので、SOFに書かれる画像サイズはパディング部分を差し引いた値を書いてパディング部分を見えなくしています。
量子化
MCUは8x8ピクセルの画像データ数個で構成されています。
今度は、この8x8ピクセルの画像データ(ブロック)についての話です。
ほとんどのJPEG画像は8ビット精度ですので、1ピクセルが1バイト、1ブロックで64バイトのデータです。
このデータをDCT変換で同じく64バイトのデータに変換します。
ここらへんがちょっと難しいので、雰囲気だけ理解して下さい。
DCTはDiscrete Cosine Transferの略で、日本語で離散コサイン変換と言います。
左上のピクセルを基準に、データの変化を周波数として分解、低周波のものから並べて、8x8バイトのデータにします。
DCT変換の詳しい説明は割愛します。興味ある方は専門書をお読み下さい。
この左上の基準データをDC成分と呼び、その他の周波数成分をAC成分と呼びます。
出来たデータは、左上に近い方(低周波)ほど判読し易い大雑把な値、右下に近い方(高周波)ほど判読しにくい微小な差となります。
この値に、Y、Cb、Cr各成分毎に用意されている量子化テーブルの値で割ります。
画像を再生する時は逆に同じ量子化テーブルの値を掛けます。
割った時の余りの値は記録しないので、余りが出た分だけ画像は劣化します。
しかし、量子化テーブルの割る値が大きい程、データは小さな値になり、この後に行うハフマン圧縮で短かなデータにすることが出来ます。
このように、データを段階的な変化データにして数値を制限する事を量子化と呼びます。
また、量子化されたデータを係数と呼びます。
例えば、8ビットの階調だと0から255まで表せますが、元データが129、量子化テーブルが2だと、量子化後の値(係数)は64、復元すれば128になります。
129が128になることで1劣化したことになりますが、この程度の階調差では人の目では判読出来ません。
元データ129をビットに表せば、1000 0001で、8ビットで表現出来ます。
量子化後の64では、100 0000となり7ビットで1ビット削減出来ます。
量子化テーブルが24だとどうでしょうか?
129÷24=5、余り9で9だけ劣化しますが、5をビットに直すと101で表現するビット数が5ビット削減出来た事になります。
実際のハフマン圧縮はもう少し複雑で、的確な例えではないですが、雰囲気は判りますでしょうか?
参考
量子化テーブル例 実際の量子化テーブルの値を表にしたもの
量子化テーブル比較 画質を変えて出力させた量子化テーブルを判り易くグラフにしたもの
ジグザグスキャン
量子化された8x8バイトの平面データを、今度は直線状に並べた64バイトのデータにします。
低周波から高周波になるように、左上から右下にジグザグ状に並べ替えます。
量子化テーブルは一般に左上に近い数値ほど小さく、右下に近い数値ほど値を大きくします。
そうする事によって画像の劣化を抑え、画像データを少なく出来ます。
そういったテーブルで量子化されたデータは右下に近いほど0の出現頻度が高くなります。
ハフマン圧縮では0が連続するほど圧縮効率が高くなる特徴があり、0が並びやすいように並び替えると圧縮効率が高まります。
ハフマン圧縮
今まではバイト単位でデータを加工していましたが、このハフマン圧縮の段階でビットデータに直され、データが圧縮されます。
大雑把に言うと、元のデータはその値によって長さの変わるビットデータ(ハフマン符号と補足データ)に直され、全体から見て少ない容量になります。
この圧縮の仕組みも、複雑ですので用語解説程度で留めています。雰囲気だけ理解して下さい。
ハフマン符号は後に続くデータが何ビットで、どのような値に該当するかを表しています。
また、ハフマン符号はハフマンテーブルで割当てられ、画像データで出現頻度が高い値を短いコードになるように割当れば、その分圧縮効率が上がります。
ハフマン圧縮において、量子化の説明に出てきたDC成分とAC成分では、若干処理が違います。
DC成分
画像の先頭以外は前のDC成分との差を記録します。
係数は1つなので、単純にハフマン符号+データと言う形でビットデータに変換します。
差分にすることでほとんどの場合、値を小さく出来るので圧縮効率は上がります。
逆に画像データの途中でデータ抜けやデータ化けを起こすと、その部分から画像の末端まで影響が出ます。
後で説明するリスタートインタバル処理では、一定間隔でDC成分をそのままの値で記録し、データエラーの影響を最小限にとどめます。
AC成分
DC成分と異なり、量子化後のそのままの値を変換します。(差分ではありません)
係数を63個記録するために、データを短くする工夫がされています。
AC成分のハフマンコードは、ビットデーター長の他にランレングスと言う、0の値の係数がいくつあるかも意味し、そのためDC成分に比べハフマンコードの種類も多くなっています。
DC成分は、係数が一つですから、必ず一つのハフマンコードで表されます。
AC成分は、値が0の係数の連続と0以外の係数をまとめて一つのハフマンコードに出来るので、1ブロックのAC成分、係数1から63までを表すために、実際には63個より少ない数のハフマンコードで表せます。
特定コードの連続をランと呼びます。
ハフマン圧縮では0が何回連続したかをランレングスと言う値で表し、同じコードを繰り返さず、連続回数をデータにすることでデータ長を短くしています。
また、AC成分には以下の2種類の特殊コードが用意されており、0の連続を短いコードで表し圧縮効果を上げています。
※これらのハフマン符号は決まったビットパターンでは無く、ハフマンテーブルにより決められます。
ZRL(Zero Run Length)
値データと併記のランレングスは0から15までしか表せません。
16個以上続いた場合、16個連続分をZRLと言うコードで表し、残りのデータを別で変換します。
EOB(End of Block)
ブロックの最終まで0が連続する場合、EOBと言うコードを記録し、以降のデータを省略します。
参考
DCハフマンテーブル例 実際の輝度DC成分用ハフマンテーブルの値を表にしたもの
ACハフマンテーブル例 実際の輝度AC成分用ハフマンテーブルの値を表にしたもの
スタッフィングビット
JPEGの画像データはビット単位で記録されますが、その後に出現するマーカ(DHT、SOS、RST、DNL、EOI)はバイト単位で記録されます。
画像データがバイト境界で終了しない場合、次のバイト境界まで"1"を詰めて、データ長を揃えます。
このバイト境界に揃えるビットをスタッフィングビットと言って、JPEG規定では"1"を詰めることになっています。
ただし、ここが"0"になっていても、通常画像ビュアーなどはエラーにしません。
以上、だいぶ難しい所もありますが、理解出来なくても修復は出来ますから安心して下さい。
量子化テーブル例 |
実際に記録される量子化テーブルの例
輝度成分量子化テーブル(IJG30%画質)をJpegTableAnalyzerで表示させたもの
ジグザグスキャン通りに再配置している
量子化テーブル比較 |
高画質(左図)に比べ低画質(右図)で保存した画像は高周波成分(図の手前右側)が削られている様子がわかります。
638KB(96%) 289KB(43%) 213KB(32%) 一般の画像ソフト(IJG系)で画質設定を80%、50%、30%で保存した画像をJpegTableAnalyzerでチャート表示させたもの
サイズ表示はJPEGヘッダー等を除いたイメージデータ部分のみの値、元ファイルは668KB
画質・圧縮サイズをイメージしやすいように反転しています(上端=1,下端=255)
左奥がDC成分(青)、その他がAC成分(赤)
DCハフマンテーブル例 |
汎用ハフマンテーブル(輝度DC成分)をJpegTableAnalyzerで解析表示させたもの
ACハフマンテーブル例 |
汎用ハフマンテーブル(輝度AC成分用)をJpegTableAnalyzerで解析表示させたもの(一部抜粋)
DC成分に比べランレングス用ビットがあり、ZRLやEOBと言う特殊なハフマン符号が用意されている