Perl/CGI研究室 'PERL-LABO'

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

gifcat.plの使い方

研究内容

gif 画像を連結してくれるライブラリ gifcat.pl の使い方を研究しましょう。

詳細

gifcat.plって?

gifcat.pl は杜甫々さんが無料で配布されている、gif画像連結処理ライブラリです。 ありがたく使わせて頂きましょう。杜甫々さんのウェブサイトは とほほのWWW入門 です。 gifcat.pl は とほほのCGIソフト集 ページから ダウンロードできます。 杜甫々さんありがとうございます!

さてこの gifcat.pl、画像を連結してくれるというのはどういうことかというと、 アクセスカウンターなどで数字を表示するときにテキストでなくて画像を使いたい場合に とても役に立つライブラリです。 先に 0 から 9 までの数字の画像を gif ファイルで用意しておきます。 そして表示するときに、この gif ファイルを好きなようにならべて1枚の gif 画像として表示して くれるんです。例えば、123 っていう数字を画像で表示したいとき、 123 っていう画像を用意しておかなくても、gifcat.pl を使えば、 1 と 2 と 3 の画像をつなげて 123 にして表示してくれるんです。 カウンタのように、数字が次々に変わるものは、その数字毎に画像ファイルを用意しておく なんてことはできっこありません。そんなわけで、この gifcat.pl というライブラリは 画像表示のアクセスカウンターを作るのには本当にありがたい素晴らしいライブラリ なのです。

さて、 最初に私が作ったように、テキストを出力するCGIプログラムはIFRAMEタグを使って 呼び出すしかありません。IFRAMEタグはサイズを指定する必要がありますが、 これがくせもので、ブラウザによってテキストを表示するのに必要なサイズが違ってきます。 たとえば、私が作った現在のテキストを表示するアクセスカウンターは、 InternetExplorer でちゃんと表示されるサイズを指定しても、 Opera で見るとそのサイズの中に文字が入りきらずにスクロールバーがでて、変なことになってしまいます。 これはなにが原因なのか、デフォルトのフォントが違うのか、微妙にマージンが違うのか、 分かりませんが、うまくいきません。 それに、そもそも、テキストで表示するカウンタよりも、画像を使って表示するカウンタの方が かっこいいです。そんなわけで、gifcat.pl の使い方を研究させて頂いて、 アクセスカウンターをかっこよくしよう!というのが真の目標です。

結果

CGIプログラムで gif 画像を出力する方法

今まで、CGIプログラムで出力を行うときはいつもテキストでした。 ですから、いつも IFRAME タグで呼び出していました。 それじゃ、画像を表示するのってどうやるんでしょう? それをまず研究しましょう。

答えは、HTTPヘッダにあります。 HTTPヘッダで、データがなんのデータか指定するんでした。 今まではテキストだけでしたので、いつも Content-type: text/html っていうのをHTTPヘッダで 出力していました。ここを変えるんです。ここを、これは gif 画像ですよ!っていう風に。 それはずばり、次のようなものです。

Content-type: image/gif

image/gif です!へぇー。こうやって指定するんですね。 で、後は普通に print とかでデータを出力すると。 画像を print で出力するっていうのもピンと来ないですけど。 …これで、第一関門突破ですね。

gifcat.plの使い方

続いて、gifcat.pl です。gifcat.pl の使い方は、杜甫々さんのウェブページで 次のように解説されています。

基本的な使い方
    require "gifcat.pl";
    open(OUT, "> out.gif");
    binmode(OUT);    # MS-DOS や Windows の場合に必要です。
    print OUT &gifcat'gifcat("0.gif", "1.gif", "2.gif");
    close(OUT);

require はいいですよね。ライブラリを読み込むんでした。 次の、open はファイルを開いています。OUT というのはファイルハンドルですね。 そして、binmode という関数。これは、名前を見ると、バイナリモードで出力するっていう 意味のようですが、Windows の場合だけみたいです。 それじゃ Linux でこの関数を呼んだらどうなるのかっていうと、何も起きないみたいです。 何も起きないですけど、もしかして Windows サーバー上で使われるかも知れないし 呼んでおいた方がいいですね。 そして、print です。ここで、gifcat 関数を呼んでいます。 &gifcat'gifcat というところですが、これは、このサイトで最初から使っていた書き方だと gifcat::gifcat になります。うーん。実は前から気になってたんですが、 私は パッケージ名::関数名 っていう書き方を最初からしてるんですが、 この書き方ってどこで覚えたんだろう?確か、&パッケージ名'関数名 っていう書き方は 古い書き方で、パッケージ名::関数名 っていう書き方が新しい書き方ってどこかで読んだように 思います。…今度調べておきます。さて gifcat 関数ですが、引数は gif ファイルのファイル名。何個でもいいみたいです。 ここで、gifcat 関数が複数の gif ファイルを連結して新しい gif を作ってくれて、 それが OUT に出力されるわけですね。そして close でファイルを閉じます。

