JPEGについて

JPEGファイルの概要

  JPEGは、Joint Photographic Experts Group のことで、この規格を討議したISO/IECの合同会合の名称であるが、一般にはその規格で記録された画像ファイルのことを指しており、具体的にはISO/EC10918−1(JIS X4301)によるものを指している。ファイル拡張子は通常jpgやjpegである。なお、以下の説明はJFIF(Jpeg File Interchange Format)によるものについてのものである。

JPEG(JFIF)では、画像はYCbCr形式(色を輝度、青差分、赤差分で表す方式。RGBとは計算式により相互に変換できる)で処理、記録される。通常、画像を8×8画素ずつに区画し、前記の各成分値について8×8の区画ごとに(データを間引く場合は複数の区画を纏めて64個のデータとして)離散フーリエ変換の一種である2次元離散余弦変換(DCT)を行い、得られた数値を簡略化処理(量子化)したものを、ハフマン符号(モールス信号のようなものと考えてよいが、0が続く場合の符号もある)によるビット列として画像データとする。

JPEGファイルには、データの始まりや終わり、アプリケーションで使用する情報、量子化テーブル、ハフマンテーブル、圧縮データのヘッダー等も、それらを示すマーカとともに記録されている。EXIF情報もこれらのアプリケーション情報として記録されているものである。

JPEGは、その処理の過程で画像情報の一部が永久に失われることとなる。このため、ファイルから画像を再生し、それをまたJPEGファイルとして保存すると、そのたびに画像の劣化が生じるが、画像に標題ではロスレス回転も可能で、この場合は記録されているデータを並び替えるだけなので画像の劣化が生じない。

JPEGファイルの記録フォーマット
1.マーカ
 ファイルは2バイトのマーカにより区切られた構成単位からなっている。一部を除きマーカの後には、当該マーカで示される一連のデータが続いており(マーカとそれに続くデータからなる構成単位をマーカ部分列[マーカセグメント]という)、マーカの直後に当該マーカ部分列のサイズ(マーカ自身を除いたバイト数)が2バイトの数値で記録(数値は常にビッグ・エンディアンである)される。マーカには次のようなものがある。

意味 マーカ(HEX) 説明
画像開始(SOI) FFD8 ファイルは必ずSOIから始まらなければならない。
アプリケーション用(APPn) FFEn アプリケーションで使用するデータである。nの例として、n=0:JFIF、n=1:Exif、n=2:MPF、n=13:Adobe等が一般的である。
MPFは、同一ファイルに記録された複数の画像の付属情報を格納したもの。
量子化テーブル(DQT) FFDB 量子化テーブルは輝度成分用と色差成分用の2種類とすることが多い。
ハフマンテーブル(DHT) FFC4 ハフマンテーブルは暗号解読表のようなもので、AC用とDC用各2種類、計4種類使用することが多い。
フレームヘッダ(SOF) FFCx 画像形式、大きさ等の基本データが記録されるもので、xが0〜3は一般方式で0:ベースライン、2:プログレッシブである。xが5〜7は差分方式、9〜11は算術方式など。
リスタート間隔定義(DRI) FFDD スキャンデータにおいて、前データとの差分値を0にリセットする間隔(MCU数)が2バイトで記録される。
コメント(COM) FFFE 任意のコメントを記述することが出来る。
スキャンヘッダ(SOS) FFDA 画像のスキャンデータについて、スキャンの範囲等が記録され、この直後に実際のスキャンデータが続く。
リスタートマーカ(RST) FFDn スキャンデータ中に、DRIで記された数のMCUデータごとに置かれる。nは0から順に7迄増えるのを繰り返す。
画像終了(EOI) FFD9 一連の画像データの終了を示す。

(注)SOI、RST、EOIはマーカ単独で使用され、マーカ部分列のサイズなどはない。

