我已经实现将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;
}
我提取的数据是经得起检验的哦,查看里面的各项信息都和原来的一样.
拜托各位了,高手们!
现在的问题是,我在读取自己保存的文件后,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;
}
我提取的数据是经得起检验的哦,查看里面的各项信息都和原来的一样.
拜托各位了,高手们!
读取部分:Bitmap("my.bmp"); 有什么区别??
http://www.vckbase.com/document/viewdoc/?id=446
以上实例中都有用到流操作,学习一下会有不一样的思路。