Save HBITMAP to *.bmp file using only Win32

前端 未结 5 1191
醉酒成梦
醉酒成梦 2020-11-29 05:25

I have a HBITMAP in my pure Win32 project (no external libraries are used). Can I export it to a *.bmp file using only Winapi and/or CRT functions so I don\'t incur any extr

相关标签:
5条回答
  • 2020-11-29 05:56

    One function code for HBITMAP to *.bmp file.

    BOOL SaveHBITMAPToFile(HBITMAP hBitmap, LPCTSTR lpszFileName)
    {
        HDC hDC;
        int iBits;
        WORD wBitCount;
        DWORD dwPaletteSize = 0, dwBmBitsSize = 0, dwDIBSize = 0, dwWritten = 0;
        BITMAP Bitmap0;
        BITMAPFILEHEADER bmfHdr;
        BITMAPINFOHEADER bi;
        LPBITMAPINFOHEADER lpbi;
        HANDLE fh, hDib, hPal, hOldPal2 = NULL;
        hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
        iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
        DeleteDC(hDC);
        if (iBits <= 1)
            wBitCount = 1;
        else if (iBits <= 4)
            wBitCount = 4;
        else if (iBits <= 8)
            wBitCount = 8;
        else
            wBitCount = 24;
        GetObject(hBitmap, sizeof(Bitmap0), (LPSTR)&Bitmap0);
        bi.biSize = sizeof(BITMAPINFOHEADER);
        bi.biWidth = Bitmap0.bmWidth;
        bi.biHeight = -Bitmap0.bmHeight;
        bi.biPlanes = 1;
        bi.biBitCount = wBitCount;
        bi.biCompression = BI_RGB;
        bi.biSizeImage = 0;
        bi.biXPelsPerMeter = 0;
        bi.biYPelsPerMeter = 0;
        bi.biClrImportant = 0;
        bi.biClrUsed = 256;
        dwBmBitsSize = ((Bitmap0.bmWidth * wBitCount + 31) & ~31) / 8
            * Bitmap0.bmHeight;
        hDib = GlobalAlloc(GHND, dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
        lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
        *lpbi = bi;
    
        hPal = GetStockObject(DEFAULT_PALETTE);
        if (hPal)
        {
            hDC = GetDC(NULL);
            hOldPal2 = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
            RealizePalette(hDC);
        }
    
    
        GetDIBits(hDC, hBitmap, 0, (UINT)Bitmap0.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
            + dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);
    
        if (hOldPal2)
        {
            SelectPalette(hDC, (HPALETTE)hOldPal2, TRUE);
            RealizePalette(hDC);
            ReleaseDC(NULL, hDC);
        }
    
        fh = CreateFile(lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
    
        if (fh == INVALID_HANDLE_VALUE)
            return FALSE;
    
        bmfHdr.bfType = 0x4D42; // "BM"
        dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;
        bmfHdr.bfSize = dwDIBSize;
        bmfHdr.bfReserved1 = 0;
        bmfHdr.bfReserved2 = 0;
        bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;
    
        WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
    
        WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
        GlobalUnlock(hDib);
        GlobalFree(hDib);
        CloseHandle(fh);
        return TRUE;
    }
    
    0 讨论(0)
  • 2020-11-29 06:00

    i'll leave this self contained proof of concept here since I'll probably need to look it up later since it's not obvious. It takes a screenshot of the desktop window and saves it into bitmap.bmp:

    #include <Windows.h>
    #include <stdio.h>
    #include <assert.h>
    
    /* forward declarations */
    PBITMAPINFO CreateBitmapInfoStruct(HBITMAP);
    void CreateBMPFile(LPTSTR pszFile, HBITMAP hBMP); 
    int main(int argc, char **argv);
    
    PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp)
    { 
        BITMAP bmp; 
        PBITMAPINFO pbmi; 
        WORD    cClrBits; 
    
        // Retrieve the bitmap color format, width, and height.  
        assert(GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)); 
    
        // Convert the color format to a count of bits.  
        cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
        if (cClrBits == 1) 
            cClrBits = 1; 
        else if (cClrBits <= 4) 
            cClrBits = 4; 
        else if (cClrBits <= 8) 
            cClrBits = 8; 
        else if (cClrBits <= 16) 
            cClrBits = 16; 
        else if (cClrBits <= 24) 
            cClrBits = 24; 
        else cClrBits = 32; 
    
        // Allocate memory for the BITMAPINFO structure. (This structure  
        // contains a BITMAPINFOHEADER structure and an array of RGBQUAD  
        // data structures.)  
    
         if (cClrBits < 24) 
             pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                        sizeof(BITMAPINFOHEADER) + 
                        sizeof(RGBQUAD) * (1<< cClrBits)); 
    
         // There is no RGBQUAD array for these formats: 24-bit-per-pixel or 32-bit-per-pixel 
    
         else 
             pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                        sizeof(BITMAPINFOHEADER)); 
    
        // Initialize the fields in the BITMAPINFO structure.  
    
        pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
        pbmi->bmiHeader.biWidth = bmp.bmWidth; 
        pbmi->bmiHeader.biHeight = bmp.bmHeight; 
        pbmi->bmiHeader.biPlanes = bmp.bmPlanes; 
        pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; 
        if (cClrBits < 24) 
            pbmi->bmiHeader.biClrUsed = (1<<cClrBits); 
    
        // If the bitmap is not compressed, set the BI_RGB flag.  
        pbmi->bmiHeader.biCompression = BI_RGB; 
    
        // Compute the number of bytes in the array of color  
        // indices and store the result in biSizeImage.  
        // The width must be DWORD aligned unless the bitmap is RLE 
        // compressed. 
        pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
                                      * pbmi->bmiHeader.biHeight; 
        // Set biClrImportant to 0, indicating that all of the  
        // device colors are important.  
         pbmi->bmiHeader.biClrImportant = 0; 
         return pbmi; 
     } 
    
    void CreateBMPFile(LPTSTR pszFile, HBITMAP hBMP) 
     { 
         HANDLE hf;                 // file handle  
        BITMAPFILEHEADER hdr;       // bitmap file-header  
        PBITMAPINFOHEADER pbih;     // bitmap info-header  
        LPBYTE lpBits;              // memory pointer  
        DWORD dwTotal;              // total count of bytes  
        DWORD cb;                   // incremental count of bytes  
        BYTE *hp;                   // byte pointer  
        DWORD dwTmp;     
        PBITMAPINFO pbi;
        HDC hDC;
    
        hDC = CreateCompatibleDC(GetWindowDC(GetDesktopWindow()));
        SelectObject(hDC, hBMP);
    
        pbi = CreateBitmapInfoStruct(hBMP);
    
        pbih = (PBITMAPINFOHEADER) pbi; 
        lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
    
        assert(lpBits) ;
    
        // Retrieve the color table (RGBQUAD array) and the bits  
        // (array of palette indices) from the DIB.  
        assert(GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, 
            DIB_RGB_COLORS));
    
        // Create the .BMP file.  
        hf = CreateFile(pszFile, 
                       GENERIC_READ | GENERIC_WRITE, 
                       (DWORD) 0, 
                        NULL, 
                       CREATE_ALWAYS, 
                       FILE_ATTRIBUTE_NORMAL, 
                       (HANDLE) NULL); 
        assert(hf != INVALID_HANDLE_VALUE) ;
    
        hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"  
        // Compute the size of the entire file.  
        hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
                     pbih->biSize + pbih->biClrUsed 
                     * sizeof(RGBQUAD) + pbih->biSizeImage); 
        hdr.bfReserved1 = 0; 
        hdr.bfReserved2 = 0; 
    
        // Compute the offset to the array of color indices.  
        hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
                        pbih->biSize + pbih->biClrUsed 
                        * sizeof (RGBQUAD); 
    
        // Copy the BITMAPFILEHEADER into the .BMP file.  
        assert(WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), 
            (LPDWORD) &dwTmp,  NULL)); 
    
        // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.  
        assert(WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) 
                      + pbih->biClrUsed * sizeof (RGBQUAD), 
                      (LPDWORD) &dwTmp, ( NULL)));
    
        // Copy the array of color indices into the .BMP file.  
        dwTotal = cb = pbih->biSizeImage; 
        hp = lpBits; 
        assert(WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)); 
    
        // Close the .BMP file.  
         assert(CloseHandle(hf)); 
    
        // Free memory.  
        GlobalFree((HGLOBAL)lpBits);
    }
    
    int main(int argc, char **argv)
    {
        HWND hwnd;
        HDC hdc[2];
        HBITMAP hbitmap;
        RECT rect;
    
        hwnd = GetDesktopWindow();
        GetClientRect(hwnd, &rect);
        hdc[0] = GetWindowDC(hwnd);
        hbitmap = CreateCompatibleBitmap(hdc[0], rect.right, rect.bottom); 
        hdc[1] = CreateCompatibleDC(hdc[0]);
        SelectObject(hdc[1], hbitmap);    
    
        BitBlt (    
            hdc[1],
            0,
            0,
            rect.right,
            rect.bottom,
            hdc[0],
            0,
            0,
            SRCCOPY
        );
    
        CreateBMPFile("bitmap.bmp", hbitmap);
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-29 06:03

    Yes, this is possible, using the Windows Imaging Component (WIC). WIC offers built-in encoders, so that you don't have to manually write out bitmap headers and data. It also allows you to choose a different encoder (e.g. PNG), by changing as little as one line of code.

    The process is fairly straight forward. It consists of the following steps:

    1. Retrieve properties from the source HBITMAP using GetObject (dimensions, bit depth).
    2. Create an IWICImagingFactory instance.
    3. Create an IWICBitmap instance from the HBITMAP (IWICImagingFactory::CreateBitmapFromHBITMAP).
    4. Create an IWICStream instance (IWICImagingFactory::CreateStream), and attach it to a filename (IWICStream::InitializeFromFilename).
    5. Create an IWICBitmapEncoder instance (IWICImagingFactory::CreateEncoder), and associate it with the stream (IWICBitmapEncoder::Initialize).
    6. Create an IWICBitmapFrameEncode instance (IWICBitmapEncoder::CreateNewFrame), and initialize it in compliance with the source HBITMAP (IWICBitmapFrameEncode::Initialize, IWICBitmapFrameEncode::SetSize, IWICBitmapFrameEncode::SetPixelFormat).
    7. Write bitmap data to the frame (IWICBitmapFrameEncode::WriteSource).
    8. Commit frame and data to stream (IWICBitmapFrameEncode::Commit, IWICBitmapEncoder::Commit).

    Translated to code:

    #define COBJMACROS
    
    #include <Objbase.h>
    #include <wincodec.h>
    #include <Windows.h>
    #include <Winerror.h>
    
    #pragma comment(lib, "Windowscodecs.lib")
    
    HRESULT WriteBitmap(HBITMAP bitmap, const wchar_t* pathname) {
    
        HRESULT hr = S_OK;
    
        // (1) Retrieve properties from the source HBITMAP.
        BITMAP bm_info = { 0 };
        if (!GetObject(bitmap, sizeof(bm_info), &bm_info))
            hr = E_FAIL;
    
        // (2) Create an IWICImagingFactory instance.
        IWICImagingFactory* factory = NULL;
        if (SUCCEEDED(hr))
            hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
                                  &IID_IWICImagingFactory, &factory);
    
        // (3) Create an IWICBitmap instance from the HBITMAP.
        IWICBitmap* wic_bitmap = NULL;
        if (SUCCEEDED(hr))
            hr = IWICImagingFactory_CreateBitmapFromHBITMAP(factory, bitmap, NULL,
                                                            WICBitmapIgnoreAlpha,
                                                            &wic_bitmap);
    
        // (4) Create an IWICStream instance, and attach it to a filename.
        IWICStream* stream = NULL;
        if (SUCCEEDED(hr))
            hr = IWICImagingFactory_CreateStream(factory, &stream);
        if (SUCCEEDED(hr))
            hr = IWICStream_InitializeFromFilename(stream, pathname, GENERIC_WRITE);
    
        // (5) Create an IWICBitmapEncoder instance, and associate it with the stream.
        IWICBitmapEncoder* encoder = NULL;
        if (SUCCEEDED(hr))
            hr = IWICImagingFactory_CreateEncoder(factory, &GUID_ContainerFormatBmp, NULL,
                                                  &encoder);
        if (SUCCEEDED(hr))
            hr = IWICBitmapEncoder_Initialize(encoder, (IStream*)stream,
                                              WICBitmapEncoderNoCache);
    
        // (6) Create an IWICBitmapFrameEncode instance, and initialize it
        // in compliance with the source HBITMAP.
        IWICBitmapFrameEncode* frame = NULL;
        if (SUCCEEDED(hr))
            hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frame, NULL);
        if (SUCCEEDED(hr))
            hr = IWICBitmapFrameEncode_Initialize(frame, NULL);
        if (SUCCEEDED(hr))
            hr = IWICBitmapFrameEncode_SetSize(frame, bm_info.bmWidth, bm_info.bmHeight);
        if (SUCCEEDED(hr)) {
            GUID pixel_format = GUID_WICPixelFormat24bppBGR;
            hr = IWICBitmapFrameEncode_SetPixelFormat(frame, &pixel_format);
        }
    
        // (7) Write bitmap data to the frame.
        if (SUCCEEDED(hr))
            hr = IWICBitmapFrameEncode_WriteSource(frame, (IWICBitmapSource*)wic_bitmap,
                                                   NULL);
    
        // (8) Commit frame and data to stream.
        if (SUCCEEDED(hr))
            hr = IWICBitmapFrameEncode_Commit(frame);
        if (SUCCEEDED(hr))
            hr = IWICBitmapEncoder_Commit(encoder);
    
        // Cleanup
        if (frame)
            IWICBitmapFrameEncode_Release(frame);
        if (encoder)
            IWICBitmapEncoder_Release(encoder);
        if (stream)
            IWICStream_Release(stream);
        if (wic_bitmap)
            IWICBitmap_Release(wic_bitmap);
        if (factory)
            IWICImagingFactory_Release(factory);
    
        return hr;
    }
    

    Here's a companion test application to showcase the usage. Make sure to #define OEMRESOURCE prior to including any system headers to allow use of the OBM_ images.

    int wmain(int argc, wchar_t** argv) {
    
        HRESULT hr = S_OK;
        hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
        if (FAILED(hr))
            return -1;
    
        HBITMAP bitmap = LoadImage(NULL, MAKEINTRESOURCE(OBM_ZOOM), IMAGE_BITMAP, 0, 0,
                                   LR_DEFAULTCOLOR);
    
        hr = WriteBitmap(bitmap, argv[1]);
    
        // Cleanup
        if (bitmap)
            DeleteObject(bitmap);
    
        CoUninitialize();
        return 0;
    }
    

    This will load a system-provided bitmap, and save it to the pathname specified as an argument on the command line.

    Limitations:

    • No support for alpha channels. Although bitmaps version 5 support alpha channels, I am not aware of any way to find out, whether an HBITMAP refers to a bitmap with an alpha channel, nor would I know, how to determine, whether it is pre-multiplied. If you do want to support an alpha channel, make sure to set the EnableV5Header32bppBGRA property to VARIANT_TRUE (see BMP Format: Encoding).
    • No support for palletized bitmaps (bpp <= 8). If you are dealing with palletized bitmaps, make sure to supply an appropriate HPALETTE in the call to IWICImagingFactory::CreateBitmapFromHBITMAP.
    • The encoder is initialized with the GUID_WICPixelFormat24bppBGR pixel format constant. A more versatile implementation would deduce a compatible pixel format from the source HBITMAP.
    0 讨论(0)
  • 2020-11-29 06:05

    Yet another minimalistic option is to use OLE's IPicture. It's always been around, still a part of Win32 API:

    #define _S(exp) (([](HRESULT hr) { if (FAILED(hr)) _com_raise_error(hr); return hr; })(exp));
    
    PICTDESC pictdesc = {};
    pictdesc.cbSizeofstruct = sizeof(pictdesc);
    pictdesc.picType = PICTYPE_BITMAP;
    pictdesc.bmp.hbitmap = hBitmap;
    
    CComPtr<IPicture> picture;
    _S( OleCreatePictureIndirect(&pictdesc, __uuidof(IPicture), FALSE, (LPVOID*)&picture) );
    
    // Save to a stream
    
    CComPtr<IStream> stream;
    _S( CreateStreamOnHGlobal(NULL, TRUE, &stream) );
    LONG cbSize = 0;
    _S( picture->SaveAsFile(stream, TRUE, &cbSize) );
    
    // Or save to a file
    
    CComPtr<IPictureDisp> disp;
    _S( picture->QueryInterface(&disp) );
    _S( OleSavePictureFile(disp, CComBSTR("C:\\Temp\\File.bmp")) );
    
    0 讨论(0)
  • 2020-11-29 06:13

    There is no API to save into file directly because, generally, having a bitmap handle does not mean you have direct access to bitmap data. Your solution is to copy bitmap into another bitmap with data access (DIB) and then using it data to write into file.

    You typically either create another bitmap using CreateDIBSection, or you get bitmap data with GetDIBits.

    CreateFile, WriteFile writes data into file.

    You write: BITMAPFILEHEADER, then BITMAPINFOHEADER, then palette (which you typically don't have when bits/pixel is over 8), then data itself.

    See also:

    • C++: Hbitmap/BITMAP into .bmp file (this answer)
    • Saving .bmp file using hBitmap = CreateDIBSection() in C Win32
    • Storing an Image on MSDN

    The Code

    This is the code from the MSDN article (Note that you need to define the errhandler() function):

    PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)
    { 
        BITMAP bmp; 
        PBITMAPINFO pbmi; 
        WORD    cClrBits; 
    
        // Retrieve the bitmap color format, width, and height.  
        if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) 
            errhandler("GetObject", hwnd); 
    
        // Convert the color format to a count of bits.  
        cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
        if (cClrBits == 1) 
            cClrBits = 1; 
        else if (cClrBits <= 4) 
            cClrBits = 4; 
        else if (cClrBits <= 8) 
            cClrBits = 8; 
        else if (cClrBits <= 16) 
            cClrBits = 16; 
        else if (cClrBits <= 24) 
            cClrBits = 24; 
        else cClrBits = 32; 
    
        // Allocate memory for the BITMAPINFO structure. (This structure  
        // contains a BITMAPINFOHEADER structure and an array of RGBQUAD  
        // data structures.)  
    
        if (cClrBits < 24) 
            pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
            sizeof(BITMAPINFOHEADER) + 
            sizeof(RGBQUAD) * (1<< cClrBits)); 
    
        // There is no RGBQUAD array for these formats: 24-bit-per-pixel or 32-bit-per-pixel 
    
        else 
            pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
            sizeof(BITMAPINFOHEADER)); 
    
        // Initialize the fields in the BITMAPINFO structure.  
    
        pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
        pbmi->bmiHeader.biWidth = bmp.bmWidth; 
        pbmi->bmiHeader.biHeight = bmp.bmHeight; 
        pbmi->bmiHeader.biPlanes = bmp.bmPlanes; 
        pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; 
        if (cClrBits < 24) 
            pbmi->bmiHeader.biClrUsed = (1<<cClrBits); 
    
        // If the bitmap is not compressed, set the BI_RGB flag.  
        pbmi->bmiHeader.biCompression = BI_RGB; 
    
        // Compute the number of bytes in the array of color  
        // indices and store the result in biSizeImage.  
        // The width must be DWORD aligned unless the bitmap is RLE 
        // compressed. 
        pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
            * pbmi->bmiHeader.biHeight; 
        // Set biClrImportant to 0, indicating that all of the  
        // device colors are important.  
        pbmi->bmiHeader.biClrImportant = 0; 
        return pbmi; 
    } 
    
    void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, 
                       HBITMAP hBMP, HDC hDC) 
    { 
        HANDLE hf;                 // file handle  
        BITMAPFILEHEADER hdr;       // bitmap file-header  
        PBITMAPINFOHEADER pbih;     // bitmap info-header  
        LPBYTE lpBits;              // memory pointer  
        DWORD dwTotal;              // total count of bytes  
        DWORD cb;                   // incremental count of bytes  
        BYTE *hp;                   // byte pointer  
        DWORD dwTmp; 
    
        pbih = (PBITMAPINFOHEADER) pbi; 
        lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
    
        if (!lpBits) 
            errhandler("GlobalAlloc", hwnd); 
    
        // Retrieve the color table (RGBQUAD array) and the bits  
        // (array of palette indices) from the DIB.  
        if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, 
            DIB_RGB_COLORS)) 
        {
            errhandler("GetDIBits", hwnd); 
        }
    
        // Create the .BMP file.  
        hf = CreateFile(pszFile, 
            GENERIC_READ | GENERIC_WRITE, 
            (DWORD) 0, 
            NULL, 
            CREATE_ALWAYS, 
            FILE_ATTRIBUTE_NORMAL, 
            (HANDLE) NULL); 
        if (hf == INVALID_HANDLE_VALUE) 
            errhandler("CreateFile", hwnd); 
        hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"  
        // Compute the size of the entire file.  
        hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
            pbih->biSize + pbih->biClrUsed 
            * sizeof(RGBQUAD) + pbih->biSizeImage); 
        hdr.bfReserved1 = 0; 
        hdr.bfReserved2 = 0; 
    
        // Compute the offset to the array of color indices.  
        hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
            pbih->biSize + pbih->biClrUsed 
            * sizeof (RGBQUAD); 
    
        // Copy the BITMAPFILEHEADER into the .BMP file.  
        if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), 
            (LPDWORD) &dwTmp,  NULL)) 
        {
            errhandler("WriteFile", hwnd); 
        }
    
        // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.  
        if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) 
            + pbih->biClrUsed * sizeof (RGBQUAD), 
            (LPDWORD) &dwTmp, ( NULL)))
            errhandler("WriteFile", hwnd); 
    
        // Copy the array of color indices into the .BMP file.  
        dwTotal = cb = pbih->biSizeImage; 
        hp = lpBits; 
        if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) 
            errhandler("WriteFile", hwnd); 
    
        // Close the .BMP file.  
        if (!CloseHandle(hf)) 
            errhandler("CloseHandle", hwnd); 
    
        // Free memory.  
        GlobalFree((HGLOBAL)lpBits);
    }
    
    0 讨论(0)
提交回复
热议问题