如何将一个已有的bmp图片---GDI+中的Bitmap*变量,保存到自己定义的file文件中?

realbluce 2008-10-25 02:51:13
我需要自己封装定义一个文件,里面有其他信息,也有bmp图片文件,都封装在一个自定义的文件里,但是在将BMP图片也用file.write()的时候却出问题了.
我将图片的一些信息提取出来,分别保存,然后想再用的时候,也用file.read()的方法,分别再把图片的各个必要信息读取出来,最后用Bitmap::FromaBITMAPINFO()的方法把图片构造出来,可是发现重新构造出来的图片却是一片白色(也像是灰色的),我把代码帖出来,不要怀疑代码的编译,都是正确的,应该是方法步骤上有些问题,还请哪位达人给予赐教,帮忙解决.


这是保存的部分:
Bitmap* pTempPic = temp->m_pPic;//pTempPic 就是要保存的图片,图片是正确的,可以正确显示.

HDC hDisplay = CreateDC(_T("DISPLAY"), NULL, NULL, NULL); //首先得到整个屏幕的句柄
_ASSERT(NULL!=hDisplay);


int nBits = GetBitsNumPerPixel(pTempPic); //每个象素的位数,调用下面的自定义函数
int nWidth = pTempPic->GetWidth();//GDI+里的Bitmap方法.
int nHeight = pTempPic->GetHeight();//GDI+里的Bitmap方法.
int nXResolution = pTempPic->GetHorizontalResolution();//GDI+里的Bitmap方法.
int nYResolution = pTempPic->GetVerticalResolution();//GDI+里的Bitmap方法.

DWORD dwLineBits = GetLineBits(nBits, nWidth); //每行字节数,调用下面的自定义函数

//下面分配内存
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);

Color clr;
pTempPic->GetPixel(0,0,&clr);

HBITMAP hBmp;
pTempPic->GetHBITMAP(clr,&hBmp);

int nLines = GetDIBits(hDisplay, hBmp, 0, pTempPic->GetHeight(),
pBits, (BITMAPINFO*)pInfoHeader, DIB_RGB_COLORS);

fl.Write(&nWidth,sizeof(nWidth));
fl.Write(&nHeight,sizeof(nHeight));
fl.Write(&nBits,sizeof(nBits));
fl.Write(&nXResolution,sizeof(nXResolution));
fl.Write(&nYResolution,sizeof(nYResolution));
fl.Write(&dwFileSize,sizeof(dwFileSize));
fl.Write(pBits,dwFileSize);

相关调用的函数如下:
DWORD XXXXX::GetLineBits(int nBits, int nWidth)
{
DWORD dwLineBits = 0; //每行字节数

switch (nBits)
{
case 1:
dwLineBits = nWidth/8;
break;
case 8:
dwLineBits = nWidth;
break;
case 16:
dwLineBits = nWidth*2;
break;
case 24:
// dwLineBits = (nWidth+1)*3-((nWidth+1)*3)%4;
dwLineBits = nWidth*3;
break;
case 32:
dwLineBits = nWidth*4;
break;
case 64:
dwLineBits = nWidth*8;
break;
default:
//其他情况(这里产生资源泄漏,只是例子,所以没管)
MessageBox(NULL, _T("不支持该格式!"), _T("不支持!"), MB_OK);
break;
}

return dwLineBits;
}

int XXXXX::GetBitsNumPerPixel(Bitmap* pBitmap)
{
_ASSERT(pBitmap != NULL);

int nBitsPerPixel = 0;

PixelFormat pixelFormat = pBitmap->GetPixelFormat();

switch (pixelFormat)
{
case PixelFormat1bppIndexed :
nBitsPerPixel = 1;
break;
case PixelFormat4bppIndexed :
nBitsPerPixel = 4;
break;
case PixelFormat8bppIndexed :
nBitsPerPixel = 8;
break;
case PixelFormat16bppARGB1555 :
case PixelFormat16bppGrayScale :
case PixelFormat16bppRGB555 :
case PixelFormat16bppRGB565 :
nBitsPerPixel = 16;
break;
case PixelFormat24bppRGB :
nBitsPerPixel = 24;
break;
case PixelFormat32bppARGB :
case PixelFormat32bppPARGB :
case PixelFormat32bppRGB :
nBitsPerPixel = 32;
break;
case PixelFormat48bppRGB :
nBitsPerPixel = 48;
break;
case PixelFormat64bppARGB :
case PixelFormat64bppPARGB :
nBitsPerPixel = 64;
break;
}

return nBitsPerPixel;
}

