我已经实现将Bitmap*类型变量保存成自己的的二进制文件了,经过验证保存功能是正确的,BMP的各个部分都有,文件大小和原图片相符,4字节对齐问题也有相应处理,总之一句话:Bitmap*类型变量按照我的代码准确而正确地保存成了CFile文件.
   现在的问题是,我在读取自己保存的文件后,BMP的各个部分数据也都是正确的,可我却怎么也无法将他们重新构造为可以显示的Bitmap*.郁闷啊!特向各位高手中的高高手求助!
   我把主要代码贴下:
   1,文件保存过程,(验证部分也写下了,是将内存中数据换了个路径保存成BMP图片)       Bitmap* pTempPic = pUnit->m_pPic;//这就是原来的图片//
UINT nSize = pTempPic->GetPaletteSize();

ColorPalette* palette = (ColorPalette*)malloc(nSize);
pTempPic->GetPalette(palette, nSize);//GDI+提供的提取颜色信息的方法.

fl.Write(&nSize,sizeof(nSize));
fl.Write(palette,nSize);

int nBits = GetBitsNumPerPixel(pTempPic);  //GDI+提供的提取每个象素的位数的方法.
int nWidth = pTempPic->GetWidth();                      //GDI+提供的.....
int nHeight = pTempPic->GetHeight();                    //GDI+提供的.....
int nXResolution = pTempPic->GetHorizontalResolution(); //GDI+提供的....
int nYResolution = pTempPic->GetVerticalResolution();   //GDI+提供的....

DWORD dwLineBits = GetLineBits(nBits, nWidth);//自己写的方法,每行字节数,里面有4字节对齐的处理.

DWORD dwBitsCount = dwLineBits * nHeight;
DWORD dwFileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBitsCount;  BYTE * pMem = (BYTE *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, dwFileSize); //分配内存 

if (NULL == pMem) 

  return; 


BITMAPFILEHEADER* pBMPHeader = (BITMAPFILEHEADER*)pMem; 
BITMAPINFOHEADER* pInfoHeader = (BITMAPINFOHEADER*)((BYTE *)pBMPHeader + sizeof(BITMAPFILEHEADER)); 
BYTE* pBits = (BYTE*)pInfoHeader + sizeof(BITMAPINFOHEADER);

pBMPHeader->bfType = ('M'<<8) | 'B'; 
pBMPHeader->bfSize = dwFileSize; 
pBMPHeader->bfReserved1 = 0; 
pBMPHeader->bfReserved2 = 0; 
pBMPHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 

pInfoHeader->biSize = sizeof(BITMAPINFOHEADER); 
pInfoHeader->biWidth = nWidth; 
pInfoHeader->biHeight = nHeight; 
pInfoHeader->biPlanes = 1;  //调色板数 
pInfoHeader->biBitCount = nBits; 
pInfoHeader->biCompression = BI_RGB; 
pInfoHeader->biSizeImage = dwBitsCount; 
pInfoHeader->biXPelsPerMeter = nXResolution; 
pInfoHeader->biYPelsPerMeter = nYResolution; 
pInfoHeader->biClrUsed = palette->Count; 
pInfoHeader->biClrImportant = 0;  HDC hDisplay = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);   
       _ASSERT(NULL != hDisplay);    Graphics gs(hDisplay);
gs.DrawImage((Image*)pTempPic, PointF(0.0,0.0));                  //
                                                                          //
HDC hMemDc = CreateCompatibleDC(hDisplay);                        //
_ASSERT(NULL != hMemDc);                                          //
                                                                      //
        HBITMAP hBmp = CreateCompatibleBitmap(hDisplay, nWidth, nHeight); //通过CompatibleBitmap ,将原来的图片信息转换成HBITMAP 
HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDc, hBmp);            //
                                                                          //
BOOL blnReturnValue = BitBlt(hMemDc, 0, 0, nWidth, nHeight, hDisplay, 0, 0, SRCCOPY); 
       _ASSERT(0 != blnReturnValue); 
hBmp = (HBITMAP)SelectObject(hMemDc, hOldBmp);   
_ASSERT(NULL != (DWORD)hBmp || GDI_ERROR != (DWORD)hBmp);  DeleteDC(hMemDc);   
hMemDc = NULL; int nLines = GetDIBits(hDisplay, hBmp, 0, pTempPic->GetHeight(), //因为GetDIBits这个函数只能从CompatibleBitmap里面提取DIB信息. 
pBits, (BITMAPINFO*)pInfoHeader, DIB_RGB_COLORS); 

DeleteObject(hBmp);   
hBmp = NULL;

DeleteObject(hOldBmp);   
        hOldBmp = NULL;

