2次元画像処理 BMP
2次元画像処理の項目へ戻る
概要
BMP形式のファイルは比較的読み込み易い形式になってます。最初の54byteがHeader情報になっていて、この中に画像の高さpixelと横幅pixelの情報がありますので、これさえ抜き出せれば、あとはRGBの情報を読み込めば、表示できます。OS/2っていうん?の場合はBIDとか、圧縮方式を適用したRLEという拡張子のものもBMPの仲間っていうか、なんていうか同じものです。
とは言いつつも、それだけでは特殊な形式のBitmapファイルもありますので読み込みエラーに遭遇する可能性がありますし、書き出す時も、もう少し情報をしっかりと最初の決まり事や各バイトの決まり事に従って付与しておかないと他のアプリでも画像を開くことができないというエラーになるようなアプリになってしまう可能性もあります。
ファイル構成
- Bitmapファイルヘッダー
- 00~01 2Byte:'B','M'にあたるアスキーコード0x42→B 0x4d→M 固定です。
- 02~05 4Byte:ファイルサイズ[Byte]を格納します。符号なし整数として記載。30~33の領域で指定している値が0の場合0でも、正しい値でもなんでもOK。
- 06~07 2byte:常に0の予約領域1
- 08~09 2byte:常に0の予約領域2
- 10~13 4Byte:ファイル先頭から画像データまでのバイト数。24bitColorRGBファイルならパレット情報を埋め込む必要もなく54ビットで事足りるヘッダになるので、0x36です。符号なし整数として記載。
※符号なし整数部はリトルエンディアン方式なので 10~13の情報は54ビットを表すためには0x00,0x00,0x00,0x36を逆順にならべて0x36,0x00,0x00,0x00になります。
- Bitmap情報ヘッダーWindows系 OS/2系の短いモノやV4 V5ヘッダーと呼ばれるモノも存在します。全部対応しないとビューワとしては不完全となります。
- 14~17 4Byte:情報ヘッダのバイト数。24bitColorRGBファイルなら40byteなので、0x28です。0x28,0x00,0x00,0x00ですね。
- 18~21 4Byte:画像の横幅pixel
- 22~25 4Byte:画像の高さpixel
- 26~27 2Byte:プレーン数。つまり画像の区画数です。1枚分、1区画しか使えないので、1で固定です。0x01です。0x01,0x00ですね。
- 28~29 2Byte:カラービット数。24bitColorRGBなら24です。0x18です。0x18,0x00ですね。HTMLの色を#000000~#FFFFFFであらわすあれと同じ表現方法です。ほかにもモノクロの1bitや16色4bit、256色8bit、65535色16bit法(BITFIELDS利用によるRGBをそれぞれ5bitで表現する方法、RGB555やRGB565、RGB655、RGB556)があります。
- 30~33 4Byte:圧縮方式。0で圧縮無しのよくあるbmpになります。したがって、0x00,0x00,0x00,0x00となるのが通常だと思います。
- 他にも1,2,3,4,5の3種類の方式が選択できるようになっています。それぞれの圧縮方式については後述したいと思います。
- ・1:RLE8という方式。正式にはラン レングス エンコード(Run Length Encoded 8bits Per Pixel)です。
- ・2:RLE4という方式。正式にはラン レングス エンコード(Run Length Encoded 4bits Per Pixel)です。
- ・3:Bitfieldsというマスク(RGBデータに影響を与えるデータ)を与える圧縮無し方式の特殊なモノという感じです。
- ・4:JPEG圧縮方式。bmpファイルの中身がJPEGになるという特殊用途です。
- ・5:PNG圧縮方式。bmpファイルの中身がPNGになるという特殊用途です。
- いずれもあまりみかけませんが、規格にはあるので、対応しないとダメなのかもしれません。対応しませんと宣言して画像処理アプリを公開するということもアリでしょうか?使う人にわかってもらうことが大事ですよね。全部の圧縮方式に対応していないと捕まるとかそういうことはないです。さも完璧な画像処理アプリを装って、上記にきちんと対応していないプログラムを公開すると叩かれるかもしれません。気を付けてください。BMPも意外と複雑な仕組みのものがあったりするということです。せめて、このフラグを読み取って圧縮方式がxxxになっているファイルです。このアプリでは開けません。というようなメッセージが出るような仕組みを持たせておくとアプリ利用者は合点がいくのではないでしょうか?
- 34~37 4Byte:画像データ部分の情報容量[バイト]。適当な値が設定されていることもあります。適当というか、間違えた計算に基づくファイル容量の値だったりということです。0が設定されていることも多いです。
- 38~41 4Byte:水平(横方向)解像度[dot/m]。96[dpi](96[dot/inch]Windowsで扱う文書やスクリーン画面を印刷するときによく使われる値)であれば、3780[dot/m]となります。おおよそ39.37インチが1mですから、96dpiというのは1インチに96dotということですから、39.37倍すると1mあたりのdot数に変換できます。3779.52..ですが、おおよそ3780です。これを16進数で表現するなら、0x0ec4です。c4,0e,00,00です。
- 42~45 4Byte:垂直(縦方向)解像度[dot/m]。上記の説明と同じような感じのものです。
- 46~49 4Byte:パレット数:色番号1から順番に格納される色情報を画像データとヘッダ情報の間にいれることができます。その色数。正しい情報が入っていない場合もあるみたいです。その場合は28~29で指定される色数情報が優先されて読み込むようになっています。
- 50~53 4byte:重要色数。これが正確に指定されていることも少ない情報です。
- BitFieldマスク値
30~33 4Byte:圧縮方式が3のBitFieldの場合に使われるヘッダ情報です。それ以外の場合、このヘッダー部分は省略される部分です。省略されない場合は情報量は12byteになります。
- Bitmapパレット
28~29の部分で、色表現ビット数が8より小さい場合に利用する部分で、それ以外の場合、このヘッダー部分は省略される部分です。
46~49のインデックス数の指定を信じてよいと思いますが、厳密には全ファイルサイズ n[byte] - ( ヘッダー情報サイズ[byte] + ビットフィールド12[byte]) の情報量の値が指定のパレットサイズと一致していたら、指定の値を採用し、一致していなかったら、論理演算で 1 << (カラービット数(28~29で指定される値))の大きさと考えてよいでしょう。インデックス番号は0番から始まります。最大値は(大きさ - 1)ですね。つまり、8bit/pxなら、論理演算1<<8で求められるパレットの大きさ256で0~255番までのパレットが存在し、WindowsフォーマットならRGBQUADという方式のパレットになり1つのパレットに2バイトづつ、B青,G緑,R赤,予約領域、の値が格納されてビットストリームが連続して記述されています。番号は振られていませんので、順番にパレットの大きさ分だけ読み込んでいきます。8bit/pxの場合が最大で256x4の1024バイトが使われます。1bit/pxの場合は2x4で8バイトっすね。4bit/pxの場合は16x4で64バイトになります。この情報以降はbitmapデータになります。境目はよくわからないのがバイナリー形式です。1つが狂えば、姿カタチは消えてしまうのですから、なんとなく恐ろしいことだと感じてしまいます。
- Bitmapデータ
ここからがRGBデータの並びになります。画像の左下から水平に右へと1ピクセルの行にあたるモノをピクセルごとにデータとして格納していて、1行のデータがおわると画像の上側の情報を描くように順次データを格納しています。データ自体に行の終端のデータはないので、ヘッダー情報にある横幅の大きさ分を読み込んだら次の上の行のデータであるとプログラム側が認識して描画していきます。ここで少し変わった決まりがあって4の倍数バイトが1行になるようにデータが調整されていないといけないことになっています。1行が4の倍数バイトにならない場合は0x00のようなダミーデータを埋めることになっています。書き込む場合はダミーデータを入れ忘れないようにすること、読み込むときは4の倍数バイトが1行であることを認識してダミーデータを無視するような処理をしなければなりません。RGBの値は24bitつまり3バイトで表現され、例えば赤のピクセルのRGB値は0xFF,0x00,0x00、リトルエンディアンのように、BGRの順でデータが格納されます。ですから赤は0x00,0x00,0xFFとなります。
上記のようなビットマップ仕様からすると横幅5ピクセルのビットマップなら、1行のデータを16バイトづつ表示するようなバイナリーエディタでその形を想像することができるような表示がなされます。下から上にデータがつまっているため、像は逆さになりますね。ちなみに縦幅をヘッダー部で負の値として登録すると上から下に像の情報が格納されているとしてデータのつまりかたと実際の描画情報の縦の向きが同じになります。横方向についても同じ法則を持っていますので、左からではなく右から左に描画がなされます。
BMPファイル 読み込み・書き込みプログラム
サンプルプログラム創作前の愚痴'17-12-29~'17-01-xx継続中
ちょちょっとすればできると思ったんですけど、BMPも実際、プログラムサンプルを作るとなると意外と大変っすね。かれこれ1週間近くしょうもないプログラム組んでる気がする。しょうもないのに時間かかる。Win32/64 おそるべし。やっと24bitと32bitビットマップを24Bit/px32Bit/pxのカラー表示モードのPCでひらけるようになったところです。ちかれた。そのうちサンプルプログラムが出来上がるでしょう。このネットのあちらこちらにあるサンプルなので、それを使う方が早いかもね。ようするにオープンソースでBMPとJPEGとPNGとGIFとTIFFが開けるやつ探せばいいんでしょ。GIMPとかのソースを解読すればええんでしょうか?あとはLibere Officeだっけ、Office.orgの後釜のやつ。ああいうのを解読すれば、読み込む方法と書き込む方法がわかるかもしれない。まぁ、ああいうプロジェクトのはソースの可読性がかなり難しい構造になってるから、簡単には理解できないでしょうけど。何が重要なところかがわかりづらいと思うし、説明もないっすからね。アレを理解できる人は、こういうページには来ないよね。
まぁ気長に待っていてください。私なりの解説記事を頑張って作ります。ランレングス圧縮BMP、通称RLEと8bitパレット16bitパレットのBMPの読み書きのプログラムができていないっす。LoadImageっていう関数で済むことをちまちま理解しようとすると大変です。JPEGの解説で右往左往すると思ってましたが、ここで1st右往左往っす。
こんな感じですね。自分のPCのデスクトップの状態を惜しげもなく公開です。Dynapad N72は画面が1920x1080というFullHD表示ですが、分解能が細かすぎるため拡大機能が使われています。自分は100%のままでもいいかなとはおもうのですが、125%拡大で使っています。でも、プログラムの方は、なんか違う倍率の表示になってますね。なんじゃこれ?なんか調べなきゃいけないこと増えてるなorz。Live2ch、FL Studio12、ClipStudioPaintEx、MicrosoftOffice Excel2010/Word2010、Chrome、Adobe Creative Cloud/Acrobat DCを追加でインストールしてますね。
Live2chは基本読むだけですね。書き込むと議論にキリがないということを悟ったのは10年前ごろです。教えても教えても次から次へと質問してくるし、話しても話しても理解してくれない人はいるし、反論する人はいる。反論がないときは、多くの人に読まれてないだけですね。つまり、わかりあえることはほとんどないといって過言でもない。世界平和に挑戦するようなものだ。2chのような場所での議論が好きな人はたくさんいるようです。そういう人に任せることにしました。やっぱねネットのこれからの時代は基本、一方通行これだね。リアル世界で双方向しましょ。
FLはDAWっすけど、作曲は最近してません。バンドのギターが実際はどんな演奏をしているのか、譜面から入れてみて確認したりという感じです。Clipで絵をかくのは最近のブームです。Officeはやっぱプログラムするのには、あった方が連携するアプリの動作の確認が楽です。あとは、最初から入ってるアプリが優秀なのでソコソコ楽です。このパソコンのおかげで気楽にPCで作業できるのです。いいね♪
2017-01-11追記:
いやはや軽い気持ちで書き始めたBMP記事でしたが、奥が深いっす。BITFIELDSの部分までできました。カラーパレットヘッダの読み込みもWindows形式のみ対応です。結構疲れた、時間の無駄のような気がしつつも、一回やり始めたし、ちょこちょこ頑張って終わらせようと思います。こりゃJPEG記事はやめといた方がいいな。と思いました。ん~あとはOS/2対応 WindowsのV4,V5ヘッダ対応とカラーパレット方式の画像データ読み込みおよびRLE-4、RLE-8の画像データ読み込み処理か…あ~あとイメージの高さと横幅情報が負のときの反転処理もだな。メンドイ。で、今日になって、末恐ろしい真実をしってしまったのです。このBMP形式にはマイクロソフト独自のシステム的解釈も存在していて、なんとなく見たことはあったんですがシステムカラーとかっていう画面描画に関する扱いがあるみたいなんです。BMPとプログラムとWindows。複雑。BMPも相当なもんですね。決まりを考えた人たちってすごいなぁ。どんだけの時間を費やして決めたんだろうか…。システムカラーについて知る必要があるのかは、BMPとのこれからの関係性と重要性をよく考えてから記事にしたいと思います。あまり必要にならないことは書かないほうがいいよね。
2017-01-14追記:
あとは、OS/2対応 WindowsのV4,V5,反転…あとちょい。
2017-01-19追記:
できた。と思ったけど、これから、バグだし作業です。一回もテストせずにプログラムを作ってしまった。愚かよのう。うまく動いたら、すぐに記事を更新できるだろうし、動かなければ、泣いて寝る日々だな。これだけ壮大なプログラムが動作するとはとても思えない。
2017-02-27追記:
RLE4の読み込みさえできていない。画像表示が全然、元の画像と異なる!やべぇ。まじでやべぇ。意味わからん。元に戻らない。おかしい。おちつけオレ。なんつうか、ほど遠い、仕様どおり展開してるつもりだけど、うまくいっていない。ややこし過ぎる。JPEGなんて夢のまた夢。orz。無能過ぎるオレ。つうか、あんまりやる気が沸いていないのが正直なところ。こういう時は直すより、いちからやり直した方が早いとも聞く。どうしたもんやろ…
2次元画像処理の項目へ戻る