OS:windows xp
言語:C/C++
「ビットマップ(DDB)ファイルを読み込むプログラム-(Windows, C/C++)」ではデバイス依存のビットマップを読み込むプログラムを取り上げました。
デバイスに依存しないビットマップ(DIB)を扱う方法も覚えたので、書き留めます。
以下のCDibクラスが、DIBを扱うクラスです。
※1 DIBは、1行のバイト数(横1列の画素を格納するのに必要なバイト数)が4の倍数でなければならないので、ファイルの読み書きに注意が必要です。
※2 DDBは画像の左上が原点ですが、DIBは左下が原点です。
※3 HDCに転送するにはStretchDIBits関数を使います。
int StretchDIBits(
HDC hdc, // 転送先のHDC
int XDest, // 転送先矩形の左上隅の x 座標
int YDest, // 転送先矩形の左上隅の y 座標
int nDestWidth, // 転送先矩形の幅
int nDestHeight, // 転送先矩形の高さ
int XSrc, // 転送元矩形の左上隅の x 座標
int YSrc, // 転送元矩形の左上隅の x 座標
int nSrcWidth, // 転送元矩形の幅
int nSrcHeight, // 転送元矩形の高さ
CONST VOID *lpBits, // ビット列(CDibのメンバ変数pixel)
CONST BITMAPINFO *lpBitsInfo, // ビットマップのデータ(CDibのメンバ変数bmpInfoへのポインタ)
UINT iUsage, // データの種類(ここではDIB_RGB_COLORSを指定)
DWORD dwRop // ラスタオペレーションコード(普通に転送するだけならSRCCOPYを指定)
);
/* 宣言 */
#include <windows.h>
class CDib
{
public:
CDib(const char* filename);
CDib(const int w, const int h);
~CDib();
int getWidth() {
return this->bmpInfo.bmiHeader.biWidth;
}
int getHeight() {
return this->bmpInfo.bmiHeader.biHeight;
}
unsigned char* getPixel() {
return this->pixel;
}
private:
BITMAPFILEHEADER bfh;
BITMAPINFO bmpInfo;
unsigned char* pixel;
int len;
};
/* 定義 */
#define BMP_TYPE (('M' << 8) + 'B')
static int getBytePerLine(const int width)
{
const int r = (width * 3) % 4;
return ((r == 0) ? width * 3 : width * 3 + (4 - r));
}
CDib::CDib(const char* filename)
: pixel(NULL), len(0)
{
// ファイル読み込み
FILE* fp = NULL;
fp = fopen(filename, "rb");
// ヘッダーの読み込み
fread(&(this->bfh), sizeof(BITMAPFILEHEADER), 1, fp);
fread(&(this->bmpInfo.bmiHeader), sizeof(BITMAPINFOHEADER), 1, fp);
// ピクセル列の読み込み
const int width = this->bmpInfo.bmiHeader.biWidth;
const int height = this->bmpInfo.bmiHeader.biHeight;
this->len = getBytePerLine(width);
this->pixel = new unsigned char[ this->len * height ];
fread(this->pixel, sizeof(unsigned char), this->len * height, fp);
fclose(fp);
}
CDib::CDib(const int w, const int h)
: pixel(NULL), len(0)
{
// BITMAPINFOHEADERの設定
this->bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
this->bmpInfo.bmiHeader.biPlanes = 1;
this->bmpInfo.bmiHeader.biCompression = BI_RGB;
this->bmpInfo.bmiHeader.biWidth = w;
this->bmpInfo.bmiHeader.biHeight = h;
this->bmpInfo.bmiHeader.biBitCount = 24;
this->bmpInfo.bmiHeader.biSizeImage = 0;
this->len = getBytePerLine(w);
this->pixel = new unsigned char[ this->len * h ];
memset(this->pixel, 0xff, this->len * h);
this->bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + this->len * h;
this->bfh.bfType = BMP_TYPE;
this->bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
}
CDib::~CDib()
{
if ( this->pixel != NULL ) {
delete [] this->pixel;
}
}