2.MCUについて
 データの間引きがなければ、画像の8×8画素ごとにY、Cb、Crそれぞれに8×8=64個のデータが出来ることになるが、データが間引かれる場合は間引かれた成分のデータが8×8の1ブロックに対して間引かれない成分のデータは複数ブロックになる。このような1かたまりのデータ(横m個×縦n個に1個取るように間引いた場合は8m×8n画素の画像に対応するデータになるわけである。この場合間引かれない成分のデータはm×nブロックとなる。)をMCU(最小符号化単位)という。
 画像データはMCUごとにY、Cb、Crの順に記録される。例えば色差成分が1/2に間引かれている場合では、YYCbCrYYCbCrY・・・のように成分が交互に(インターリーブして)ブロックが記録されるわけである。なお、グレースケールの場合ではY成分のみであるから、Y成分のみが連続して(非インターリーブで)記録されることとなる。

3.DCTについて
 1ブロックの成分値はDCT変換して係数値を求めるが、ここで係数値も8×8の2次元配置にして考えることとする。元ブロックのデータと変換後の数値はどちらも64個のデータからなっているがいわばこれは似て非なるものであり、成分値ブロックの例えば(5,2)の値(これは画像の左から6番目、上から3番目のピクセルの輝度又は色差の値である)とDCT変換後係数値(5,2)の値との間には直接的な対応関係はないことになる。元のブロックの大まかな傾向が変換後係数(0,0)に示され、(7,7)の方向に行くに従って元ブロックの詳細な様子が記述されることになる。前記の「直接的な対応関係がない」というのは、行列式による計算となるので直感的な意味での対応がないということであるが、行列の性質から係数値の配置や符号を換えることで元の数値(成分値、つまり画像のこと)を左右反転させたり90度傾けたりすることが可能である。
 前記のように変換後係数(0,0)は元ブロックにとって重要な値でこれを「直流係数(DC)」といい、その他の係数を「交流係数(AC)」といっている。

4.量子化テーブル
 DCT変換された係数値は量子化(特定の定数の整数倍に数値を簡略化すること。元の数値を定数で割ればよい。)により圧縮される。この際に64個の係数値はそれぞれ違う定数で割った商を記録し、画像に戻すときにはその値に量子化に使用したのと同じ定数をかけて元の係数値(もちろん完全な元数値にはならずにその定数の倍数にしかならないわけである)に戻される。JPEGでは量子化に使用した8×8の64個の定数を量子化テーブルとして画像ファイル中に記録し、画像に戻すときにはその表の数値を使用して係数値を復元する。なお、この数値を大きくしたり小さくしたりすることによって画像の圧縮率を変化させることが出来る。
 量子化テーブルは次の形式で記録される。マーカ2バイト+セグメント長2バイト[+量子化数値の精度4ビット+テーブル番号4ビット+64個の量子化数64バイト]なお、[]の部分は繰り返しが可能であるが、マーカ部分列自体を複数にしてもよい。
 量子化数値の精度は上位4ビットが使用されて、0ならテーブルの数値は1バイトの数値であり、1なら2バイトの数値であるが普通は0である。テーブル番号は下位4ビットが使用され、0から3までの4種類の数値である。量子化の数値は8×8の表のマス目を順に記録するのであるが、一般のように1行目の左から初めて1行目が終わると2行目、次3行目・・・、とはならずジグザグの順となっている。すなわち次の図のようになっている。

5.ハフマンテーブル
 量子化された係数値はハフマン符号化されて記録される。これはいわば符号付き可変ビット数値で、数値のビット数を表すビット(ハフマン符号)とそれに続く数値そのものを表すビット、の連続である。数値部分は、正数は上位ビットの0の連続部分、負数は上位ビットの1の連続部分をそれぞれ除いたビットである。ただし、負数の場合は元の数値から−1した数値とする(そうでないと−1は全てのビットが1となるので具合が悪い)。これにより、数値部分の最上位ビットが1なら正数、0なら負数ということになる。
 ハフマン符号は、モールス信号のようにコードの切れ目を指示しなくても意味がわかるように組み立てられた、ビット列コードである。ハフマンテーブルは、そこで使用されているハフマンコードの種類とその意味を定義したもの(画像ごとに最適化することによりファイルの大きさをより小さくできる)で、その内容は次のとおりである。
 マーカ2バイト+セグメント長2バイト

 テーブル種別4ビット+テーブル番号4ビット:上位4ビットはコードの使用対象の種別で、0は直流係数用、1は交流係数用を表す。下位4ビットはテーブル番号で0から3までの4種類の数値である。

 使用するハフマンコードの個数:コードのビット長が1ビットから16ビットのものがそれぞれ何個かをそれぞれ1バイトの数値で、計16バイトの数値列。これを基にして計算によりコードを生成可能である。

 それぞれのコードの意味:コードのビット数が少なく、コードを数値と考えたとき小さな数の順にコードを並べた順に、その意味を1バイトの数値で表した数値列。上位4ビットは0の連続数(ランレングス、後記参照)を表し、下位4ビットはコードに続く数値部分のビット数が何ビットかを表す。この数値列の合計バイト数は、前記のコードの個数の16個の数値の和になる。

 テーブル種別からコードの意味までは繰り返しが可能であるが、マーカ部分列自体を複数にしてもよい。

