| ディスク上のBMPファイルを表示する |
| ファイルヘッダ BITMAPFILEHEADER構造体 |
| 情報ヘッダ BITMAPINFOHEADER構造体 |
| カラーデータ 複数個のRGBQUAD構造体 |
| ピクセルデータ |
m_pDib = (BYTE*)new char[file.GetLength()]; file.Read(m_pDib, file.GetLength());データを読み込んだら、まずBITMAPFILEHEADER構造体へのポインタを取得し、 読み込んだファイルの形式が正しいかチェックする。 DIB形式のファイルでは、BITMAPFILEHEADER構造体のbfTypeメンバが"BM"という文字列になっている。
m_pBMFH = (BITMAPFILEHEADER*)m_pDib;
if( m_pBMFH->bfType != *((WORD*)"BM")) {
…… // ファイル形式が正しくない場合の処理
}
その後、各構造体へのポインタを設定する。
m_pBMIH = (BITMAPINFOHEADER*)(m_pDib + sizeof(BITMAPFILEHEADER)); m_pBMI = (BITMAPINFO*)m_pBMIH; m_pData = m_pDib + m_pBMFH->bfOffBits;BITMAPINFO構造体は、BITMAPINFOHEADER構造体とRGBQUAD構造体をまとめたものである。 また、m_pDataはピクセルデータ領域へのポインタである。BITMAPFILEHEADER構造体のbfOffBitsメンバは、 DIB形式ファイルの先頭からピクセルデータ領域の先頭位置までのオフセットを示している。
::StretchDIBits(pDC->GetSafeHdc(), x, y, m_pBMIH->biWidth, m_pBMIH->biHeight, // 転送先 0, 0, m_pBMIH->biWidth, m_pBMIH->biHeight, // 転送元 m_pData, m_pBMI, DIB_RGB_COLORS, SRCCOPY);
typedef struct tagBITMAPFILEHEADER {
WORD bfType; // 常に"BM"
DWORD bfSize; // ファイルサイズ
WORD bfReserved1; // 0に設定
WORD bfReserved2; // 0に設定
DWORD bfOffBits; // DIB形式ファイルの先頭からピクセルデータ領域の先頭までのオフセット
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize; // この構造体のサイズ
DWORD biWidth; // 幅(ピクセル単位)
DWORD biHeight; // 高さ(ピクセル単位)
WORD biPlanes; // 常に1
WORD biBitCount; // 1ピクセルあたりのカラービットの数
DWORD biCompression; // BI_RGB, BI_RLE8, BI_RLE4のいずれか
DWORD biSizeImage; // イメージの全バイト数
DWORD biXPelsPerMeter; // 0または水平解像度
DWORD biYPelsPerMeter; // 0または垂直解像度
DWORD biClrUsed; // 通常は0、biBitCount以下のカラー数に設定可能
DWORD biClrImportant; // 通常は0
} BITMAPINFOHEADER;
typedef struct tagRGBQUAD {
BYTE rgbBlue; // 青の輝度(0〜255)
BYTE rgbGreen; // 緑の輝度(0〜255)
BYTE rgbRed; // 赤の輝度(0〜255)
BYTE rgbReserved; // 予約値。0にする
} RGBQUAD;
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;
ここではDIB形式ファイルの読み込みと表示を行うために作成したクラスCUKDibの実装を以下に記述する。 実用するには、ファイル例外処理などのエラー処理を追加しておきたい。
// ヘッダファイルの記述 --------------------
class CUKDib : public CObject
{
public:
CUKDib();
virtual ~CUKDib();
BOOL Open(const char* pzFileName = NULL);
void Close();
void Draw(CDC* pDC, int x = 0, int y = 0);
private:
BYTE* m_pDib;
BITMAPFILEHEADER* m_pBMFH;
BITMAPINFOHEADER* m_pBMIH;
BITMAPINFO* m_pBMI;
BYTE* m_pData;
};
// ソースファイルの記述 --------------------
#include "stdafx.h"
#include "UKDib.h"
/////////////////////////////////////////////////////////////////////////////
// コンストラクタ
/////////////////////////////////////////////////////////////////////////////
CUKDib::CUKDib()
{
m_pDib = NULL;
}
/////////////////////////////////////////////////////////////////////////////
// デストラクタ
/////////////////////////////////////////////////////////////////////////////
CUKDib::~CUKDib()
{
Close();
}
/////////////////////////////////////////////////////////////////////////////
// Close関数
// 終了処理
//
// 引数:なし
// 戻り値:なし
// ※ メモリにデータが残っている場合は解放する
/////////////////////////////////////////////////////////////////////////////
void CUKDib::Close()
{
if( m_pDib != NULL ) {
delete m_pDib;
m_pDib = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////
// Open関数
// DIB形式のビットマップファイルを開き、データを読み込む
//
// 引数:
// pzFileName: ビットマップファイル名(デフォルトはNULL)
// 戻り値:
// データの読み込みに成功した場合はTRUE、失敗時はFALSE
/////////////////////////////////////////////////////////////////////////////
BOOL CUKDib::Open(const char* pzFileName /* =NULL */)
{
CFile file;
CString sFileName;
// あらかじめメモリを空にしておく
Close();
// ファイル名の決定
// 引数に指定されていればそれを使用する。指定されていない場合は
// コモンファイルダイアログを開く
if( pzFileName == NULL ) {
CFileDialog dlg(TRUE, "bmp", NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
"ビットマップファイル(*.bmp)|*.bmp|全てのファイル|*.*|", NULL);
if( dlg.DoModal() == IDOK ) {
sFileName = dlg.GetPathName();
}
else {
Close();
return FALSE;
}
}
else
sFileName = pzFileName;
// ファイルのオープン
if( file.Open(sFileName, CFile::modeRead | CFile::typeBinary) == FALSE ) {
Close();
return FALSE;
}
// メモリを確保し、データを読み込む
m_pDib = (BYTE*)new char[file.GetLength()];
file.Read(m_pDib, file.GetLength());
// BITMAPINFOHEADER構造体の取得
m_pBMFH = (BITMAPFILEHEADER*)m_pDib;
// 読み込んだファイルの形式をチェック
if( m_pBMFH->bfType != *((WORD*)"BM")) {
AfxMessageBox("読み込んだファイルの形式が正しくありません。");
file.Close();
Close();
return FALSE;
}
// その他の構造体やデータ領域へのポインタの設定
m_pBMIH = (BITMAPINFOHEADER*)(m_pDib + sizeof(BITMAPFILEHEADER));
m_pBMI = (BITMAPINFO*)m_pBMIH;
m_pData = m_pDib + m_pBMFH->bfOffBits;
// ファイルのクローズと終了(正常終了)
file.Close();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// Draw関数
// 読み込んだビットマップファイルを表示する
//
// 引数:
// pDC: デバイスコンテキスト
// x: ビットマップの左上隅のx座標
// y: ビットマップの左上隅のy座標
// 戻り値:
// なし
/////////////////////////////////////////////////////////////////////////////
void CUKDib::Draw(CDC* pDC, int x, int y)
{
::StretchDIBits(pDC->GetSafeHdc(),
x, y, m_pBMIH->biWidth, m_pBMIH->biHeight, // 転送先
0, 0, m_pBMIH->biWidth, m_pBMIH->biHeight, // 転送元
m_pData, m_pBMI, DIB_RGB_COLORS, SRCCOPY);
}