Visual C++では、画像描画等を行う場合は対象とする画像をリソースに取り込んでおき、
それを読み込むのが標準です。
しかし、アプリケーションを実際に作るときは、
”ディスク上の画像ファイルを直接してして表示"
する必要がある場合が多い。そのような時、Visual Basicのような簡単な処理方法はありません。
そこで、アプリケーション開発者が工夫する必要があります。API関数によるビットマップ画像
を表示する方法があります。
【DIB形式の構造】
従来、WindowsはビットマップデータをWin32API対応のデバイス独立ビットマップ(DIB形式)
を使用して表示されます。
ディスク上のビットマップファイルは、この形式で格納されています。その格納形式は
以下のようになります。
ヘッダが2つ、必要ならカラーデータ、画像の実データ
[DIB形式データ格納形式]
----------------------------
| ファイルヘッダ | ファイルのタイプ、ファイルの全サイズ
| BITMAPFILEHEADER構造体 | ビットマップデータの先頭までのオフセット
----------------------------
| 情報ヘッダ | 画像の幅と高さ
| BITMAPINFOHHEADER構造体 | 色ビット数など
----------------------------
| カラーデータ | カラーパレットデータ
| RGBQUAD構造体 |
----------------------------
| ピクセルデータ | 画像データ(1ドットごとの色指定)
----------------------------
【画像ファイルの読み込み】
画像ファイルは特別の内部構造をしているので、これを読み込む場合は配慮が必要です。
標準的な読み込み手順を示します。
(1)ファイルの選択とオープン
ファイルダイアログを使ってファイルを選択し、オープンする。
(2)2つのヘッダ部分を読み込む
画像データの先頭にある2つのヘッダ情報を読み込みます。
(3)色情報を取得する
読み込んだBITMAPINFOHEADER構造体にbiBitCountメンバ変数があります。
これは1ピクセルあたりの色表現ビット数を示しています。
これには、1,4,8,16,24,32の値を取ります。
| biBitCount |
| 値 | 表示色 |
| 4ビット | 16色 |
| 8ビット | 256色 |
| 16ビット | 65536色(HighColor) |
| 24ビット | 1677216色(TrueColor) |
この色のビット数が16ビット以上のときは、16ビット値で指定した色を確実に
再現できます。ところが16ビット未満の場合は、「限られた色指定」が実際にどの
ようになるかという問題が出てきます。これがよく言われる「65536色中256色表示可能」
といった記述です。そこで256の連続番号に対して、実際にどの色を割り当てるかという
指定をする必要があります。これを実施するのがカラーパレットという機能です。
この場合は、0〜256の番号を取るパレット番号となります。その番号に対して割り当て
られている情報が画像ファイルに書き込まれています。
従って、
「色ビット数が16未満ならパレット情報(色調合情報であるRGBQUAD構造体)が
存在し、それを読み込む必要があります。」
(4)ファイル内の実データ位置を合わせる
画像ファイルの先頭ヘッダ部をスキップして実データ部分を読み込むために、
ファイルポインタを実データ部分の先頭に位置を合わせます。そして、必要な
メモリサイズを確保し、そこに画像イメージを読み込みます。
【画像の表示】
読み込んだ画像データは単なる数値データでしかありません。これを元の画像に
展開するためには、メモリデバイスコンテキストというメモリ上の作業領域を使い
ます。ここで作成したデータを画像表示のためのデバイスコンテキストにBitBlt関数
で送ることで、画面上に画像が表示されます。これはリソースファイルになっている
画像を表示するのと本質的には同じ処理です。それらの違いは以下の通りです。
リソース管理の場合
・はじめにLoadBitmapメンバ関数を使ってビットマップリソースを読み込む
画像ファイル読み込みの場合
・読み込んだ画像イメージからビットマップを作る
「画像表示の手順」
(1)現在のウィンドウのデバイスコンテキストを取得
まず、最終的な出力となるデバイスコンテキストを取得します。
例:
HDC hDC; //デバイスコンテキストのハンドル
hDC = ::GetDC(m_hWnd);
(2)描画を準備する
ウィンドウのイベント処理を開始するための準備をします。
BeginPaint関数で準備をし画像表示後は、EndPaint関数で後処理をします。
(3)メモリデバイスコンテキストを作成
最終的に出力先となるデバイスコンテキストと互換性のある
メモリデバイスコンテキストを作成。
(4)ビットマップ形式の変換
読み込んだDIB形式データをデバイス依存のDDB形式に変換してビットマップを
作成し、そのオブジェクトを選択します。
(5)画面に表示する
用済みになったオブジェクトを解放します。
【各種構造体の解説】
画像処理で使用する構造体の構成
[BITMAPFILEHEADER構造体]
ビットマップファイルの全体情報を保持する
typedef struct tagBITMAPFILEHEADER{
WORD bfType; //ファイルタイプ
DWORD bfSize; //ファイルサイズ
WORD bfReserved1; //0予約
WORD bfReserved2; //0予約
DWORD bfOffBits; //先頭からのビットマップデータまでの距離
} BITMAPFILEHEADER;
[BITMAPINFOHEADER構造体]
画像構成に関する情報を保持する
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; //この構造体のサイズ
LONG biWidth; //画像幅
LONG biHeight; //画像の高さ
WORD biPlanes; //プレーン数(常に1)
DWORD biBitCount; //1ピクセルあたりのカラービット数
DWORD biCompression; //圧縮タイプ
DWORD biSizeImage; //イメージのバイト数
DWORD biXPelsPerMeter; //水平解像度
DWORD biYPelsPerMeter; //垂直解像度
DWORD biClrUsed; //実使用カラーインデックス数
DWORD biClrImportant; //重要カラーインデックス数
} BITMAPINFOHEADER;
[BITMAPINFO構造体]
BITMAPINFOHEADERの情報に加えていろ情報を保持する
typedef struct tagBITMAPINFO{
BITMAPINFOHEADER bmiHeader; //BITMAPINFOHEADER構造体
RGBQUAD; bmiColors[1]; //RGBカラー情報
} BITMAPINFO, FAR *LPBITMAPINFO, *PBITMAPINFO;
[RGBQUAD構造体]
色調合の実譲歩を保持する
typedef struct tagRGBQUAD{
BYTE rgbBlue; //青の明るさ
BYTE rgbGreen; //緑の明るさ
BYTE rgbRed; //赤の明るさ
BYTE rgbReserved; //未使用(必ず0)
} RGBQUAD;
[PAINTSTRUCT構造体]
ウィンドウのクライアント領域を描画する際に使う情報を保持する
typedef struct tagPAINTSTRUCT{
HDC hDC; //描画用デバイスコンテキスト
BOOL fErase; //背景の再描画の必要性(0 = 必要なし)
RECT rcPaint; //描画要求領域の左上隅と右下隅
BOOL fRestore; //予約
BOOL fIncUpdate; //予約
BYTE rgbReserved(16); //予約
} PAINTSTRUCT;