イマサラですが、WBMPのフォーマットって? Javaで読めるの?

まーやです。

イマサラなお話しですが、先日、Javaで「WBMP(ワイヤレス・ビットマップ)」なる画像の読み込みを行う機会がありました。

え?WBMPって何ですか?って感じですよね。真っ黒・真っ白の2階調の画像です。携帯電話が白黒の時代に、携帯向けサイトで画像を表示するためにできた規格です。そんな昔の規格ですが、Javaでちゃんと読み込めます。

そこに至るまで諸々と調べたので、ついでにブログに書いておきます。

WBMPのフォーマット

参考サイト
http://ja.wikipedia.org/wiki/Wireless_Application_Protocol_Bitmap_Format
http://www.marguerite.jp/Nihongo/Labo/Image/WBMP.html

ヘッダー

項目 サイズ データ
タイプ 1 byte 00 固定
ヘッダ 1 byte 00 固定
画像の幅 可変 2進数にして。下から7ビットづつ分割する。
各7ビット単位の先頭1ビットに識別子を付けて、8ビットにする。
画像の高さ 可変 識別子は、この7ビットで終わりなら “0″、続きがあれば “1″

幅と高さの可変はなんのこっちゃって感じです。具体例で説明しましょう。

「127」の場合

値は2進数で “1111111″ になる。7ビットで終わり、次のバイトには食い込まない。
続きはないので識別子は “0″ になる。
識別子と値を結合すると “01111111″ になる。

127 × 127 WBMP画像ファイルのヘッダー部分 (2進数表記)
00000000 00000000 01111111 01111111 これ以降が画像データ

「128」の場合

値は2進数で “10000000″ になる。7ビットを超えると、7ビット毎に分割する。分割は下から。
下から “0000000″ が1ブロック、その上 “1″ が1ブロック。
上の “1″ を7ビットにすると “0000001″、続きがあるので識別子を付けると “10000001″ になる。
下の “0000000″ は続きはないので識別子を付けると “000000000″ になる。

128 × 128 WBMP画像ファイルのヘッダー部分 (2進数表記)
00000000 00000000 10000001 0000000 10000001 0000000 これ以降が画像データ

可変の範囲

幅と高さの可変とはそういうことです。
WBMPでパノラマなんて現実的にはないだろうから、可変と言っても1バイトか2バイトと思っていいでしょう。

WBMPでの値 (2進数表記) サイズ
1 〜 127 00000001 〜 01111111 1 byte
128 〜 16383 10000001 0000000 〜 11111111 01111111 2 byte
16384 〜 2097151 10000001 0000000 0000000
〜 11111111 11111111 01111111
3 byte

画像データ

黒 “0″ か、白 “1″ か、です。

ヘッダーの画像の幅のピクセル分だけ白黒のビットを並べます。サイズが8で割り切れなければ、最後のバイトは境界まで0を埋めます。それをヘッダーの画像の高さだけ繰り返しています。

「127 x 127」の場合

サイズ
ヘッダー 4 byte
画像データ 127 / 8 (切り上げ) byte × 127
2,032 byte
2,036 byte

「128 x 128」の場合

サイズ
ヘッダー 6 byte
画像データ 128 / 8 (切り上げ) byte × 128
2,048 byte
2,054 byte

例外

世の中には、どうしてだか例外というものが発生します。黒と白をビットで表す規格、のはずが、バイトで表しているWBMPが存在します。

黒 “00000000″、白 “00000001″、となっているようです。

これでいくと、「128 x 128」の場合は。

サイズ
ヘッダー 6 byte
画像データ 128 byte × 128
16,384 byte
16,390 byte

ビットなら2,054バイトで済むものを…。WBMPのコンパクトさが台無し…。

Javaで読み込む

さて、上記でビットWBMPとバイトWBMPがあると説明しました。結論から言えば、このどちらも読めます。

なんらかの画像を読み込む

とにかく画像らしいので読み込んでみようという場合、ImageIO.getImageReadersで適切なImageReaderを取得して使用します。

実際にこの方法で確認してみたところ、ImageIOからWBMPImageReaderを取得できるのはバイトWBMPの方だけでした。ビットWBMPでは適切なImageReaderを取得できないため、BufferedImageを作れません。

上記で読めなかった場合には、ビットWBMPかもしれないので、今度はWBMPとしてリトライしてみます。

WBMPとして読み込む前に、ヘッダー部分をチェックしてます。ヘッダーが正しいか、サイズは適切そうか、それを判断して下記を行なっています。でも、長くなるし、WBMPだなんてイマサラ解析する人はないと思うので、そこのところは割愛します。

WBMPを読み込む

WBMPと解っているなら、WBMPImageReaderを作って読めばいいです。

終わってみればこれだけのことです。何から何までイマサラですが、ImageIOは何でも読める子ですね。

まーや
About まーや (34 Articles)
画像変換サービスPictureFitterを担当しています。 ネコ大好きのアンドロイダーです。
Contact: Twitter

Leave a comment

Your email address will not be published.

*



Top