JPEG画像形式の概要(フォーマット)。

JPEG画像のフォーマットについて解説します。

JPEG画像の概要(フォーマット)・目次。

JPEG画像でのセグメントについて。

JPEG画像のファイルはセグメントと呼ばれるブロックの集まりです。

セグメントとは、意味を持ったブロックの事で、以下の二つの形式があります。

内容を持たない、特定のセグメント。
マーカ

以下の2オクテットからなる、セグメント開始の目印です。

  • セグメントを表す、十六進数で[FF]のバイナリ。
  • セグメントの意味を与える、1オクテットのバイナリ。

つまり、特定のセグメントにはマーカ以外には内容がありません。

内容を持つ、一般のセグメント。

以下の構成になります。

マーカ

以下の2オクテットからなる、セグメント開始の目印です。

  • セグメントを表す、十六進数で[FF]のバイナリ。
  • セグメントの意味を与える、1オクテットのバイナリ。
L(セグメントの内容の長さ)(2オクテット)

セグメントの内容の長さを表します。実際にはL自身の長さ(2オクテット)も含まれますので、必ず2以上の値になります。

  • また、この値は65,535までしか入らず、依って内容は65,533オクテット以内と言う事になります。

尚、圧縮された画像データは、SOSセグメントの直後に配置される事となっております。 このデータはセグメントの形式ではありませんが、セグメントのマーカと紛らわしくなるため、十六進数で[FF]となるバイナリデータには直後に十六進数で[00]となるダミーのバイナリデータを付与する事となっております。

JPEG方式での約束事。

JPEG方式でのファイルフォーマットにおいては、以下の約束事があります。

JPEG画像の主なセグメント。

JPEG画像でのセグメントには幾つもの定義がありますが、画像展開に最低でも必要となるセグメントは以下の通りです。

SOIセグメント。

JPEG画像の先頭に必ず現れるセグメントで、画像の開始を意味します。

マーカは十六進数で[FF][D8]となります。

APP0セグメント。

APPセグメントには、圧縮方式などにより幾つもの定義がありますが、最低限必要なのはこのAPP0セグメントです。

APP0セグメントはSOIセグメントの直後に現れ、幾つかのデータを持ちますが、唯一必要なデータはセグメント内に書かれている「JFIF」という文字列です。

この文字列を見て、JPEG画像である事を判断する事になります。

マーカは十六進数で[FF][E0]となります。

具体的な内容は、以下の通りです。

マーカ(2オクテット)。
上述通り、十六進数で[FF][E0]となります。
Lp(セグメント内容の長さ)(2オクテット)。
JFIFである事を示す文字列(5オクテット)。

具体的にはアスキィ文字列「JFIF」と十六進数で[00]のバイナリです。

デコーダはこの文字列を見出して、JPEG画像ファイルと判断します。

ヴァージョンを表すバイナリ(2オクテット)。
現行の仕様では十六進数で[01][02]となります(ヴァージョン1.02を意味します)。
画像の解像度単位(1オクテット)。

一応、以下のように定義されております(いずれも十六進数でのバイナリとします)。

実際にはウェブ向けの画像では1インチ当たり72ピクセルズとされているので、[01]となります。

横方向の解像度(2オクテット)。
縦方向の解像度(2オクテット)。
ウェブ向けの画像では1インチ当たり72ピクセルズとされているので、いずれも十六進数で[00][48]となります。
サムネイルの横方向のピクセル数(1オクテット)。
サムネイルの縦方向のピクセル数(1オクテット)。
サムネイルを用意しないのであれば、どちらも十六進数で[00]となります。
サムネイルのデータ(オクテット数はサムネイルの大きさによる)。

左上から右下へ、横方向にスキャンしたサムネイルのデータを各ピクセルごとに赤成分・緑成分・青成分の3オクテットで表します。

DQTセグメント。

量子化テーブルを収めております。

量子化テーブルは、輝度データと色相データで異なったテーブルを採用する事が多いです。

具体的な形式は以下の通りです。

マーカ(2オクテット)。
十六進数で[FF][DB]となります。
Lq(セグメントの内容の長さ)(2オクテット)。

この後、以下の量子化テーブルデータが並びます。

量子化テーブルの型及び量子化テーブル番号(1オクテット)。

上4ビットは8ビット型の量子化テーブルなら[0x]、16ビット型なら[1x]となりますが、ベースライン方式では8ビット型と限られており、依って常に[0x]となります。

下4ビットは量子化テーブル番号で、多くの場合[x0]から[x3]までとなります。

