今日の成果、JPEGの生成方法を工夫してみた

KLab×はてな エンジニア応援ブログコンテスト


追記:2010/08/17 -----------
HeatHashベータ版
http://www.ohoooo.mydns.jp/
紹介エントリ
http://d.hatena.ne.jp/oho_sugu/20100817/1282042542

                                                      • -

今、プライベートな時間で進めている俺々プロジェクト、Project HeatHash(そのうちちゃんとどういう物を作りたいか書くつもり)。

今日は、その中でマップ画像を生成する部分の試験的なコードを書いていた。

HeatHashでは、GoogleMapAPIを使ってベースマップを表示し、
その上に、ある情報をヒートマップにして表示したいと思っている。
しかし、自前でタイル画像を作って表示するのはサーバー負荷が大きい。
なんとか軽くタイル画像を作る方法はないかと考えたのが、JPEGをバイト配列のままで生成する方法。


まず、表示したい画像はせいぜい16色程度の色数しか使わない。格子状に区切った各マスに、色が塗ってあるだけの画像だ。
でも、サーバーサイドでいちいちImageを作って描画してソケットに送出ってやるのは、コストがかかる。


色々と考えた末に、画像の生成=JPEGデータの生成をバイト配列の処理だけにしてしまった。
まず、ヒートマップに使いたい16色の8×8ピクセルのブロックが縦に並んだ画像ファイルをBMP(無圧縮だから)で作成する。
それをGIMPで、品質100%でいくつかのパラメータを都合良くセットして保存した。
ここからバイナリエディタの出番。
JPEGフォーマットの解説を横目に、画像データをMCU単位で切り出し、バイト配列を作成した。
それから、JPEGのヘッダ・・・というより、画像データの前までのバイト列も同様に切り出す。


では、必要なJPEG画像を作成するプログラムはどういう処理を行うか。
書き出す先のStream(ファイルでもソケットでも)に、どかっとヘッダ配列をそのまま出力。
さらに、最初のMCU分だけはそのまま、それ以降はRSTセグメントをくっつけながら、
先ほどのMCU単位で切り出したバイト配列を元データ(0〜15)に従って出力していく。
最後にEOIセグメントを出力したらクローズして終わり。
ハフマン符号のテーブルも、量子化テーブルも変えない。ほとんど計算なし。データを出力するだけで、欲しいJPEG画像ができあがった。


ここまで、Javaで作っていたので、ちょこちょこっとServletにして、ブラウザから画像が表示されることを確認して今日の作業は終わり。
久しぶりに自分らしい仕組みを作ることができたように思う。