1. 先将DDB转换为DIB (DDBToDIB)
2. 再将DIB存盘 (DDBToDIB)来自 MFC Sourcebook 网站,这里也有
http://www.csdn.net/visual%20C++/Source%20Code/Bitmap/ddb_to_dib.shtml.htm
http://www.csdn.net/visual%20C++/Source%20Code/Bitmap/bitmap_to_file.shtml.htm
// DDBToDIB - Creates a DIB from a DDB
// bitmap - Device dependent bitmap
// dwCompression - Type of compression - see BITMAPINFOHEADER
// pPal - Logical palette
HANDLE DDBToDIB( CBitmap& bitmap, DWORD dwCompression, CPalette* pPal ) 
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER  lpbi;
DWORD dwLen;
HANDLE hDIB;
HANDLE handle;
HDC  hDC;
HPALETTE hPal;
ASSERT( bitmap.GetSafeHandle() ); // The function has no arg for bitfields
if( dwCompression == BI_BITFIELDS )
return NULL; // If a palette has not been supplied use defaul palette
hPal = (HPALETTE) pPal->GetSafeHandle();
if (hPal==NULL)
hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE); // Get bitmap information
bitmap.GetObject(sizeof(bm),(LPSTR)&bm); // Initialize the bitmapinfoheader
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight  = bm.bmHeight;
bi.biPlanes  = 1;
bi.biBitCount = bm.bmPlanes * bm.bmBitsPixel;
bi.biCompression = dwCompression;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0; // Compute the size of the  infoheader and the color table
int nColors = (1 << bi.biBitCount);
if( nColors > 256 ) 
nColors = 0;
dwLen  = bi.biSize + nColors * sizeof(RGBQUAD); // We need a device context to get the DIB from
hDC = GetDC(NULL);
hPal = SelectPalette(hDC,hPal,FALSE);
RealizePalette(hDC); // Allocate enough memory to hold bitmapinfoheader and color table
hDIB = GlobalAlloc(GMEM_FIXED,dwLen); if (!hDIB){
SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
} lpbi = (LPBITMAPINFOHEADER)hDIB; *lpbi = bi; // Call GetDIBits with a NULL lpBits param, so the device driver 
// will calculate the biSizeImage field 
GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight,
(LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS); bi = *lpbi; // If the driver did not fill in the biSizeImage field, then compute it
// Each scan line of the image is aligned on a DWORD (32bit) boundary
if (bi.biSizeImage == 0){
bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) 
* bi.biHeight; // If a compression scheme is used the result may infact be larger
// Increase the size to account for this.
if (dwCompression != BI_RGB)
bi.biSizeImage = (bi.biSizeImage * 3) / 2;
} // Realloc the buffer so that it can hold all the bits
dwLen += bi.biSizeImage;
if (handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE))
hDIB = handle;
else{
GlobalFree(hDIB); // Reselect the original palette
SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
} // Get the bitmap bits
lpbi = (LPBITMAPINFOHEADER)hDIB; // FINALLY get the DIB
BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),
0L, // Start scan line
(DWORD)bi.biHeight, // # of scan lines
(LPBYTE)lpbi  // address for bitmap bits
+ (bi.biSize + nColors * sizeof(RGBQUAD)),
(LPBITMAPINFO)lpbi, // address of bitmapinfo
(DWORD)DIB_RGB_COLORS); // Use RGB for color table if( !bGotBits )
{
GlobalFree(hDIB);

SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
} SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return hDIB;
}
// WriteDIB - Writes a DIB to file
// Returns - TRUE on success
// szFile - Name of file to write to
// hDIB - Handle of the DIB
BOOL WriteDIB( LPTSTR szFile, HANDLE hDIB)
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi; if (!hDIB)
return FALSE; CFile file;
if( !file.Open( szFile, CFile::modeWrite and CFile::modeCreate) )
return FALSE; lpbi = (LPBITMAPINFOHEADER)hDIB; int nColors = 1 << lpbi->biBitCount; // Fill in the fields of the file header 
hdr.bfType = ((WORD) ('M' << 8)  and  'B'); // is always "BM"
hdr.bfSize = GlobalSize (hDIB) + sizeof( hdr );
hdr.bfReserved1  = 0;
hdr.bfReserved2  = 0;
hdr.bfOffBits = (DWORD) (sizeof( hdr ) + lpbi->biSize +
nColors * sizeof(RGBQUAD)); // Write the file header 
file.Write( &hdr, sizeof(hdr) ); // Write the DIB header and the bits 
file.Write( lpbi, GlobalSize(hDIB) ); return TRUE;
}

