[BMP]StretchDIBits
DIBを拡大/縮小する。
ファイルから読み込んだファイルやCreateDIBSection で作成した
DIBを拡大/縮小するにはStretchDIBits()関数を使う。
DDBを拡大/縮小する関数としてStretchBlt()関数もあるが、汎用性を
考えるとStretchDIBitsを覚えたほうがよいと思う。
int StretchDIBits(
HDC hdc, // デバイスコンテキスト
int XDest, // 転送先開始位置x座標
int YDest, // 転送先開始位置y座標
int nDestWidth, // 転送先画像幅
int nDestHeight, // 転送先画像高さ
int XSrc, // 元画像開始位置x座標
int YSrc, // 元画像開始位置y座標
int nSrcWidth, // 元画像幅
int nSrcHeight, // 元画像高さ
CONST VOID *lpBits, // 元画像イメージ
CONST BITMAPINFO *lpBitsInfo, // 元画像BITMAPINFO構造体
UINT iUsage, // 色形式
DWORD dwRop // ラスタオペレーション
);
戻り値は、コピーした走査行(高さのこと?)が返される。
上図のように、50%縮小した際のソースはこちら。
(エラー処理などは一切考慮なし)
class CSampleDlg : public CDialog
{
private:
// 元画像BIH
BITMAPINFOHEADER m_bih;
// 画像データ列格納
BYTE *m_pImg;
・・・
}
BOOL CSampleDlg::OnInitDialog()
{
・・・中略
CFile file(_T("C:\\Sample.bmp"), CFile::modeRead);
BITMAPFILEHEADER bfh;
file.Read(&bfh, sizeof(BITMAPFILEHEADER));
file.Read(&m_bih, sizeof(BITMAPINFOHEADER));
// イメージデータ取得
m_pImg = new BYTE [m_bih.biSizeImage];
file.Seek(bfh.bfOffBits, CFile::begin);
file.Read(m_pImg, m_bih.biSizeImage);
return TRUE;
}
void CSampleDlg::OnPaint()
{
if (IsIconic())
{
・・・中略
}
else
{
CPaintDC dc(this);
// 幅と高さを半分にする。
int nWidth = m_bih.biWidth / 2;
int nHeight = m_bih.biHeight / 2;
// 読み込んだ画像からDIBを作成する
BYTE *pImg;
HBITMAP hbmp = (HBITMAP)::CreateDIBSection(dc.GetSafeHdc(),
(BITMAPINFO*)&m_bih, DIB_RGB_COLORS, (void**)&pImg, NULL, 0);
memcpy(pImg, m_pImg, m_bih.biSizeImage);
// ビットマップオブジェクトに割り当て
CBitmap bmp;
bmp.Attach(hbmp);
// 拡大/縮小
::StretchDIBits(dc.GetSafeHdc(), 0, 0, nWidth, nHeight,
0, 0, m_bih.biWidth, m_bih.biHeight, m_pImg,
(BITMAPINFO*)&m_bih, DIB_RGB_COLORS, SRCCOPY);
}
}
このように、拡大/縮小後の幅と高さを指定することで、自動的に関数内で
拡大/縮小を行ってくれる。(元画像のサイズへの比率で。)
しかし、現状のリサイズ後イメージは画像リンクを参照してもらえば
わかるように、色の割り当てが荒い。
(回転の際に紹介したニアレストネイバー法 のような状態)
この画像を補間した状態で出力するためには、上記コードに
1行追加するだけでよいが、それはまた次回 。