フルカラー GIF 作成 JavaScript の説明
戻る


はじめに

[ご注意]
まず最初にお断りしておかなければなりませんが,このプログラムはオンラインで実行することはできません.
このプログラムでは入力として PNG 形式のファイルを読み込みますが,オンラインで実行している JavaScript からはセキュリティ上の理由により,ローカルに存在するファイルを読み込むことはできません.そのため,このプログラムを実行する場合は,まずこのプログラム(を含む HTML)を「名前を付けて保存」などの機能でダウンロードして,一旦ハードディスクなどのローカル ストレージに保存した後,その保存したプログラムをブラウザでロードして実行するようにしてください.
[追記]
Netscape 9 については上記のとおりですが,より新しいバージョンの Gecko ブラウザでは,必ずしもこのとおりではありません.
Firefox 3 では Netscape 9 と同じ方法でファイルを読み込むことができなくなりましたが,代わりに,別の新しい機能を使ってファイルを読み込むことができます.そのため,新しい機能が使えれば新しい機能を使い,使えない場合は以前と同じ方法を使うというように修正しました.
新しい機能を使っている場合には,オンラインで実行できます.

ではプログラムの説明に入ります.
「フルカラー GIF」というのは私が勝手にそう呼んでいるだけですが,要するに GIF で 256 色より多くの色を使った画像を表示しようという試みです.
このプログラムは,使用色数が 257 以上の画像を PNG 形式で入力し,それを 257 色以上表示できるように細工した GIF 形式に変換して出力します.
グラフィック エディタなどにオプションとしてこのような機能が付いていれば便利かも知れませんが,専用のプログラムを作るとすると,ただ元ファイルを読んで GIF に変換して出力するというだけのものになってしまうので,単独のプログラムを作るのもちょっと大袈裟な気がします.そこで「遊び部屋」のネタにしてみました.

入力ファイルの形式は,普通のプログラムとして作るのであれば,そのプログラムの動く OS で標準の画像ファイル形式にするのが自然なのでしょうが,JavaScript の場合は実行する OS が定まらないので,PNG を使うことにしました.

バイナリ ファイルを読み込まなければならないため,使用するブラウザの種類・バージョンはかなり限定されてしまいます.
Netscape 9 用に作っていますが,同程度以上のバージョンの Gecko エンジンを使用したブラウザなら多分動作するのではないかと思います.
Microsoft Windows 用と Linux 用の Netscape で動作確認しています.Macintosh 用については動作未確認です.

なお,GIF の仕様の本来の意図とは異なる使い方をしていますので,作成した GIF を表示する際,使用するプログラム(ウェブ ブラウザなど)によってはうまく表示できない場合もあるかも知れません.
いくつかのウェブ ブラウザで試してみましたが,私が試した範囲ではどれも正常に表示されました.
後述のように,アニメーション用の機能を使って実現しているので,アニメーション表示に対応していないプログラムでは表示できません.


使い方
  1. まず,元になる画像を PNG 形式のファイルで用意します.
  2. 「入力ファイル」でそのファイルを選択します.選択したファイルのサムネイルが表示されます.
  3. 「作成」をクリックすると,GIF 作成を開始します.
  4. GIF 作成が完了すると,作成した GIF 画像のサムネイルが表示されます.
「表示」をクリックすると,作成した画像を別ウィンドウで表示します.「保存」をクリックすると,作成した画像をファイル ダウンロードの形で保存できます.
表示や保存は,GIF 画像のサムネイルを右クリックして出るメニューからでも可能です.

PNG では,色の形式としてグレースケール,RGB(フルカラー),パレット インデックスが使えますが,このプログラムでは RGB のみ扱います.グレースケール,パレット インデックスの形式で表せる色は通常の GIF でも表せるため,フルカラー GIF にする必要がないためです.
正確には,グレースケールの場合は色のビット深度として 16 ビットも可能で,それは GIF では表せないのですが,それはそもそも GIF の仕様が 16 ビットの色をサポートしていないためなので,このプログラムを使ってもそれは回避できません.
同様に,RGB の場合も 16 ビット(1 原色あたり)の色が可能ですが,それは GIF では表せません.このプログラムでは 16 ビットの RGB の PNG を入力として使うことはできますが,作成した GIF は 8 ビットに減色されます.

このプログラムでは入力画像の色数を 65536 までに制限しています.
理論的には何色でも可能ですが,あまり色数が多いと変換に時間が掛かりますし,メモリ不足でエラーになる可能性もあります.また,作成した GIF を表示する際にも何か支障が出るかも知れません.そのため一応色数を制限しました.
色数が多い場合は,あらかじめグラフィック エディタなどである程度減色してから変換してください.

入力として 256 色以下の画像を指定した場合,それは本来フルカラー GIF に変換する必要がないものであるため,GIF 作成を行うかどうかを確認するメッセージが表示されます.作成することを選択した場合は処理を続行しますが,ちょうど 256 色の画像を使った場合,255 色と 1 色の 2 フレームの GIF に変換されます.(後述の説明を参照)

PNG ではアルファ チャネルによる半透過を使えますが,GIF では使えません.
このプログラムでは,アルファ チャネル付きの PNG を入力として使っても処理は行いますが,アルファ チャネルは無視されます.
PNG ではアルファ チャネルの他に,'tRNS' チャンクで指定する透過(GIF のように特定の 1 色だけを透過にする機能)もあります.'tRNS' チャンクの透過は GIF の透過に変換します.

