ビットマップをファイルに保存


  ビットマップをファイルに保存するということは、ビットマップDIBを作成して、そのDIBを保存するということになります。

 [備考]
   色ビット数が16未満ならパレット情報(色調合情報であるRGBQUAD構造体)が存在し、それを読み込む必要があります。
   しかし、最近の環境では32ビットのものが多いので、ここでは、RGBQUAD構造体の対応を省いています。
 
//クライアント領域の画像をDIBにして、ファイルへ保存
void CSaveBMPDlg::OnButton1() 
{

    RECT rc;
    HDC hDC, hCompatibleDC;
    HBITMAP hBitmap, hBitmapPrev;
    BITMAPINFO *pbmi;
    void *pbits;
    HANDLE hfile;
    DWORD tmp;
    BITMAPFILEHEADER bmfh;

    //ビットマップインフォを作成。
    HWND hWnd = CSaveBMPDlg::m_hWnd;
    
    //ビットマップをセーブする範囲(Client領域)を取得する
    ::GetClientRect(hWnd, &rc);

    
    hDC = ::GetDC(hWnd);
    pbmi = (BITMAPINFO*)new BYTE[sizeof(BITMAPINFO)];

    //BITMAPFILEHEADERの作成
    ZeroMemory(&pbmi->bmiHeader, sizeof(pbmi->bmiHeader));
    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    pbmi->bmiHeader.biWidth = rc.right-rc.left;
    pbmi->bmiHeader.biHeight = rc.bottom-rc.top;
    pbmi->bmiHeader.biPlanes = 1;

    //1ピクセルあたりビット数を格納
    pbmi->bmiHeader.biBitCount = GetDeviceCaps(hDC, BITSPIXEL);

    //ビットマップのバイト数を格納
    //(今時の環境では、色は1ピクセル=4バイト表現なので、単純に*4とした。)
    pbmi->bmiHeader.biSizeImage = pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biHeight * 4;


    //DIB を作成してウインドウからビットマップをコピー
    hBitmap = CreateDIBSection(hDC, pbmi, DIB_RGB_COLORS, &pbits, NULL, 0);
    hCompatibleDC = CreateCompatibleDC(hDC);
    hBitmapPrev = (HBITMAP)SelectObject(hCompatibleDC, hBitmap);
    BitBlt(hCompatibleDC, 0, 0, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight, hDC, rc.left, rc.top, SRCCOPY);
    SelectObject(hCompatibleDC, hBitmapPrev);
    ::ReleaseDC(hWnd, hDC);

    //ビットマップファイルヘッダーを作成。
    bmfh.bfType = 0x4D42;   //BitMapファイルを表すコード
                            //("BM"をWORD型に格納したもので、決まりごとです。)
    bmfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
    bmfh.bfSize = bmfh.bfOffBits+pbmi->bmiHeader.biSizeImage;

    //DIB をファイルへセーブ
    hfile = CreateFile("TEST1.bmp", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
    WriteFile(hfile, &bmfh, sizeof(bmfh), &tmp, NULL);
    WriteFile(hfile, &pbmi->bmiHeader, sizeof(pbmi->bmiHeader), &tmp, NULL);
    SetFilePointer(hfile, bmfh.bfOffBits, NULL, FILE_BEGIN);
    WriteFile(hfile, pbits, pbmi->bmiHeader.biSizeImage, &tmp, NULL);
    CloseHandle(hfile);

    //BITMAPINFOの解放
    delete[] (BYTE*)pbmi;    
}