2004年6月20日をもって、LZW圧縮技術に関するUNISYSの特許は日本国内で期限切れになりました。したがって以下で説明している小細工はもはや無意味ですが、何かの参考になる可能性もないとは言い切れないのでこのページは一応そのまま残しておきます。
[はじめに] [作成手順] [サンプル] [gzipで圧縮] [Content-Negotiation] [リンク] [更新履歴]GIF画像に使われているLZW圧縮という技術は、UNISYSが特許を取得しているため、GIF画像を扱うソフトウェアを公開するにはUNISYSとライセンス契約を結ぶ必要があります。逆にいえばLZW圧縮技術さえ使わなければ、UNISYSの特許には抵触しません。
デメリットは圧縮できないので、サイズが大きくなることです。インターネット上で配布する画像形式としては、これはかなり深刻な問題点です。
ライセンスの制約を受けない新しい画像形式としてPNGが提唱されていますが、「画像をインラインで表示できるほとんどどんなブラウザでも対応している」というGIFの何者にも代え難い長所は覆せそうにありません。
さらにPNGではアニメーションが表現できません。アニメーションを表現できる形式としてMNGというのがいちおう提唱されてはいますが、私の知る限りインライン画像として表示できる対応ブラウザはMozilla(M17以降)/Netscape 6(PR2以降)くらいしかありません。
(2003/06/22 追記)とうとうMozillaでもMNGのサポートが外されてしまいました(Bug 195280)。
個人的にはPNGがGIFを撲滅する前に、LZW圧縮技術の特許の保護期間が切れるのではないかと思っています(1983年出願なので保護期間は2003年までです)。
(2000/03/04 追記)と思っていたのですが、米国特許はちょっと修正したものを保護期間内に出願しなおすとかの技で事実上無限に保護期間を延長できるという話を聞いたので、甘かったかもしれません。とりあえず日本国内で使う分には関係なさげですが、インターネット上で公開するなら日本国内というのはちょっと厳しそうです。
(2003/06/22 追記)2003/06/20に米国でのLZW圧縮技術の特許が期限切れになりました。UNISYSは延長しなかったようです。日本で期限切れになるのは1年後の2004/06/20です。
n ビット画像の場合なら、以下のようになります。
nではわかりにくいかもしれないので、具体例をあげてみます。
8ビット画像の場合なら、以下のようになります。
8 * 254ビットが9 * 255ビットになって書き込まれるので、だいたい元イメージより13%サイズが増加します(前後に追加される8 + 9 = 17ビットは元イメージのサイズに関係なく同じビット数なので無視している)。
4ビット画像の場合なら、以下のようになります。
4 * 14ビットが5 * 15ビットになって書き込まれるので、だいたい元イメージより34%サイズが増加します(前後に追加される8 + 5 = 13ビットは元イメージのサイズに関係なく同じビット数なので無視している)。
KISS/GSのセルを無圧縮のGIFに変換します。
>
cel2gif [-I] KCFファイル CELファイル [CELファイル...]
生成されるファイルはセルと同名で、拡張子だけが .gif になります。
-Iオプションを指定するとインタレースGIFを生成します。無圧縮GIFはサイズが大きいですし、インタレースにしてサイズが大きくなることもないので、インタレースにしたほうがいいでしょう。
ただしインタレースを指定すると画像をすべて一度にメモリに読み込むので、メモリの少ない環境ではメモリ不足で変換に失敗することがあります。
4ビット / 8ビットのセルに対応しています。パレット(KCF)は24ビットのみの対応です(手抜き)。KISSの透明色情報やオフセット情報もそのまま変換します。
付属のバイナリはWin32 Console用ですが、付属のソースを再コンパイルすればたいていの環境で使えるでしょう。
本プログラムの無断再利用の禁止を禁止します【謎】。
あまり知られていませんが、HTTPでは転送するデータを圧縮(に限らず符号化)することができます。このとき、HTTPヘッダのContent-Encodingというフィールドで符号化の方式を示します。
Apacheのデフォルトの設定では、拡張子.gzのファイルを送り出すとき自動的にContent-Encoding: x-gzipを付加します。ということは、これを使えば無圧縮GIFをgzipで圧縮してネットワークの帯域を減らせるのでは…と期待が掛かりますが、世の中そんなに甘くありません。Content-Encodingヘッダは、HTTP/1.0のころからあるにもかかわらず、かならずしも対応ブラウザは多くないのです。
たとえば、Netscape Communicatorは4.06でようやくContent-Encoding: x-gzipに対応しました。それ以前のバージョンでは壊れた絵のアイコンがむなしく表示されるだけです。
さらに4.06以降であっても、gzip圧縮した画像を表示できるのは直接画像のURLを指定したときだけで、IMG要素などでHTMLに埋め込んだ場合には最初の1回は表示されません。
右クリックして「画像を表示」すれば表示されたり、すでにキャッシュに入っている画像なら表示されたりはしますが、初めて訪問した客が壊れた絵のアイコンばかり目にしたら、そのまま退散してしまうような気がします。
これではGIFの透過表示の機能などは有効に活用できません(単体で表示できればいいならそれこそPNGで十分です)。
IEはさらに謎で、Windows版のIE4がContent-Encoding: x-gzipに対応しているらしいことは確認しましたが、条件によって表示されたりされなかったりします。条件はいまだに不明です。インターネット オプションの詳細設定で「HTTP 1.1を使用する」のチェックを外すとAccept-Encodingを送らなくなるしContent-Encoding: x-gzipも認識しなくなるようです。Accept-EncodingやContent-EncodingはHTTP/1.0からあるはずなのですがどうしてそういう仕様なのかは謎です。また、IE4では最初に1回直接画像を表示しないとIMGでは表示されないようです。1回でも表示しておけばあとは大丈夫なようです。さらにMacのIEは最新の5.0でもContent-Encoding: x-gzipを認識しません。
手もとにあったHotJava 3.0やOpera 3.60やiCab Pre 1.9aなども試してみましたが、全滅でした。どれ1つとしてgzip圧縮したGIFを表示できません。iCabに至ってはタイプ10のエラーとかで落ちる始末。
というわけでgzip圧縮の画像は、NN 4.06以降/WindowsのIE 4.0以降など、極めて限られた環境でしか表示できません。しかも制限付きです。これならPNGのほうがまだマシです。GIFアニメが手離せないという向きには多少は意味があるかもしれませんが。
(2000/04/03 追記) Mozillaでは完全対応しました。さすがです。M17以降でMNGにも対応したのでMNGを使ったほうがいいかもしれませんが。Netscape 6.0 PR1には残念ながらまだ組み込まれていないようです。IE5(Win)ではサポートされなくなったようです。さすが【謎】。
Apacheの場合、MultiViewsオプションを有効にして同じディレクトリにfoo.pngとfoo.gif.gzとfoo.gifを置いておき、fooという名前のリソースを要求すると、ブラウザの能力に合わせて最適な形式の画像を自動的に選んで返してくれます。
というわけでいろんな形式の画像を全部用意しておくのが一番いいかもしれません。
(2005-03-27)True Color GIF画像のサンプルがあります。独自拡張ではありませんが、GIFは256色までしか扱えないとあまりにも広く信じられているためにビューアーによっては表示できない可能性があります。とりあえずFirefox 1.0.2/Internet Explorer 6/Opera 7.54 update 2などでは表示できるようです(2013-12-11追記)が、アニメーションGIFとみなされて「フレーム」間に強制的にウェイトが入るためのろのろと表示されます。Firefox 29ではこの問題が修正されました。Windows XP標準の「画像と FAX ビューア」では表示できませんでした。ペイントでは開くことはできて一瞬で表示されますが、GIFのまま保存すると256色に減色されてしまいます。(2013-12-11追記) Windows 8.1標準の「Windows フォト ビューアー」では最初の「フレーム」しか表示されず、Windows 8.1のペイントで開いても正しく表示されません。このGIFファイルの作成に使われているANGIFライブラリは、時期的な関係(最終更新1999年)から特許の問題を避けるために無圧縮GIFを生成しています。
GIFの解説(英語)。上記のリンクはここで見つけました。
(2005-04-02)ABYSSより。ここでもフルカラーのGIFを扱っています。ここによるとIE3やNetscape3の頃から対応していた模様。
(2001/08/07)メールが来てたのを思い出したのでリンクしてみる。なぜかトップからリンクが張られてない。もしかして返事を待ってるのだろうか。そういうメールには見えなかったのだが。
(2000/09/07)いつの間にかこっちにリンクを張られていたので正式に張り返す。
しかも表示処理に関してはかならずLZW相当の技術が必要なので、
とのことだが、無圧縮GIFだけ展開できればいいならエンコードの逆をやればいいだけなのでLZWの出る幕はないはず。
このページをMacのIE 4.5で見るとソース表示になると思うのだが、PNGが表示できないIE 4.5なんか捨ててさっさとIE 5に移行しなさいという教育的指導なのだろうか。
UNISYSの特許の請求項にある辞書テーブルを使わないで圧縮・展開を行う方法を紹介しています。
無圧縮GIFをgzipで圧縮してHTTPヘッダにContent-Encodingといれればブラウザが勝手に展開して表示してくれるというアイデアが紹介されています。やはり同じようなことはみんな思い付くものです。
なお、紹介文を読むといかにもほとんどのブラウザで使えそうに書かれていますが、これに対応したブラウザの範囲は実はそんなに広くありません(詳細)。下手をするとPNGのほうが広いくらいです。
確かにContent-EncodingヘッダはRFC 1945 (HTTP/1.0)にも出てきますが、たとえばLINK要素などはHTML 2.0からあるにもかかわらずいまだにIEもNNもほとんどサポートしていません。無圧縮でエンコードしてからgzipするなんて変則的なことをしてまでGIFを使う理由としては既存のブラウザとの互換性が大きいと思うのですが、ちょっと現実の実装に無頓着すぎるのではないかと思いました。
同じことを考えた人はすでにいたようです。ただし、
という2点を押さえておくとわずかですがサイズを小さくできます。
ここにも無圧縮GIFの作り方が書かれています。ここで説明されている方式では最初にクリア符号を出力している点がわずかに無駄なだけで、あとはほぼ最小の無圧縮GIFを出力できます。
上記2つのリンクはここで見つけました。
上記Graphics File Formats FAQのアルゴリズムを実装したlibungifを配布しているサイトです。
Free UNIXで、giflibの代わりとしてよく使われているようです。
BMPを無圧縮GIFに変換するコンバータを公開しています。ソースは公開されていないし使用許諾契約でデコンパイル・リバースエンジニアリング・逆アセンブル等も禁止されているので、何かの間違いでLZWを使っていたらとか思うと怖くて使えたものではありません。
おまけに自分のプログラムのバグをデコーダのせいにしています。いやバグとは限りませんがソース公開されていませんし。-Bオプションをつけなくてもcel2gifより大きなGIFを生成するくせに、-Bオプションをつけても私の使っている2種類の画像ローダのどちらでもまともに表示できないGIFを生成してくださるのです。いやー素晴らしい。
使用許諾契約で批判や好意的でない批評を禁止するとかいうマイクロソフトよりすごいことをしているので誰も教えてくれないというか教えようにも教えられないのでしょうね。自ら選んだ道ですからまったく問題ありませんが。
(2000/04/03追記)それでもレポートを送った勇気ある人のおかげで修正されたようです。
(2000/05/22追記)本人からメーられた。長いので読んでないけど。とりあえず何か言いたいことがあるならWebページで全世界にでも公開すればいいと思う。
BMPをRLE圧縮のGIFに変換するコンバータを公開しています。同じくRLE圧縮を使っていたgd 1.3は公開停止になってPNGを使う版に差し替えられてしまった点がやや気に掛かります。
とある無圧縮GIFライブラリの解説で、GIFはTrue Colorを扱えるという事実を知ったのでリンクを追加。
特許の期限切れに伴い先頭に注意書きを追加。agree-pngバナーを削除。
Libungifのリンクを更新。Googleで検索しても出てくるのは繋がらなくなった古いサイトへのリンクばかりだが…。
リンクを更新。
cel2gifを更新。オフセット付きのcelを正しく変換できていなかった。
gzipで圧縮すればいいと書いてあるページが紹介されていた。しまった、こんなことならもっと早く書いておけばよかった。パクりだと思われそうだがgzip関連の項目を追加。
元画像のピクセル数が(8ビット画像の場合で)254*x-1ピクセルだったとき、出力される画像ブロックの末尾に(無駄な)クリア符号がついていた。さらに254*x-2ピクセルだったときは終端符号の後ろにクリア符号が出力されてゴミになってしまっていた(ローダの表示には影響ないようだが)。
いずれも修正。これで特定サイズの画像はさらに1〜2バイト小さくなるはず。
リンクを追加。
Graphics File Formats FAQの解説やlibungifのソースを見ていて、クリア符号の出力間隔は2度目以降は2^N-2符号ごとでいいことに気付く。ので修正。
@niftyの会議室であまりにも素晴らしいサイトを教えてもらったので思わずリンクに追加。