インタレースを使った PNG は使えません.
GIF でもインタレースは使えますが PNG とは違う形式のものですし,フルカラー GIF ではそもそも表示が画像上部から順に行われるとは限らないので,インタレースの使用は意味がないためです.


原理

一般的には,GIF では 256 色までの画像しか表示できないとされています.しかし,GIF でも 256 を超える色数の画像が表示される場合があります.それはアニメーションを行う場合です.
GIF アニメーションでは,ひとつの GIF の中に複数のフレームを作成します.それを時間差を置いて順番に表示することでアニメーションを行います.各フレームの大きさは同じでなくても構わず,画像の一部分をあるフレームで書き換え,別の部分を別のフレームで書き換えるということを行うと,最終的には複数のフレームが合成された画像が出来上がります.

各フレームで使用できる色は最大 256 色ですが,各フレームは別々のカラー テーブル(パレット)を使うこともできるので,合成された画像の色数は 256 より多くなる場合があります.
次に示す GIF 画像では,最初に黒〜赤の 256 階調のグラデーションを表示し,3 秒後に下半分の領域を黒〜緑の 256 階調のグラデーションで上書きしています.
アニメーションの例
結果的に,全部で 511 色(黒は共通)の色を使った画像が出来ることになります.

各フレームの表示開始時間は任意に設定できます.すべてのフレームを時間 0,つまり最初から表示するように設定すれば,1 枚の画像に近い形で色数の多い画像を表示できるはずです.

しかし,これだけではまだ充分ではありません.上の例のように,使用する色が単純な矩形領域で別れている場合にはよいのですが,通常の画像では同じ色が画像内のいろいろな箇所に現われます.そのため,単純な矩形領域に分割することはできません.
たとえば次の画像では 401 色が使われていますが,こうなると単純な矩形領域のフレームに分割することはできません.
サンプル画像
(PNG 画像)
もちろん,256 色以下の小さい矩形領域に細かく分割することは可能ですが,それではフレーム数が非常に多くなってしまいます.そこで,透過表示の機能を使ってフレームを合成します.
処理の概要は次のようになります.
  1. 元の画像に使われている色をすべて集める.
  2. 集めた色を 255 色ごとのブロックに分割し,各ブロックに対応してフレームを作成する.
  3. フレームのカラー テーブルの 255 のエントリに該当ブロックの色を割り当て,残りの 1 エントリは透過色に使用する.
  4. 該当ブロックに含まれる色についてはその色で表示するようにし,それ以外の色についてはすべて透過色を設定する.
上の画像の場合だと 401 色を 255 色と 146 色に分割し,2 フレームを作成します.
各フレームの画像は次のようなものになります.この画像では説明のため,実際には透過になる部分を黄色で表示しています.
1 番目のフレーム
サンプル画像 フレーム 1

2 番目のフレーム
サンプル画像 フレーム 2
これを合成すると,次のような画像が出来上がります.(この画像が上の PNG 画像と同じに見えていない場合は,ご使用のブラウザではフルカラー GIF をうまく表示できないということです.)
サンプル画像 GIF
(GIF 画像)
実は,最初のフレームについては必ずしも透過色を使う必要はなく,256 色のエントリすべてを画像内の色の表示に使うことも可能です.該当の 256 色以外の箇所はすべて後に続くフレームで上書きされるので,その箇所には 256 色中のどれかの色を仮に設定しておけばよいことになります.
しかしそのようにした場合,最初の 256 色以外の箇所は,一旦本来の色とは異なる色で表示された後本来の色に変わることになり,あまりスマートではありません.
また,画像に本来の意味での透過部分を作りたい場合,つまりすべてのフレームを合成した最終画像に透過する箇所がある場合は,結局最初のフレームにも透過色が必要になります.
そのような理由から,最初のフレームについても特に処理を分けず,常に透過色を使うようにしています.

もうひとつ考慮しておかなければならないことがあります.それは,アニメーションのループ再生についてです.
GIF アニメーションではループを設定して,アニメーションを繰り返し再生することがよくあります.フルカラー GIF に対してループ再生が行われると,すべてのフレームの表示が完了した後,また最初のフレームから書き直しが始まってしまいます.
ループ再生の機能は GIF の仕様(GIF89a)にはなく,Netscape によるアプリケーション拡張として定義されています.元々は Netscape 独自の拡張ですが,後に他のブラウザでもサポートされるようになったものです.
GIF の仕様にはないものですから,ループ再生をしたくなければ単に該当アプリケーション拡張を設定しなければよいだけのはずなのですが,現実には無条件に GIF アニメーションをループ再生してしまうブラウザがあります.また,GIF ファイルに指定がなくても任意の回数ループするような設定ができるようなブラウザもあるかも知れません.

そこでその対策として,最後のフレームの表示時間を可能な限り大きな値に設定しておくことにします.設定可能な表示時間の最大は 655.35 秒です.そのようにしておけば,もしループ再生が行われたとしてもその間隔は 655.35 秒(約 10.9 分)になります.ブラウザでウェブ ページを見ているような状況を想定した場合,これは充分長い時間と思われます.


作成例

少し色数の多い画像について実際に GIF を作成した例です.8572 色(34 フレーム)の画像です.
入力 PNG
作成例 PNG
出力 GIF
作成例 GIF

戻る