解决方案 »

  1.   

    如果只是想保存24位位图的话,我有一个比较简单的例子:在这之前,你应该有了一个位图句柄(你不会没有位图句柄吧,你没有的话
    我可以给你的,你不说我怎么会知道呢,不可能你向我要我不给你,而你不
    向我要而我偏要给你。你不会向我要吧?)。  BITMAP bmp;
      DWORD FileSize;//文件大小
      BYTE* pbyFileBuf;//缓冲区
      BITMAPFILEHEADER bmh;//
      PBITMAPINFO pbmi;
     
      ::GetObject(m_hBitmap,sizeof(bmp),&bmp);
     
      FileSize=sizeof(bmh)+sizeof(BITMAPINFOHEADER)+bmp.bmHeight*bmp.bmWidthBytes;
      pbyFileBuf=new BYTE[FileSize];
      //Only save 24bits bmp file
      pbmi=(PBITMAPINFO)LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER));
     
      bmh.bfType=0x4d42;//((DWORD)'M'<<8)+'B';
      bmh.bfReserved1=0;
      bmh.bfReserved2=0;
      bmh.bfSize=FileSize;
      bmh.bfOffBits=sizeof(BITMAPINFOHEADER)+sizeof(bmh);
     
      pbmi->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
      pbmi->bmiHeader.biWidth=bmp.bmWidth;
      pbmi->bmiHeader.biHeight=bmp.bmHeight;
      pbmi->bmiHeader.biPlanes=1;
      pbmi->bmiHeader.biBitCount=bmp.bmBitsPixel;
      pbmi->bmiHeader.biCompression=BI_RGB;
      pbmi->bmiHeader.biSizeImage=0;
      pbmi->bmiHeader.biXPelsPerMeter=0;
      pbmi->bmiHeader.biYPelsPerMeter=0;
      pbmi->bmiHeader.biClrUsed=0;
      pbmi->bmiHeader.biClrImportant=0;
     
      HDC hMemDC=CreateCompatibleDC(NULL);
      CreateCompatibleBitmap(hMemDC,800,600);
      HBITMAP hOldBitmap=(HBITMAP)SelectObject(hMemDC,m_hBitmap);
         
      BYTE* pbyBuf1=(BYTE*)((LPSTR)pbyFileBuf+sizeof(bmh));
      BYTE* pbyBuf2=(BYTE*)((LPSTR)pbyFileBuf+sizeof(bmh)+sizeof(BITMAPINFOHEADER));
      memcpy(pbyFileBuf,&bmh,sizeof(bmh));
      memcpy(pbyBuf1,pbmi,sizeof(BITMAPINFOHEADER));
      GetDIBits(hMemDC,m_hBitmap,0,bmp.bmHeight,pbyBuf2,pbmi,DIB_RGB_COLORS);
     
      CFile file(FileName,CFile::modeCreate and CFile::modeWrite);
      file.WriteHuge(pbyFileBuf,FileSize);
      file.Close();
    很不好意思,其中有的部分只是简单的数字,而不是根据实际位图的大小。
    若还有不懂的地方,请E-mail me!
      

  2.   

    将内存位图保存为文件,MSDN上有现成例子Platform\Graphics and...\GDI\Bitmaps\Using Bitmaps\Storing an Image我机器上的mk地址: mk:@MSITStore:D:\MSDNSE~1\MSDN\GDI.chm::/devdoc/live/pdgrmm/bitmaps_7zfp.htm
    The following example code defines a function that allocates memory for and initializes members within a BITMAPINFOHEADER structure. PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)

        BITMAP bmp; 
        PBITMAPINFO pbmi; 
        WORD    cClrBits;     // Retrieve the bitmap's 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 the 24-bit-per-pixel format.      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. 
        pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8 
                                      * pbmi->bmiHeader.biHeight 
    cClrBits; 
    // Set biClrImportant to 0, indicating that all of the 
        // device colors are important. 
         pbmi->bmiHeader.biClrImportant = 0; 
         return pbmi; 
     } 
     
    The following example code defines a function that initializes the remaining structures, retrieves the array of palette indices, opens the file, copies the data, and closes the file. 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  and  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);
    }