BMPファイルからDIBを読み込む

Windows の標準グラフィック形式であるBMPファイルは、DIB の前にヘッダを付けた構造になっています。具体的には、BITMAPINFOとカラーテーブル、ビットマップバッファの前にBITMAPFILEHEADERが付加されるようです。ただし、この他のヘッダが付くこともある上に、BITMAPINFO などでは一部が省略される可能性もあるようなので、ビットマップのポインタは単純に特定バイトを足すのではなく、オフセット(BITMAPFILEHEADER のbiOffBits)を調べる必要があります。

なお、ファイルの先頭(すなわちBITMAPFILEHEADER の先頭)には、ビットマップファイルである事を表すBMの2バイトがあるので、まずこれを確認した方が良いでしょう。

ビットマップの読み込み

基本的には、ファイルをバッファに読み込んだらBITMAPINFO とビットマップバッファへのポインタを設定して終わりです。先頭からsizeof(BITMAPFILEHEADER) だけ後ろにBITMAPINFOの先頭が来て、ビットマップの先頭はBITMAPFILEHEADERiOffBitsにファイルの先頭からビットマップまでのオフセットがはいっています。
つまり、

  fh=CreateFile(szFn,GENERIC_READ,0,NULL,OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,NULL); // ファイルオープン

  lpBuf=GlobalAlloc(GPTR,GetFileSize(fh,NULL)); // バッファ確保

  ReadFile(fh,lpBuf,GetFileSize(fh,NULL),&dummy,NULL);

  lpInfo=(LPBITMAPINFO)(lpBuf+sizeof(BITMAPFILEHEADER));

  offset=*(LPDWORD)(lpBuf+10); // ビットマップまでのオフセット
  lpBMP=lpBuf+offset; // ビットマップバッファのポインタ

  CloseHandle(fh);

とすれば、BITMAPINFO とビットマップバッファのポインタ(つまりDIBそのもの)を作成できるわけです。今回のプログラムでは、16・24ビットの読み込みを想定しましたが、8ビットDIBについても同様の方法で読み込めるでしょう。カラーテーブルがあるので多少異なる部分もありますが、ビットマップまでのオフセットに注意すればそれほど問題はありません。

プログラム例

今回のプログラムは、ビットマップファイルを選んで表示するものです。起動したら、ボタンをクリックしてファイルを選んでみてください。16ビット/フルカラーDIBを読み込む事が出来ます。
ただし、今回のプログラムではWindowsのDIBをそのまま記録していることを想定していますので、場合によっては問題があるかもしれません。特に、BITMAPINFO の一部が省略されている場合などはやや不安ですね。できれば、BITMAPINFOの大きさ(biSize)を調べて、設定されているものだけを指定した方が良いのかもしれません。

プログラムソース表示

Windowsプログラミング研究室>プログラミング資料庫