実際にはベースライン方式の場合、輝度成分に対しての量子化テーブルは[00]、色相成分に対してのものは[01]が当てられる事になっております。

量子化テーブル本体(8ビット型なら64オクテット)。

この量子化データは、0番目が直流成分に対してのもの、1番目以降はジグザグスキャンによって並べ替えられた順序で並びます。

値は1だと量子化がなされず、最大値(8ビット型なら255)では完全に情報が破棄される事を意味します。

DHTセグメント。

圧縮に用いたハフマン符号表を収めております。

ハフマン符号の体系は、多くの場合輝度の直流成分, 輝度の交流成分, 色相の直流成分及び色相の交流成分で異なっております。

具体的な形式は以下の通りです。

マーカ(2オクテット)。
十六進数で[FF][C4]となります。
Lh(セグメントの内容の長さ)(2オクテット)。

この後、以下のハフマン符号表データが並びます。

ハフマン符号表の種別の型及び符号表番号(1オクテット)。

上4ビットは直流成分に対する符号表なら[0x]、交流成分に対するものなら[1x]となります。

直流成分交流成分で符号表を共有する事は不可能なので、必ず双方の符号表が存在する事となります。

すなわち、如何なる場合でも最低二つの符号表が定義される事となります。

一方下4ビットは符号表番号で、多くの場合[x0]から[x3]までとなります。

実際には、輝度成分に対しての符号表は[00]、色相成分に対してのものは[01]が当てられる事になっております。

符号の個数(16オクテット)。

先頭から順に、1ビット符号の個数, 2ビット符号の個数, … , 16ビット符号の個数となります。

符号の意味(符号の個数分のオクテット)。

直流成分の場合は、バイナリで符号に続くバイナリデータのビット数(0〜11)となります。

交流成分の場合は、以下のようなバイナリになります。

尚、下位4ビットが0となる符号として、以下の特別な符号があります。

ZRL符号(十六進数で[F0])

十六個のゼロデータが連続した場合。

後続するバイナリデータは無く、代りに新たなハフマン符号が後続します。

  • ゼロデータが十六個以上連続する場合は、必要な数だけZRL符号を出して、それから上記の正規のハフマン符号を出すようにします。
EOB符号(十六進数で[00])

データ処理が途中で打切りになる場合。

通常、63個の交流成分を全て圧縮する事になっておりますが、後ろの方が全部ゼロデータとなっている場合、一番最後のゼロで無い成分までを取扱ってそこで打切りにする事が出来ます。

その場合、このEOB符号を置いて打切りとします。

SOF0セグメント(ベースライン)。

SOF2セグメント(プログレッシヴ)。

SOFセグメントにもいろいろな定義がありますが、圧縮方式や画像形式により使われるセグメントが決まっております。

最もよく使われるハフマン符号圧縮では、以下のSOFセグメントが使われます。

ベースライン方式
SOF0セグメントが用いられます。
プログレッシヴ方式
SOF2セグメントが用いられます。

いずれもフォーマットは同じで、画像の大きさや、どの量子化テーブル及びハフマン符号表を利用するかが書かれております。

具体的な内容は、以下の通りです。

マーカ(2オクテット)。
ベースライン方式(SOF0セグメント)
十六進数で[FF][C0]となります。
プログレッシヴ方式(SOF2セグメント)
十六進数で[FF][C2]となります。
Lf(セグメント内容の長さ)(2オクテット)。
データのビット数(1オクテット)。
ベースライン方式は8ビットなので、[08]となります。
画像の高さ(2オクテット)。
画像の幅(2オクテット)。

言うまでも無く、画像の大きさを表します。

単位はピクセルです。

Nf(データのコンポーネント数)(1オクテット)。

コンポーネントとは、輝度・色相の各成分の事と思って頂ければ良いでしょう。

カラー画像の場合は、輝度・青色相・赤色相の三つのコンポーネントがあり、従ってこの値は[03]となります。

一方グレイスケールの場合は、輝度しかないため、この値は[01]になります。

この後に、各コンポーネントごとの以下のデータが並びます。

コンポーネントの番号(1オクテット)。
通常、輝度成分は[01], 青色相は[02], 及び赤色相は[03]となります。
サンプリング比率(1オクテット)。

上位4ビットが横方向の、下位4ビットが縦方向のサンプリング比率となります。

カラー画像で通常良く用いられている4:1:1方式では、輝度成分は[22]、色相成分は[11]となります。