6.フレームヘッダ
 マーカ2バイトとセグメント長2バイトの後に、標本のビット精度1バイト(普通8である)、画像の高さ2バイト、幅2バイト(いずれもピクセル)、成分数1バイト(カラーは3、グレースケールは1である)と続き、この後に成分数だけ次の内容が繰り返される。
 成分の種類1バイト(Y成分は1、Cbは2、Crは3)、その成分は1つのMCUの中に8×8のブロックがいくつあるかを上位4ビットに横の個数、下位4ビットに縦の個数を記録した1バイト(その成分が間引きされていれば他のどれかは1×1以外になる)、その成分が使用する量子化テーブル番号(3の量子化テーブルのところで記したテーブル番号のこと)1バイト、の合計3バイト
 最も普通に見られるJPEG形式である「ベースライン」方式では、このマーカはFFC0であり、比較的よく見られる形式である「プログレッシブ」方式ではFFC2である。

7.スキャンヘッダ
 スキャンヘッダの直後に、実際の画像データであるスキャンが続く。スキャンヘッダとスキャンはベースライン方式では1組だけであるが、プログレッシブ方式では複数となる。
 スキャンヘッダは、マーカ2バイトとセグメント長2バイトの次に、そのスキャンに含まれる成分数1バイト、[成分の種類1バイト(Y成分は1、Cbは2、Crは3)、上位4ビットでその成分の直流係数に使用するハフマンテーブル番号と下位4ビットで同じく交流係数に使用するハフマンテーブル番号(いずれも5のところで記したテーブル番号のこと)を示す1バイト、の計2バイト]が続き、[]内は成分の数だけ繰り返される。
 その後に当該スキャンが、64個あるDCT係数の何番目から何番目(ジグザグ順序)までのものかが、開始番号1バイト、終了番号1バイトの順で記録される。ベースラインの場合には全ての係数が一度にスキャンされるので開始は0、終了は3Fとなる。
 一番最後に、そのスキャンデータは元の値から右に何ビットシフトしたものか(2の何乗分の1になっているか)を下位4ビットで、上位4ビットはその成分の該当DCT係数の直前のスキャンでの前記下位4ビットの値とする1バイトが来る。ベースラインではこのバイトは常に0である。

8.スキャンデータとリスタートマーカ
 その後にスキャンデータが続く。スキャンデータは連続したビット列で、データはMCUごとに記録され、MCUの並びは画像の左上から順次右に移動して、右端に来ると次は1つ下の左端から・・・と進む。MCU内ではY→Cb→Crの順に8×8のブロックごとに、4に記したジグザグ順序で記録される。
 データは5のハフマンテーブルのところで記したハフマン符号で記録される。直流係数は値そのものではなく、その成分の直前の直流係数との差(11ビット以内)が記録される。なお、スキャンの最初は値そのものが記録されるが、そのほかスキャン中にRST(リスタートマーカ)が現れたときにも、その次の直流係数は差がリセットされて値そのものが記録される。RSTがMCU何個ごとに現れるかはDRI(リスタート間隔定義)に記されている。ただし、DRI、RSTが無い画像も多い。
 交流係数はその値が0以外のときだけその値(10ビット以内)が記録される。このとき8×8のブロック内で、直前の0でない交流係数を記録してから又はブロックの初めから今回までに、係数0が何個あったかが同時に記録される。これはハフマンコードの意味には5で記したように「ランレングス」が含まれており、これが前記の0の個数に相当する。0が15個まではそれぞれに対応するハフマンコードが使用されるが、16個以上になる場合はランレングス15で数値ビット数0を意味するコード(ZRLという)を使用して0が15個あることを記録し、次に残りの0の個数と係数値について記録する。また、ブロックの最後まで0が連続する場合は、ランレングス0で数値ビット数も0を意味するハフマンコード(EOBという)が記録される。
 スキャンデータの中にFFのバイトが生じた場合にはその直後に0のバイトが挿入される。これによりマーカに使用されるFFのバイトと区別される。なお、スキャンの最後がバイト長に合わないときはビット1を補って最後のバイトを完成させる。

