// CDIBSectionの派生クラスとして、CDIBSectionExを作ります。
class CDIBSectionEx:public CDIBSection{
public:
LONG m_bpp; // 1ピクセル当たりのビット数
RGBQUAD m_rgb[256]; // カラーテーブル
CDIBSectionEx():m_bpp(0){;}
BOOL LoadBitmap(LPSTR filename);
BOOL SaveBitmap(LPSTR filename);
};
// BITMAPロードメンバ関数
BOOL CDIBSectionEx::LoadBitmap(LPSTR filename)
{
// ファイルオープン
HFILE fp = _lopen(filename,OF_READ);
if(fp == HFILE_ERROR)return FALSE;
LONG filesize = _llseek(fp,0,FILE_END); // ファイルサイズ取得
_llseek(fp,0,FILE_BEGIN);
// ファイルヘッダー読み込み
BITMAPFILEHEADER fh;
_lread(fp,&fh,sizeof(fh));
if(memcmp(&fh.bfType,"BM",2) != 0){
// BITMAPファイルでは無い
_lclose(fp);
return FALSE;
}
// 画像情報ヘッダー読み込み
LPBITMAPINFO ih = (LPBITMAPINFO)malloc(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
_lread(fp,ih,sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
// ヘッダーに従って、DIBSectionを生成する
HDC dc = GetDC(0);
if(!Create(dc,ih,DIB_RGB_COLORS)){
ReleaseDC(0,dc);
free(ih);
_lclose(fp);
return FALSE;
}
ReleaseDC(0,dc);
m_bpp = ih->bmiHeader.biBitCount;
// 必要ならカラーテーブルを読み込む
switch(m_bpp){
case 1: memcpy(m_rgb,ih->bmiColors,sizeof(RGBQUAD) * 2);break;
case 4: memcpy(m_rgb,ih->bmiColors,sizeof(RGBQUAD) * 16);break;
case 8: memcpy(m_rgb,ih->bmiColors,sizeof(RGBQUAD) * 256);break;
}
// 画像データ読み込み
_llseek(fp,fh.bfOffBits,FILE_BEGIN);
_lread(fp,m_bits,GET_DIBSIZE(ih));
_lclose(fp);
free(ih);
return TRUE;
}
// BITMAPセーブメンバ関数
BOOL CDIBSectionEx::SaveBitmap(LPSTR filename)
{
// BITMAP情報生成
BITMAPFILEHEADER fh; ZeroMemory(&fh,sizeof(fh));
BITMAPINFOHEADER ih; ZeroMemory(&ih,sizeof(ih));
LONG rgb_count = 0;
memcpy(&fh.bfType,"BM",2);
fh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
ih.biSize = sizeof(ih);
ih.biWidth = m_width;
ih.biHeight = m_height;
ih.biPlanes = 1;
ih.biBitCount = (WORD)m_bpp;
ih.biCompression = BI_RGB;
switch(m_bpp){
case 1:
rgb_count = 2;
ih.biSizeImage = (((ih.biWidth / 4) + 3) & 0xfffffffc) * ih.biHeight;
fh.bfOffBits += (sizeof(RGBQUAD) * 2);
break;
case 4:
rgb_count = 16;
ih.biSizeImage = (((ih.biWidth / 2) + 3) & 0xfffffffc) * ih.biHeight;
fh.bfOffBits += (sizeof(RGBQUAD) * 16);
break;
case 8:
rgb_count = 256;
ih.biSizeImage = ((ih.biWidth + 3) & 0xfffffffc) * ih.biHeight;
fh.bfOffBits += (sizeof(RGBQUAD) * 256);
break;
case 24:
rgb_count = 0;
ih.biSizeImage = ((ih.biWidth * 3 + 3) & 0xfffffffc) * ih.biHeight;
break;
default:
return FALSE;
}
fh.bfSize = fh.bfOffBits + ih.biSizeImage;
// ファイル出力オープン
HFILE fp = _lcreat(filename,0);
if(fp == HFILE_ERROR)return FALSE;
// ファイルヘッダー出力
_lwrite(fp,(LPSTR)&fh,sizeof(fh));
// BITMAP情報出力
_lwrite(fp,(LPSTR)&ih,sizeof(ih));
if(rgb_count > 0)_lwrite(fp,(LPSTR)m_rgb,sizeof(RGBQUAD) * rgb_count);
// 画像データ出力
_lwrite(fp,(LPSTR)m_bits,ih.biSizeImage);
_lclose(fp);
return TRUE;
}
// CDIBSectionExの使用例です。
// ファイルからBITMAPをロードし、加工した後にファイル出力を行います。
CDIBSectionEx dib;
if(dib.LoadBitmap("input.bmp")){
// dibをGDIで加工できるようにデバイスコンテキストを用意する
HDC dc = GetDC(0);
HDC mdc = CreateCompatibleDC(dc);
ReleaseDC(dc);
HBITMAP ob = SelectObject(mdc,dib);
// テキストを書きこむ
SetBkMode(mdc,TRANSPARENT);
TextOut(mdc,32,64,"あいうえおかきくけこ",10);
// デバイスコンテキストを開放する
SelectObject(mdc,ob);
DeleteDC(mdc);
// ファイル出力
dib.SaveBitmap("output.bmp");
}