PNG (Portable Network Graphics, ピング) フォーマット。
この章では、PNG フォーマットの機能のそれぞれについて、ざっと紹介していきます。しかし、GIF 問題を初めて認識されたあなたにとっては、おそらく PNG の詳しい機能などには興味がないことでしょう。あなたの最も知りたいことは、PNG の高機能性ではなく、本当に GIF の代わりになるのか、ということのはずです。だから、この章はあなたにとって少々たいくつなことでしょう。
PNG 画像は、横幅と高さを持った、1枚の長方形です。JPEG フォーマットのように本体とは別のサムネイル画像(縮小画像)を格納したり、GIF フォーマットのように複数の画像を格納したりすることはありません。
幅と高さは、それぞれ、1〜231-1ピクセルまで可能です。0 ピクセルにすることはできません。
PNG フォーマットは次の 3 タイプのカラー形式があります。それぞれ特徴や格納形式が違います。
グレイスケール 2, 4, 16, 256, 65536 段階の、5種類から選ぶことができます。
GIF フォーマットと同じ手法です。パレットを使うことで、トゥルーカラー PNG よりもサイズが小さくなります。パレット数 2, 4, 16, 256 個 の 4 種類から選ぶことができます。
画像データとは別にパレットテーブルを持つ必要があります。各パレットは 24 bit カラー(1677 万色)の中から任意に選ぶことができます。
1677 万色(24 bit フルカラー)、280 兆色(48 bit トゥルーカラー)の 2 種類を選択できますが、通常は 1677 万色を選択すると思います。なぜなら、現時点で約 280 兆色を処理できるマシンや画像ツールは少ないでしょう。
PNG 画像は、可逆圧縮です。JPEG のような非可逆圧縮はあり得ません。
PNG 画像は、Deflate 圧縮データ形式で圧縮されています。Deflate では、
このいずれかの方法で圧縮することになります。特別の事情がなければ 3 番目を選ぶとよいでしょう。
LZ77 も、ハフマンも、時間をかけることによって圧縮率を向上させることができます。どの程度圧縮率を重視するか、または圧縮速度を重視するかは、アプリケーションの判断にゆだねられています(オプション指定によってユーザーが選択できる場合もあるでしょう)。
画像作成者はどの程度の圧縮率を選択すべきでしょうか? 実は、展開にかかる時間は、圧縮率にほとんど依存しません。よって、最大限の圧縮率重視で構わないでしょう。
PNG の Deflation 圧縮方式は LZW より古いもので、単独の圧縮効率の点からいえば LZW に劣ります。( LZW は優れた圧縮アルゴリズムです。)。これを補うために、PNG ではフィルタリングという差分調整を行います。これは画像情報はいっぱんに変化がなだらかな情報の集まりという特性を生かし、圧縮効率を上げる工夫です。
Deflation による圧縮に加え、画像データをあらかじめフィルタリング処理を行うことによって、Deflation による圧縮効率を高めることができます。
注意: PNG でいう「フィルタ」とは、圧縮の前処理を行う手法であって、画像そのものに手を加えるわけではありません。どのフィルタを使ったとしても画像そのものは変化しません。
現在は、5種類のフィルタ用アルゴリズムが用意されています。絵柄にあった適切なアルゴリズムを選ぶことで、ファイルサイズを効果的に減少させることができます
フィルタ形式 | フィルタ特徴 | 適用すべきイメージ |
---|---|---|
None | フィルタを適用しません。 | インデックスカラーPNG (256色)や、2 階調グレイスケール PNG 画像は、フィルタ無しが有利です。 |
Sub | 左にあるピクセルからの差分情報を扱います。 | 横方向に似たような色が続く部分が多い領域に有効です。 |
Up | 真上にあるピクセルからの差分情報を扱います。 | 縦方向に似たような色が続く部分が多い領域に有効です。 |
Average | 左と、真上の 2 ピクセルからの平均値から、ピクセルの色を予測し、その予測からの差分情報を扱います。 | 似たような変化の色をもった領域に有効です。 |
Paeth | 左、真上、左上の 3 ピクセルを関数に代入し計算値を作成します。計算値と、左、真上、左上との差分をそれぞれ取り、もっとも差分が少ないピクセルを予測値とし、その予測からの差分が情報を扱います。 | Sub、Up、Average の効果が低い領域、なだらかな色の領域に有効です。 |
フィルタは、1水平ライン毎に異なるフィルタを指定します。
注意: もしあなたが特別の事情によって Deflate 圧縮データ形式に「無圧縮」を指定していた場合、フィルタが無意味なものになるばかりでなく、フィルタのぶんだけ生画像データが増えます。その増分は必ず 縦のピクセル数 バイトです。
各ラインにどのフィルタを適用するかは、完全にアプリケーションに任されています。ですので、まったく同じ画像でも、アプリケーションによって圧縮効率が全然違います。残念ながら現在の計算機能力では、フィルタ組み合わせの最適解の計算を瞬時に完了させることはできません。もし、Pentium 400MHz マシンで、厳密に 200x200pixel フルカラー PNG 画像の最適解を求めようとするならば、10 分やそこらでは完了しません。
従って、最適解にできるだけ近似したフィルタの組み合わせを求める能力がツールに求められます。我々の調査では、どういうわけか Adobe 社のフィルタ圧縮能力は著しく低く、その他のベンダー製の PNG ツールはほぼ十分な圧縮効率を達成しています。
ではここで実際に、フィルタリングのアルゴリズムを『ごくかんたん』にご説明しましょう。サンプルの画像として、横幅10ピクセル、縦幅1ピクセルの全体的に赤っぽいPNG画像を用意しました。フィルタ形式は、Sub(真横の平均)を選びます。
( width 10 x height 1 の 24 bit フルカラー PNG 画像の例) |
フィルタは1水平ライン(スキャンラインといいます)ごとに行なわれます。このサンプル画像では、縦幅が1ピクセルしかないので、この横1列全体に対して、Sub のフィルタをかけます。
下の表を併せて見て下さい。Sub フィルターは、それぞれのひとつ左のピクセルに対応するバイト値との差分を取ります。まずは 1 つ目のピクセルですが、左には何もないので、全てが0であるピクセル(完全な黒)があるものとして計算します。本番はここからです。2 つ目のピクセルに注目しましょう。第 2 ピクセルは RGB: C03030 のピクセルであり、ひとつ左の RGB: B03020 との差分を取ると、RGB: 100000 となります。この作業を繰り返すと、フィルタリング後のバイト列が出来上がります。
色 | ||||||||||||||||||||||||||||||
データ並び | B0 | 30 | 20 | C0 | 30 | 30 | D0 | 40 | 20 | C0 | 40 | 20 | C0 | 40 | 20 | D0 | 80 | 10 | E0 | 80 | 00 | FF | 80 | 00 | FF | 00 | 00 | FF | 00 | 00 |
フィルタ後 | B0 | 30 | 20 | 10 | 00 | 00 | 10 | 10 | F0 | F0 | 00 | 00 | 00 | 00 | 00 | 10 | 40 | F0 | 10 | 00 | F0 | 1F | 00 | 00 | 00 | 80 | 00 | 00 | 00 | 00 |
フィルタを使うことによって、本当にデータ量が減ったのでしょうか? データ数を見ると、フィルタリング前後で全く変わっていません。このように、フィルタ自身はデータ量を減らしません。それどころか、各スキャンラインのデータの先頭には、使用したフィルタ形式を表す1バイトがくっつくので、逆に 1 バイト増えています。
しかし、フィルタリング後のデータはかなり冗長になったでしょう。冗長なデータほどこの後の Deflation による圧縮率が増加すると期待されます。この画像サンプルは1ピクセルごとに色が変化する忙しいデータ並びですが、一般の画像はこれほど変化しないことが多く、さらに冗長性がA}$9$3$H$G$7$g$&!#
PNG 画像は、プログレッシブ表示を行なうためのインターレースに対応しています。
通常画像が、データ並びのまま上から下へ表示していくのに対し、インターレース画像は、まず全体を歯抜きのように表示させ、徐々に間を埋めていき、じわじわと鮮明に表示します。一般に、画像をインターレース化することで、一般にファイルサイズは増加しますが、いち早く全体のイメージをユーザへ伝えることができます。
PNG フォーマットでは、Adam 氏が考案した「Adam7」と呼ばれる手法を採用して、合計7回のパスで全体を表示させます。
GIF の時はどうだったでしょうか。インターレース GIF の場合、画像を8ラインごとに区切り、計4回のパスで表示していました。一方インターレース PNG の場合、画像を8x8の正方形に区切り、計7回のパスで表示します。言葉だけではわかりにくいので、下の図と合わせてご覧下さい。
注意: 上図は、あくまで表示順序を示すだけの模式図です。
インターレース PNG は、
という利点があります。
さて、インターレース PNG は、インターレース GIF より表示速度も速く、見やすさも上だと書きました。良い歌い文句には、落とし穴がつきものです。本当に PNG の方が有利なのかを、上記の原理をもとに、実際の「ジワジワ」イメージを作ってみました。
注意: 比べやすいように、縦横2倍に拡大してあります。
まず、「見やすさ」という点で比較してみますと、(4) のところで比べてみれば一目瞭然です。お互い全データ部の 1/8 を読んだ時点ですが、GIF の方がわけのわからないバーコード状態なのに対し、PNG はすでに全体像がつかめています。クリッカブルマップでは特に威力を発揮するでしょう。「少年の眼がリンクになっている」とすれば、(4) の時点であなたはインターレース GIF と インターレース PNG のどちらの眼がクリックしやすいですか?
次に、「初めに全体画像を描画するまでのスピード」ですが、スペック的には GIF では全データの 1/8 なのに対し、PNG では 1/64 となっています。画像の総サイズが 64k だったとして、GIF 画像は 約 8k を読んだあたりから全体が表示されるのに対し、PNG 画像はたった 1k を読んだだけで全体が表示されはじめるのです!。インターレース PNG の方が実に 8 倍も速く全体像をつかむことができます。
補足: しかし、Internet Explorer 4/5 は、インターレース PNG の初めの3回のパスを飛ばして、ラスト4パスだけを表示します。初めに表示するまでのスピードとしては、GIF と全く同じです。何度もリフレッシュするよりは初めの情報量の少ないパスを飛ばしてクライアントの負荷を下げる意図があるのでしょう。Netscape Navigator は PNG スペックどおり 7 回のパスで表示します。
ただ残念なことにインターレース PNG について、私の調査では、
という結果を導きました。これは、インターレース GIF とは比べて、かなり不利です。Adam7 のアルゴリズムにしたがって、画像をメッタ切りに分割しているので、圧縮効率が激減したものと思われます。不必要にインターレースにするのは避けねばなりません。PNG の開発者は、全体のサイズが増加してでも、初めのパスが 1/64 で表示できるメリットの方が大きいと考えたのでしょう。
以前の画像ファーマットでは、作成された画像を他プラットフォームで表示すると、明るさが変化して見える問題点があり、Web デザイナーを悩ませていました。たとえば Windows では ガンマ値 1/2.2、Mac OS では ガンマ値 1/1.8 とプラットフォームによって異なり、Win⇔Mac 間で画像を移行すると、明るすぎたり暗すぎたりと作成者の意図とは異なる明るさで表示される現象が起こったのです。PNG はガンマ値を設定し、どのプラットフォームでも適切に表示できるように指定できます。
ガンマ値は、0〜1 の範囲で、100000 段階で指定します。100000 倍したものが実際のガンマ値となるように指定します。(例:1/2.2 は 45455、1/1.8 は 55556)
ガンマ補正は任意です。ガンマ値が指定されていなかった場合、PNG ビューアは、標準的なガンマ値 1/2.2 が指定されたものと見て表示することが多いです。また、ガンマ補正はαチャンネルには、影響を与えません。
PNG では、全てのピクセルについて透明度を指定する「αチャンネル」機能、または、いくつかの色だけを透明にしたいときのための「透過色」機能の、どちらか一方だけを使うことができます。どちらとも使わなくても構いません。
αチャンネルは、非常に強力な透過設定です。
αチャンネルを用いると、画像中のすべてのピクセルは、RGBの情報に加えて透明度を定義するα値の情報を持つようになります。あるピクセルにおいて、α=0の場合は完全に透明で、後ろの背景色がそのまま表示され、α=MAXの場合は完全に不透明です。α値が中間の値を取った場合、いわゆる「半透明」が表現できます。すべてのピクセルが透明度情報を持つのですから、サイズ増加は免れません。
α値のとりうる範囲は、その画像の色深度と同じです。たとえば、各RGBが 0〜255 の範囲を取り得るフルカラー1677万色画像の場合、α値もまた 0〜255 です。(例:R=255、G=234、B=14、α=127)
αチャンネルは、グレイスケール PNG とトゥルーカラー PNG で有効です。
透過色は、簡易な透過設定です。
たとえば、透過 GIF のように1色だけを透明にしたいだけなのに、全てのピクセルに透過情報を持たせる「αチャンネル」では、不必要にサイズを消費してしまい非常にバカらしいことになります。こういうケースではαチャンネルを使わなくても、いくつかの色だけに透明度情報を持たせる「透過色」機能でたいがい間に合います。「透過色」機能は、カラータイプにより、その機構が少しずつ違います。
グレイスケール 65536 レベルのうち、何種類でも透明定義を行えます。透明定義されたグレイレベルは完全透明(α=0)で、その他のグレイレベルは完全不透明になります。「半透明」は表現できません。
最大 256個のパレットにおいて、それぞれα値を設定できます。α値は 0〜255 を取りうり半透明も定義できます。パレット0から順番に定義してゆきますが、定義されなかったパレットはすべてα=255(完全不透明)と定義されます。
何色でも透明色に定義できます。透明定義された色は完全透明(α=0)で、定義されなかった色は完全不透明になります。「半透明」は表現できません。
PNG 画像は、任意でテキスト情報をもつことが出来ます。テキストに使われるエンコーディングは、
のどちらかを使用することになります。日本語を扱いたければ UTF-8 しか選択肢がありません。格納できる文字数は無制限です。
テキストデータは、Deflation で圧縮して格納するか否かを選ぶことができます。
『この画像の著作権は、その作成者であるうんたらかんたらほんだらへんだらはんだら…』
というような、長くてつまらないメッセージは、圧縮して格納するとよいでしょう。一方、
『みずみずしい夕張メロンの画像です。』
というような、画像に説明を与えるたぐいのメッセージであれば、むしろ圧縮せずに格納することが好まれるでしょう。PNG ビューアで全体の画像を展開する前に、この画像についての情報が得られるチャンスが生まれます。
補足: とはいうものの、日本語の場合、可変長エンコード UTF-8 によってギタギタにされてしまった文字列が、あなたのバイナリエディタで閲覧できる可能性は、低いでしょう。
このテキストデータの位置は、PNG 画像のどの部分に置くこともできます。プレーンテキストを先頭のほうに配置することで、バイナリエディタで画像を直接見たときに、コメントが見やすくなるかもしれません。
背景色を1色選ぶことができます。
この指定は、背景色を PNG 表示ソフトに指示するだけで、実際に背景色をどう扱うかは、個々の PNG 表示ソフトにまったく任されています。
意図的にアスペクト比(縦横の比率)を指定することができます。
実際のアスペクト比率を定義するか、または縦横それぞれの ppm (Pixels per meter, 1メートルあたり何ピクセルか)の、どちらかで指定できます。
実際に格納されている色深度よりも、実際に表示するときはより低い色深度で表示させたいときに使います。
たとえば、色情報としては 48bit (約280兆色) の深度で保存しておくが、一般的に280兆色を扱える環境は少ないため、表示させるときには 24bit カラー(約1677万色) に減色させたいときに用います。この場合、R:0xFFF G:0xAAA B:0xB92 という色情報を持つピクセルは、R:0xFF G:0xAA B:0xB9 だとして表示されます。
画像中の、すべての色の範囲を表示することが出来ないときのために、あらかじめ減色パレットが用意された減色パレットセットを使うことができます。減色パレットセット中には何色でも定義できます。各色はそれぞれ、R、G、B、α値、頻度を定義します。
頻度は 0 〜 65535 の範囲で指定し、他の色と比較したときの「重要度」を定義します。たとえば肌色系統の頻度を上げておくことで、人間の顔がより効果的に減色されるかもしれません。すべての色の頻度が同じだった場合、意味がありません。
画像中の、すべての色の範囲を表示することが出来ないときのために、あらかじめ色の頻度を指定しておき、減色の際に有効活用します。あまり重要でない色は省くために、ソフトにヒントを与えるものです。
頻度は 0 〜 65535 の範囲で指定し、他のパレットと比較したときの「重要度」を各色についてそれぞれ定義します。たとえば肌色系統の頻度を上げておくことで、人間の顔がより効果的に減色されるかもしれません。すべてのパレットの頻度が同じだった場合、意味がありません。
画像が最終更新された時間を保存しておけます。年、月、日、時、分、秒までの単位です。西暦 65535 年まで扱えます。