最后是读取并重新构造图片的部分:

int nWidth;
int nHeight;
int nBits;
int nXResolution;
int nYResolution;
DWORD dwFileSize;

fl.Read(&nWidth,sizeof(int));
fl.Read(&nHeight,sizeof(int));
fl.Read(&nBits,sizeof(int));
fl.Read(&nXResolution,sizeof(int));
fl.Read(&nYResolution,sizeof(int));
fl.Read(&dwFileSize,sizeof(DWORD));

BYTE* pBits = new BYTE[dwFileSize+1];
fl.Read(pBits,dwFileSize);

BYTE * pMem = (BYTE *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, dwFileSize);

if (NULL == pMem)
{
return 0;
}

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

//下面初始化
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 = 0;
pInfoHeader->biXPelsPerMeter = nXResolution;
pInfoHeader->biYPelsPerMeter = nYResolution;
pInfoHeader->biClrUsed = 0;
pInfoHeader->biClrImportant = 0;

pUnit.m_pPic = Gdiplus::Bitmap::FromBITMAPINFO((BITMAPINFO *)pInfoHeader,(VOID*)pBits;//能正确构造图片,但是是白的.



再次谢谢各位好心的帮忙者了.
...全文
375 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
realbluce 2008-10-26
  • 打赏
  • 举报
回复
顺便问一句,GetDIBits实际什么都没有get出来,那么有没有什么办法能够得到GDI+中用于构造Bitmap对象的Dib位图数据呢?
我一直是想用GDI+中的Bitmap::FromBITMAPINFO( const BITMAPINFO *gdiBitmapInfo,VOID *gdiBitmapData)的方法重新构造图片,所以保存图片的时候,也想按其中的两个参数提取已有图片信息保存,重构的时候再按该方法恢复.
现在的问题是该方法中的这两个参数,如何获取,才是正确的?
lyserver 2008-10-26
  • 打赏
  • 举报
回复
俺在博客里写了一篇如何正确释放资源里的图片资源到磁盘文件,里面有位图分析的代码,LZ不妨看一看。
wltg2001 2008-10-26
  • 打赏
  • 举报
回复
GDI+我不明白,不过将一个Bitmap对象保存成位图文件我倒是会,我博客里有一个源代码
realbluce 2008-10-25
  • 打赏
  • 举报
回复
我在程序里面保存宽度,高度等信息也是为了在重新读取的时候,再次构造BITMAPINFO等信息.
realbluce 2008-10-25
  • 打赏
  • 举报
回复
我这里要保存的是DIB,而不是DDB,也需要BITMAPINFO,和它的图元信息,所以还请各位多多帮忙.
wltg2001 2008-10-25
  • 打赏
  • 举报
回复
太长了,看不出来什么,不过为什么要定义这个函数呢:DWORD dwLineBits = GetLineBits(nBits, nWidth); //每行字节数,调用下面的自定义函数
一行的字节数在BITMAP结构中不是有一个成员:bmWidthBytes指定了一行的字节数吗?而且你的实现代码也有问题,考虑到数据对齐的原因,一行所占的字节数并不一定等于宽度乘以色深
hbdycnm 2008-10-25
  • 打赏
  • 举报
回复
BMP分为ddb和dib。
你用于显示的是ddb,是没办法存起来的。
可以用image试试,看能存否!

GetDIBits实际什么都没有get出来。

19,464

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