9.プログレッシブ(段階符号処理)形式の場合
1)特徴
 フレームヘッダマーカがFFC2のJPEG画像は、遅いモデムによる通信(最近ではほとんどみられなくなった)などにより画像を表示するとき、最初に目の粗い画像からだんだん詳細な画像に変わる方式のものであり、6に記したスキャンが複数に分かれていて、これにより少しずつ詳細になるものである。
 スキャンを分ける方式には、記録するDCT係数を分けて、最初に直流係数や交流係数の初めの方を記録し、後の方の交流係数は後の方のスキャンに記録する方法(周波数選択)と、係数の上位ビットを先に記録して後のスキャンになるに従ってだんだん下位のビットを記録する方法(逐次近似、周波数選択と組み合わせて使用)とがあり、これらを組み合わせたもの(完全段階処理)も多い。なお、逐次近似の2番目以降のスキャンでは1ビットずつのスキャンとなる。逐次近似の場合のスキャンヘッダの最終バイトは、当該成分の最初のスキャンでは、上位4ビットは0で下位4ビットは残りのスキャンの回数となり、最後のスキャンでは上位4ビットは1で下位4ビットは0となる。
2)直流係数
 プログレッシブでは直流係数は単独でスキャン(ヘッダの開始番号、終了番号とも0になる)される。逐次近似を併用する場合の2番目以降のスキャンにおいては、スキャンデータはハフマン符号ではなくビットそのものが順に記録される。
3)交流係数
 交流係数のスキャンは画像成分ごとに別のスキャン(ヘッダの成分数バイトが常に1であり、開始番号は1以上である)となる。ここで使用されるハフマン符号には、スキャンの対象となる係数(バンド、開始番号から終了番号までの係数のこと)の係数値が全て0であるバンドの連続数を表すコード(EOBs、このコードでは係数値のビット数が0であることと、このコードに続くバンドの連数を示すビット列のビット数を意味する)も使用され、このコードの後には連続するバンドの数を示すビット列(1ビットで2か3、2ビットで4から7を記録。以下同様)が続く。
 逐次近似での2番目以降のスキャンにおいては、以前のスキャンでは0であって今回のスキャンで0でない係数についてハフマンコードにより係数値が記録されるが、係数値は1ビットなので−1か1のみ(ビットでは0か1)である。0の個数は、以前のスキャンと今回のスキャンを併せたもので0のものの個数が記録されるのであり、前の係数記録又はスキャンの始めから今回の係数記録の間に、以前のスキャンで0でない係数がある場合は、今回の係数記録ビットの後に該当の係数の今回のスキャンによるビットが1ビットずつ順に記録される。これはEOBが記録される場合も同じで、0の続くバンド数を示すビット列の後に、やはりそこまでの0でない計数のビット列が続いて記録される。この様子を例示すると次のようになる。(上位2ビット以上と最下位1ビットの2スキャンの例。S01はスキャンヘッダの最終バイトの上位4ビットが0で下位4ビットが1であることを示す。また、H12は0の続き(ランレングス)が1で係数値ビット数が2を意味するハフマンコードを示す。なお、数値は、その数を表す最低限のビット列を示す。
 元の係数値の例:   29 0 10 23 4 0 1 8 13 0 0 0
 初めのスキャン:S01 H04-14-H13-5-H04-11-H02-2-H23-4-H03-6-H00(EOB)
 最後のスキャン:S10 H21-1-1-0-1-0-H00(EOB)-0-1

公式のJPEG規格書
   JIS X4301の閲覧(日本産業標準調査会にリンク)

(注)記載内容には十分注意をしたつもりですが、勘違いやミスタイプ等により誤りがあった場合はご容赦下さい。