DeleteObject(hDisplay);   
hDisplay = NULL;
//////////////////////////////////////////////////////////////////
//查看存储文件是否正确// 在上一级目录存储原图片//
CString strTemp = strTempPath;//原路径
int nIndex = strTemp.ReverseFind('\\');

CString strEnd = strTemp.Right(strTemp.GetLength() - nIndex + 1);
strTemp = strTemp.Left(nIndex - 1); nIndex = strTemp.ReverseFind('\\');
strTemp = strTemp.Left(nIndex - 1); strTemp += strEnd; HANDLE hFile = CreateFile((LPCTSTR)strTemp, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); 
if (NULL == hFile  || INVALID_HANDLE_VALUE == hFile) 

MessageBox(NULL, _T("文件已经存在!"), _T("错误!"), MB_OK); 
return; 


DWORD dwWriteCount = 0; 
if (!WriteFile(hFile, (void  *)pBMPHeader, dwFileSize, &dwWriteCount, NULL)) 

MessageBox(NULL,  _T("写入文件失败!"),  _T("错误"),  MB_OK | MB_ICONEXCLAMATION); 
CloseHandle(hFile); 
return; 

//查看存储文件是否正确//结果证明这样的保存是正确的^_^
//////////////////////////////////////////////////////////////////////////////////
fl.Write(&dwFileSize,sizeof(dwFileSize)); fl.Write((LPVOID) pBMPHeader, dwFileSize); free(palette); GlobalFree(pMem);主要的代码就是这些了,文件提取的部分还是按保存的顺序来,能够正确地提取文件中的保存信息,还请高手们教教我,如何把这些信息重新构造成Bitmap*,如果实在不行,退而求其次,能保存成正确显示的CBitmap,或者HBITMAP,也不胜感激.算了,我还是把数据提取部分的代码也贴出来吧,反正也没几行.                UINT nSize;
fl.Read(&nSize,sizeof(UINT));

ColorPalette* palette = (ColorPalette*)malloc(nSize);//颜色信息应该是派不上用场的,一般情况下都是24位以上的,可以在次暂时忽略
fl.Read(palette,nSize);

DWORD dwFileSize;

fl.Read(&dwFileSize,sizeof(DWORD));
BYTE * pMem = (BYTE *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, dwFileSize); 

if (NULL == pMem) 

return 0; 


BITMAPFILEHEADER* pBMPHeader = (BITMAPFILEHEADER*)pMem; fl.Read((LPVOID) pBMPHeader, dwFileSize);
 
BITMAPINFOHEADER* pInfoHeader = (BITMAPINFOHEADER*)((BYTE *)pBMPHeader + sizeof(BITMAPFILEHEADER));
BYTE* pBits = (BYTE*)pInfoHeader + sizeof(BITMAPINFOHEADER); if(pBMPHeader->bfType != 0x4d42) 
{
break;
}
我提取的数据是经得起检验的哦,查看里面的各项信息都和原来的一样.
拜托各位了,高手们!

解决方案 »

  1.   

    楼上说的方法我都试过,但是不行,如果楼上的大侠有时间的话,可以把我的代码调试一下,你就知道了,GDI+中的方法我试过不少,可能是我对参数的要求还了解得不够透彻,所以都没成功过,构造出来的Bitmap*类型变量,显示的时候,要么是全黑一片,要么是一片全白,甚至有的还在显示的时候会跑出汇编的界面,显示某一行用于显示图片的代码有错误,所以还请教有这方面经验的高手,不吝赐教.多谢了.
      

  2.   

    保存部分:感觉就是标准的位图保存操作,GDI+一个函数就可以搞定啊。
    读取部分:Bitmap("my.bmp"); 有什么区别??
      

  3.   

    各位大哥,我是把许多BMP图片和其他的许多信息保存在一个自己定义的CFile文件里的,这个功能已经实现了,现在的问题是,重新读取这个CFile文件后,可以获取到每个BMP图片的各部分信息,比如fileheader ,bitmapinfoheader,pbits等等,然后再用这些信息,重新构造一个Bitmap*类型的变量,让这个重构的内存中的图片,和原来一样,可以正确显示出来.而不是在硬盘的某个位置,用路径的方式再读取.现在的问题是,我把这些图片的各部分信息,如何重构一个图片,重构成Bitmap*类型的变量,我做不好.我试了很多方法,都不能正确显示,重构的图片应该不正确.
      

  4.   

    GDI+中有很多对象都有数据流,即可以将对象数据输入/输出到内存中,你可以查查这方面的资料,根本不用解析文件结构,另外它还支持多种图像格式。
      

  5.   

    http://www.vckbase.net/document/viewdoc/?id=451
    http://www.vckbase.com/document/viewdoc/?id=446
    以上实例中都有用到流操作,学习一下会有不一样的思路。