これは、1MCU(処理単位となる画像を分割して出来たブロックで、4:1:1方式では16ピクセルズ四方)から輝度成分は縦横とも2ブロック(すなわち4ブロック)を、色相成分は縦横とも1ブロック(つまり1ブロック)をサンプリングする事となります。

利用する量子化テーブル(1オクテット)。

DQTセグメントで定義された量子化テーブル番号が当てられます。

SOSセグメント。

圧縮された画像データの前に付けられるセグメントです。

ベースライン方式では単一の画像データのみとなりますが、プログレッシヴ方式では処理を分割した組数だけ画像データが続き、従ってSOSセグメントも組数だけあります。

具体的な内容は、以下の通りです。

マーカ(2オクテット)。
十六進数で[FF][DA]となります。
Ls(セグメント内容の長さ)(2オクテット)。
Ns(データのコンポーネント数)(1オクテット)。
コンポーネントとは、SOF0セグメント同様、輝度・色相の各成分の事と思って頂ければ良いでしょう。

この後に、各コンポーネントごとの以下のデータが並びます。

コンポーネントの番号(1オクテット)。
通常、輝度成分は[01], 青色相は[02], 及び赤色相は[03]となります。
利用するハフマン符号表番号(1オクテット)。

上位4ビットが直流成分の、下位4ビットが交流成分の符号表番号となります。

番号はDHTセグメントで定義された番号となります。

カラー画像では大抵輝度成分は[00]、色相成分は[11]となりますが、しらぎくさいと実験室で公開しているJPEGエンコーダではどちらも[00]となります。

最後に、以下のデータが続きます。

スペクトルに関するデータ(3オクテット)。

具体的には

  1. 初めの1オクテットはブロック内で処理対象となる一番目の成分の番号(0〜63)
  2. 次のの1オクテットはブロック内で処理対象となる最後の成分の番号(0〜63)
  3. 最後の1オクテットは処理されるビットの範囲

を表します(詳細は割愛します)。

DRIセグメント。

RSTnセグメント。

DRIセグメントは、リスタート処理の周期(インターヴァル)を設定し、RSTnセグメントはデコーダがリスタートを行う事を表します。

リスタートとは。

圧縮過程において、直流成分は前に処理した直流成分との差分を取っていったものをハフマン符号化します。

この差分は次回の処理に引継がれ、どんどん累積していく事になります。

ところで、直流成分値によっては累積差分がハフマン符号で表現出来る範囲をオーヴァフロウする事があり得ますが、その場合生成された画像は正常な表示が出来なくなります。

このため、一定数のMCUを処理する毎に直流成分の累積差分をクリアする必要があり、この初期化動作をリスタートと言います。

実際のセグメント配置と構造。

具体的には、DRIセグメントセグメントで指定された数のMCU分の圧縮データごとにRSTnというセグメントを挿入します。

デコーダはRSTnセグメントを見出す度にリスタートを実行します。

DRIセグメントの内容は以下の通りです。

マーカ(2オクテット)。
十六進数で[FF][DD]となります。
Lr…セグメントの内容の長さ(2オクテット)。
内容は2オクテットと成るので、Lr自身の長さを合わせて十六進数で[00][04]となります。
インターヴァル(2オクテット)。
この数値の数のMCUを処理するごとに、RSTnセグメントが画像データ中に現れ、デコードに関するデータの一部がリセット(リスタート)されます。

尚、RSTnセグメントはマーカのみで内容はありません。

マーカは十六進数で[FF][Dn]となります。

DRIセグメントが設置されていない場合は、画像データ中にRSTnセグメントが現れる事はありません。

EOIセグメント。

このセグメントは画像データ終了を意味しており、JPEGファイルの末尾に必須となっております。

このセグメントは内容を持たないセグメントであり、従ってマーカのみの2オクテットとなります。

マーカは十六進数で[FF][D9]となります。

JPEG画像ファイルの構成。

ベースライン方式の場合、以下の順序で配置される事となります。

  1. SOIセグメント
  2. APP0セグメント
  3. DQTセグメント
  4. DHTセグメント
  5. SOF0セグメント
  6. (DRIセグメント)
  7. SOSセグメント
  8. 画像データ
  9. EOIセグメント

プログレッシヴ方式の場合、以下のようになります。

  1. SOIセグメント
  2. APP0セグメント
  3. DQTセグメント
  4. DHTセグメント
  5. SOF2セグメント
  6. (DRIセグメント)
  7. 以下のブロックが分割された組数だけ繰り返されます。

    1. SOSセグメント
    2. 画像データ
  8. EOIセグメント

ページ外へのご案内。