このサンプルは、gifcat を使って新しい gif ファイルを作るやり方みたいです。 CGIプログラムの場合は、出力先はファイルじゃないです。 ファイルハンドルを指定せずに、print 文を使えばよかったんでしたね。 ですから、出力先ファイルを開いたり閉じたりっていう処理はしなくてもいいです。 ん?そうすると、binmode 関数の引数には何を渡したらいいんでしょう? 実は、print 文でなにも指定しないときっていうのは STDOUT っていう、最初から 用意されているファイルハンドルにたいして出力を行うんでした。 ですから、この場合は binmode(STDOUT) ってすればいいんですね。 まとめると次のようになります。

CGIプログラムでの基本的な使い方
    require "gifcat.pl";
    print "Content-type: image/gif\n\n";
    binmode(STDOUT);
    print gifcat::gifcat("0.gif", "1.gif", "2.gif");
とにかく使ってみる

それでは、実際に gifcat.pl を使ってみましょう。 使用する gif ファイルは、次のようなものです。 0 から 9 までの10個のファイルです。

この画像ファイル、どこからもってきたかというと、…忘れてしまいました。すいません。 フリー素材で、背景が透過色になっています。ですから、背景に色が付いていてもOKな画像です。 ただ、字が黒ですから背景が黒いとなにも見えません (^^;

それでは、この10個のファイルを連結するCGIプログラムを作りましょう。 次のようなものです。

#!/usr/bin/perl

require 'gifcat.pl';

print "Content-type: image/gif\n\n";

binmode(STDOUT);

print gifcat::gifcat(
	"img/0.gif", "img/1.gif", "img/2.gif", "img/3.gif",
	"img/4.gif", "img/5.gif", "img/6.gif", "img/7.gif",
	"img/8.gif", "img/9.gif"
);

次のリンクをクリックしてください。0 〜 9 の画像ファイルが1枚の画像として表示されます。

gifcat.pl で画像10枚を連結

表示されました!0から9までパラパラパラっと。 ひとまず成功です。

アニメーションgif

0 から 9 まで順に表示されていきますが、これは1枚の画像です。 正確には、1つのアニメーション gif なんだそうです。 アニメーション gif というのは、複数の画像をある時間間隔を置いて、 順に指定した位置に表示することでアニメーションする gif 画像のことです。 gifcat.pl は、このアニメーション gif の仕組みを利用して画像を連結しているんですね。 話によると、これは gif の特許に絡む話らしいです。 gif は特許をどこかのだれかが持っていて、なので、中のデータをいじくると こと特許に触れてしまうらしいですね。特許の有効期限がいつまでなのか調べていないのですが、 そんなわけでアニメーション gif の仕組みを使って結合をしているんだそうです。 しかし凄いことを考えますよね。このライブラリ、世界中で使われているんじゃないでしょうか? jcode.pl もそうでしたが、こうした偉人の皆様のおかげで我々は簡単に画像を使ったアクセス カウンターなどを作れるわけですから、真剣に凄いと思いますし尊敬します!!

アニメの時間間隔について

さて、アニメーション gif の仕組みを使っているということで、 パラパラパラっと画像が表示されていきます。 これ、個人の趣味が大きく絡んでくるとは思いますが、 パっと表示されるのとパラパラパラっと表示されるのと、どっちがいいでしょうか。 私の趣味では、パっと表示してくれた方が気持ちがいいように思います。 ライブラリの説明では、その辺の解説は無いみたいです。 そこで、勉強もかねて、gifcat.pl の中身を拝見して、 画像表示の時間間隔をどうやって決めているのか研究してみましょう。

gifcat.pl 自身は、gif のフォーマットが分かっていないとチンプンカンプンですから、 全てを理解しようとはせず、なんとなく流れをみていって、そして、それらしきものを見つけました。 GraphicControlExtension 関数の中の、次の部分です。

$TransparentColorFlag[$Gif]  = $PackedFields23 & 0x01;
$DelayTime             = ord(substr($buf, $cnt, 1))
		       + ord(substr($buf, $cnt+1, 1)) * 256; $cnt += 2;
$TransparentColorIndex[$Gif] = ord(substr($buf, $cnt, 1)); $cnt++;

真ん中の行です。 なんともありがたいことに、変数名が DelayTime!いかにも、それっぽいです。 分かりやすい変数名に助けられました。 で、その右辺ですが、$buf には gif ファイルの内容が入っています。 $cnt には、現在処理している、ファイルの先頭からの位置が入っていて、処理がすすむと どんどん値が大きくなってデータの後ろへ後ろへと処理が移っていきます。 substr 関数は、指定した位置の、指定した長さの文字列を得る関数でした。 ord 関数というのは、初めてみましたが、文字に対応する数値(A に対応するのが 65 だったかな?っていうのを 最初の方で研究しましたね)を返す関数だそうです。 つまり、$buf の中の $cnt バイト目の1バイトの値を取得しているんですね。 それを、2回していますが、2回目は 256 をかけています。256 というのは、16進数でいうと 100。 これはたぶん、15 が 1x10+5 と書くことができるのと同じで、 2バイト分の数値が1バイトずつに分かれているのを元の数値に戻しているんでしょう。 そうすると、2バイトで表すことができる数値は 0 〜 65535 となります。 これが終わったら、$cnt を2増やして次のデータに進んでいます。

さて、上に示した $DelayTime のところですが、これはファイルから 読み取る部分でした。問題は、書き込むときに、どんな値で書き込んでいるのかっていうことです。 もしかして、わざとパラパラパラっと表示されるように指定しているのかも…。 で、探してみました。上の、読み取る部分から逆算しまして、書き込むところは次の部分でした。

$GifImage .= pack("C", $PackedFields23 | $TransparentColorFlag[$j]);
$GifImage .= pack("CC", 0x00, 0x00);
$GifImage .= pack("C", $TransparentColorIndex[$j]);

真ん中の行が問題のところみたいです。 前後の行で処理している変数の名前が読み込みのときと同じなので分かりやすいです。 さて、期待に反して、書き込んでいる数値は 0 !つまり、もっとも短い時間間隔で 表示するように指定されています。えー、ホント?と思いました。 その割には、パラパラパラ…ですよね。で、試しに、ここの数字を変えてみたりすると、 確かに、表示される速度が遅くなることを確認しました。次のリンクをクリックしてみてください。 書き込む値、つまり表示速度を 0x30, 0x00 にした場合です。

gifcat.pl で画像10枚を連結 (ゆっくり表示)

ここまで研究して、gifcat.pl は表示時間間隔を最も短くするような処理をしていることが分かりました。 それでも、パラパラパラ…なんですね。そうだったのかー。 もしかして、ワザとゆっくりさせているのかな、パっと表示されるように変更できるんじゃないかな… と思ったんですが、残念です。でも、gifcat.pl の使い方も分かりましたし、 今回の研究も充分成果がありましたね!

なお、ちょっと調べてみたところ、gif アニメの表示時間間隔は 1/100秒 単位で指定できるんだそうです。 ということは、10枚の画像を連結したものが 10/100秒、つまり 0.1秒で表示されるはずなのになぁ、 と思うのも当然ですよね。実際は、1秒くらいかかってるかのような印象です。 gif を表示するブラウザの方がおかしいのかな?

あと、画像がゆっくり表示されるもんだから、gifcat.pl は 処理が凄く複雑で、画像を1枚ずつ時間をかけて送ってきていて、それで こうやってパラパラパラと表示されるんじゃないかっていうのも 最初思いましたが、これは完全に誤解でした。 画像連結処理、それに通信そのものは一瞬で終わっているんですが、 画像そのものが、ゆっくり表示されるような性質のものなんです。 試しに、上のリンクの、10枚の画像を連結したものをマウスでドラッグ&ドロップとかして ファイルに保存して、あらためてそのファイルをブラウザで見てみましょう。 同じように、ゆっくりパラパラと表示されます。そういうものなのですね。

その他の画像連結ライブラリ

できたら、連結した画像をパっと表示してくれる方がいいなぁ、と思って gifcat.pl 以外の画像連結ライブラリも探してみました。 そしたら、いくつかあったのですが、どうも複雑だったり、汎用性に不安があるとかで、 やっぱりまず最初は gifcat.pl を使わせて頂くのがよさそうだなぁと思いました。 もし機会があれば、他の画像連結ライブラリについても研究してみようと思います。

gifcat.pl の利用について

gifcat.pl は、無料で利用できるだけでなく、自由に改造してもいいし、 自由に再配布してもいいんだそうです。本当に、作者の杜甫々さんは凄い方ですね!

分かったこと

  1. gifcat.pl で gif 画像を連結して表示することができます。
  2. gif 画像を出力するときのHTTPヘッダは Content-type: image/gif です。
  3. 連結した画像はアニメーション gif として画面に表示されます。
  4. パラパラパラ…と画像が1枚ずつ表示されますが、これはアニメーション gif の仕様です。
  5. gifcat.pl を利用した場合、それ以上表示速度を速くすることはできないみたいです。
Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

Copyright (c) 'PERL-LABO' All Rights Reserved.  リンクフリーです。