プログラミングのメモ帳(C/C++/HSP)

日々のプログラミングで気づいた点や小技集を紹介します。(Windows 10/XP/Vista、VC2017、HSP)

指定領域のビットマップ保存

2010年08月12日 22時12分00秒 | ビットマップ関連

クライアント領域に色々な図形を描ける簡単なお絵かきソフトを作成したとします。
このソフトで描いたクライアント領域の図形をビットマップ形式で保存したい場合があります。
今回は思いっきり簡単にビットマップ形式でファイル保存できる方法を紹介します。

簡単に保存するには、ビットマップ形式のうちで32ビット限定で保存させます。
これが最も簡単にビットマップ形式のファイルに保存できる方法と思います。
それではビットマップ保存の具体的な記述を紹介します。(戻る)

サンプル

// 指定領域のビットマップ保存
extern BOOL funcSaveRect( LPCTSTR lpFname, HDC hDC, LONG cx, LONG cy, LONG sx, LONG sy )
{
    HANDLE hFile = CreateFile( lpFname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
    
    if ( hFile != INVALID_HANDLE_VALUE ){
        LONG    lHeadSize  = (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO));
        LONG    lWidthSize = (sx * sizeof(DWORD));
        LONG    lImageSize = (lWidthSize * sy);
        DWORD   dwSize;
        
        // BITMAPFILEHEADERの初期化
        BITMAPFILEHEADER bmpHead = { 0 };
        bmpHead.bfType          = 0x4D42;       // 識別子(BM)
        bmpHead.bfSize          = lHeadSize + lImageSize;
        bmpHead.bfReserved1     = 0;
        bmpHead.bfReserved2     = 0;
        bmpHead.bfOffBits       = lHeadSize;
        
        // BITMAPINFOの初期化
        BITMAPINFO bmpInfo = { 0 };
        bmpInfo.bmiHeader.biSize            = sizeof(BITMAPINFOHEADER);
        bmpInfo.bmiHeader.biWidth           = sx;
        bmpInfo.bmiHeader.biHeight          = sy;
        bmpInfo.bmiHeader.biPlanes          = 1;
        bmpInfo.bmiHeader.biBitCount        = 32;
        bmpInfo.bmiHeader.biCompression     = BI_RGB;
        bmpInfo.bmiHeader.biSizeImage       = 0;
        bmpInfo.bmiHeader.biXPelsPerMeter   = 0;
        bmpInfo.bmiHeader.biYPelsPerMeter   = 0;
        bmpInfo.bmiHeader.biClrUsed         = 0;
        bmpInfo.bmiHeader.biClrImportant    = 0;
        
        // DIBセクションの作成
        LPDWORD     lpPixel;    // ピクセル配列
        HBITMAP     hBitmap;    // ビットマップ
        HDC         hSaveDC;    // 保存スクリーン
        hBitmap = CreateDIBSection( NULL, &bmpInfo, DIB_RGB_COLORS, (LPVOID*)&lpPixel, NULL, 0 );
        hSaveDC = CreateCompatibleDC( hDC );
        SelectObject( hSaveDC, hBitmap );
        
        // 保存領域のコピー
        BitBlt( hSaveDC, 0, 0, sx, sy, hDC, cx, cy, SRCCOPY );
        
        // ファイルに書き込む
        WriteFile( hFile, &bmpHead, sizeof(BITMAPFILEHEADER), &dwSize, NULL );
        WriteFile( hFile, &bmpInfo, sizeof(BITMAPINFO),       &dwSize, NULL );
        WriteFile( hFile, lpPixel,  lImageSize,               &dwSize, NULL );
        
        // DIBセクションの破棄
        DeleteDC( hSaveDC );
        DeleteObject( hBitmap );
        CloseHandle( hFile );
        return TRUE;
    }
    return FALSE;
}

// 使用例
extern VOID funcSaveFile( HWND hWnd, LPCTSTR lpFname )
{
    HDC hDC;
    
    hDC = GetDC( hWnd );
    funcSaveRect( lpFname, hDC, 0, 0, 256, 256 );
    ReleaseDC( hWnd, hDC );
}
  • hWnd には、ウインドウ・ハンドルを指定します。
  • lpFname には、保存するビットマップのファイル名を指定します。

説明

funcSaveRect 関数は、指定した hDC の指定領域を切り取る形でビットマップ形式のファイルに保存します。
ビットマップのピクセル配列を取得するためにDIBセクションを作成してます。
ここで作成された保存スクリーンに hDC の指定領域を BitBlt 関数で切り取るようにコピーします。
あとは保存スクリーンのピクセル配列である lpPixel をファイルに書き出すだけです。
ファイルにはヘッダ情報(bmpHead)、ビットマップ情報(bmpInfo)、イメージ(lpPixel)の順に書き出します。
これで32ビット限定でビットマップ形式のファイルに保存されます。

その他

2色、16色、256色の場合もDIBセクションを作成してからパレット情報を作成します。
その後にヘッダ情報、ビットマップ情報、パレット情報、イメージ情報を順に書き出します。
このときの注意点としては、2色、16色、256色はイメージ情報がパックされることです。
パックとは、2色×4ピクセル=1バイト、16色×2ピクセル=1バイトという構造です。
256色は1ピクセルで1バイトなのでパレット値をそのままイメージ情報に変換するだけです。
※詳しくは、いずれ2色、16色、256色のビットマップ保存を紹介します。



コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« ダブル・バッファリングの方... | トップ | [バージョン情報]ダイアログ »
最新の画像もっと見る

コメントを投稿

ビットマップ関連」カテゴリの最新記事