bmp保存问题

0="0" 2010-04-27 07:39:31

CFileDialog fdlg(false,NULL,NULL,OFN_HIDEREADONLY| OFN_OVERWRITEPROMPT,_T("位图文件(*.bmp)|*.bmp|"),NULL);
if(fdlg.DoModal()!=IDOK)
return;

CString str;
str=fdlg.GetFileName()+_T(".bmp");

int iWidth=500;
int iHeight=500;
int iPixel=16;
LPBITMAPINFO lpbmih=new BITMAPINFO;
lpbmih->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
lpbmih->bmiHeader.biWidth=iWidth;
lpbmih->bmiHeader.biHeight=iHeight;
lpbmih->bmiHeader.biPlanes=1;
lpbmih->bmiHeader.biBitCount=iPixel;
lpbmih->bmiHeader.biCompression=BI_RGB;
lpbmih->bmiHeader.biSizeImage=0;
lpbmih->bmiHeader.biXPelsPerMeter=0;
lpbmih->bmiHeader.biYPelsPerMeter=0;
lpbmih->bmiHeader.biClrUsed=0;
lpbmih->bmiHeader.biClrImportant=0;

HDC hdc,hdcMem;
HBITMAP hBitmap=NULL;
CBitmap *pBitmap=NULL;
CDC *pMemDC=NULL;
BYTE *pBits;
hdc=CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL);
hdcMem=CreateCompatibleDC(hdc);
hBitmap=CreateDIBitmap(hdcMem,(BITMAPINFOHEADER *)lpbmih,DIB_PAL_COLORS,(void**)&pBits,NULL,0);
pBitmap=new CBitmap;
pBitmap->Attach(hBitmap);
pMemDC=new CDC;
pMemDC->Attach(hdcMem);
pMemDC->SelectObject(pBitmap);

CRect rc(0,0,iWidth,iHeight);
pMemDC->SetBkMode(TRANSPARENT);
///添加自绘图
/////////
CBrush brushCtl;
brushCtl.CreateSolidBrush(RGB(255,255,205));
pDC->Rectangle(rcClient);
pDC->FillRect(rcClient,&brushCtl) ;
brushCtl.DeleteObject();

CPen cpen,*pPen;
cpen.CreatePen(PS_SOLID,2,RGB(0,0,255));
pPen=pDC->SelectObject(&cpen);

pDC->MoveTo(10,10);
pDC->LineTo(50,50);
/////////
//保存到文件并创建
BITMAPFILEHEADER bmfh;
ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER));
bmfh.bfType=(WORD)(('M'<<8)|'B');
bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
bmfh.bfSize=bmfh.bfOffBits+(iWidth+iHeight)*iPixel/8;


int iBMPBytes=iWidth*iHeight*iPixel/8;

CFile file;
if(file.Open(filename,CFile::modeWrite|CFile::modeCreate))
{
file.Write(&bmfh,sizeof(BITMAPFILEHEADER));
file.Write(&(lpbmih->bmiHeader),sizeof(BITMAPINFOHEADER));
file.Write(pBits,iBMPBytes);
file.Close();
}
pMemDC->DeleteDC();
delete pMemDC;pMemDC=NULL;
delete pBitmap;pBitmap=NULL;
delete lpbmih;lpbmih=NULL;

保存下来的bmp文件无法打开.显示"没有足够的内存或资源..."
请兄弟们帮助.解决
...全文
186 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
快乐鹦鹉 2010-04-29
  • 打赏
  • 举报
回复
不废话了,直接贴一个现成的函数,自己比对吧。
BOOL  CPetrelProView::HBITMAP2Bmp(HBITMAP hBitmap, const CString &strFileName)       
{
if(hBitmap == NULL)
return FALSE;

HDC hDC;
//当前分辨率下每象素所占字节数
int iBits;
//位图中每象素所占字节数
WORD wBitCount;
//定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0;
//位图属性结构
BITMAP Bitmap;
//位图文件头结构
BITMAPFILEHEADER bmfHdr;
//位图信息头结构
BITMAPINFOHEADER bi;
//指向位图信息头结构
LPBITMAPINFOHEADER lpbi;
//定义文件,分配内存句柄,调色板句柄
HANDLE fh, hDib, hPal,hOldPal=NULL;

//计算位图文件每个像素所占字节数
hDC = CreateDC("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;

//pBmp->GetBitmap(&Bitmap);
GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.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 = 0;

dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;

//为位图内容分配内存
hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;

// 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}

// 获取该调色板下新的像素值
// pBmp->GetBitmapBits(dwBmBitsSize,lpbi);
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);

//恢复调色板
if (hOldPal)
{
::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}

//创建位图文件
fh = CreateFile(strFileName, 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;


}
快乐鹦鹉 2010-04-29
  • 打赏
  • 举报
回复
bmfh.bfSize=bmfh.bfOffBits+(iWidth+iHeight)*iPixel/8;


int iBMPBytes=(iWidth*iHeight*iPixel+31)/32;

pBits=new BYTE[iWidth*iHeight];
============
1.为什么这里pBits又new呢?前面不白干了?
2.bfSize的算法中,iWidth+iHeight干什么用?不是乘法?
lili0920 2010-04-29
  • 打赏
  • 举报
回复
BITMAPFILEHEADER bmfh;
ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER));
bmfh.bfType=(WORD)(('M'<<8)|'B');
bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+数据长度;
bmfh.bfSize=bmfh.bfOffBits+(iWidth+iHeight)*iPixel/8;
尹成 2010-04-29
  • 打赏
  • 举报
回复
帖子都沉底了,帮楼主顶下
尹成 2010-04-28
  • 打赏
  • 举报
回复
3#说得对,
把int iBMPBytes=iWidth*iHeight*iPixel/8;
改为;int iBMPBytes=(iWidth*iHeight*iPixel+31)/32;
就可以了
wendysen 2010-04-28
  • 打赏
  • 举报
回复
再提醒你一下,如果是生成适合保存的图片,要生成DIB图像,很多函数都是生成DDB图像, 看上去一样,但遇到什么操作的时候还是不一样的
0="0" 2010-04-28
  • 打赏
  • 举报
回复
补充一下..
我把DC内绘的图在picture控件中输出是正常的啊..只是保存的图片有问题.
求兄弟们帮我啊.
快乐鹦鹉 2010-04-28
  • 打赏
  • 举报
回复
把修改后的代码再贴出来看看
快乐鹦鹉 2010-04-28
  • 打赏
  • 举报
回复
加31是为了保证哪怕前面的值是一位长度,也可以保证最后的结果是四个字节的倍数
(1+31)/32就是四字节了。
0="0" 2010-04-28
  • 打赏
  • 举报
回复

void CdeletDlg::save(CString filename)
{
int iWidth=500;
int iHeight=500;
int iPixel=16;
LPBITMAPINFO lpbmih=new BITMAPINFO;
lpbmih->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
lpbmih->bmiHeader.biWidth=iWidth;
lpbmih->bmiHeader.biHeight=iHeight;
lpbmih->bmiHeader.biPlanes=1;
lpbmih->bmiHeader.biBitCount=iPixel;
lpbmih->bmiHeader.biCompression=BI_RGB;
lpbmih->bmiHeader.biSizeImage=iWidth*iHeight;
lpbmih->bmiHeader.biXPelsPerMeter=0;
lpbmih->bmiHeader.biYPelsPerMeter=0;
lpbmih->bmiHeader.biClrUsed=0;
lpbmih->bmiHeader.biClrImportant=0;

HDC hdc,hdcMem;
HBITMAP hBitmap=NULL;
CBitmap *pBitmap=NULL;
CDC *pMemDC=NULL;
BYTE *pBits;
hdc=CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL);
hdcMem=CreateCompatibleDC(hdc);
hBitmap=CreateDIBitmap(hdcMem,(BITMAPINFOHEADER *)lpbmih,DIB_PAL_COLORS,(void**)&pBits,NULL,0);
pBitmap=new CBitmap;
pBitmap->Attach(hBitmap);
pMemDC=new CDC;
pMemDC->Attach(hdcMem);
pMemDC->SelectObject(pBitmap);

CRect rc(0,0,iWidth,iHeight);
pMemDC->SetBkMode(TRANSPARENT);
///添加自绘图
/////////
DrawCurve(pMemDC,rc);
/////////
//保存到文件并创建
BITMAPFILEHEADER bmfh;
ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER));
bmfh.bfType=(WORD)(('M'<<8)|'B');
bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
bmfh.bfSize=bmfh.bfOffBits+(iWidth+iHeight)*iPixel/8;


int iBMPBytes=(iWidth*iHeight*iPixel+31)/32;

pBits=new BYTE[iWidth*iHeight];
CFile file;
if(file.Open(filename,CFile::modeWrite|CFile::modeCreate))
{
file.Write(&bmfh,sizeof(BITMAPFILEHEADER));
file.Write(&(lpbmih->bmiHeader),sizeof(BITMAPINFOHEADER));
file.Write(pBits,iBMPBytes);
file.Flush();
file.Close();
}
pMemDC->DeleteDC();
delete pMemDC;pMemDC=NULL;
delete pBitmap;pBitmap=NULL;
delete lpbmih;lpbmih=NULL;
delete[]pBits;
}

void CdeletDlg::OnBnClickedBtnSave()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog fdlg(false,NULL,NULL,OFN_HIDEREADONLY| OFN_OVERWRITEPROMPT,_T("位图文件(*.bmp)|*.bmp|"),NULL);
if(fdlg.DoModal()!=IDOK)
return;

CString str;
str=fdlg.GetFileName()+_T(".bmp");
save(str);
}

void CdeletDlg::DrawCurve(CDC* pDC, CRect rcClient)
{
/* CBrush brush1,brush2;
brush1.CreateSolidBrush(RGB(255,255,255));
brush2.CreateSolidBrush(RGB(0,0,0));
pDC->Rectangle(rcClient);
CRect rectwhite,rectblack;
bool bl=false;

for(int j=0;j<m_intY;j++)
for(int i=0;i<m_intX;i++)
{
CRect rt(i*m_width/m_intX,m_height/m_intY*j,i*m_width/m_intX+m_width/m_intX,j*m_height/m_intY+m_height/m_intY);
if(bl==true)
{
rectblack=rt;
pDC->FillRect(&rectblack,&brush2);
}
if(bl==false)
{
rectwhite=rt;
pDC->FillRect(&rectblack,&brush1);
}
bl=!bl;
}
brush1.DeleteObject();
brush2.DeleteObject();
*/
//页面背景色
CBrush brushCtl;
brushCtl.CreateSolidBrush(RGB(255,255,205));
pDC->Rectangle(rcClient);
pDC->FillRect(rcClient,&brushCtl) ;
brushCtl.DeleteObject();

CPen cpen,*pPen;
cpen.CreatePen(PS_SOLID,2,RGB(0,0,255));
pPen=pDC->SelectObject(&cpen);

pDC->MoveTo(10,10);
pDC->LineTo(500,500);

就是这个啊.输出来的是白色的....没有线...
清风盛开 2010-04-28
  • 打赏
  • 举报
回复
同意楼上
qianhe_he 2010-04-28
  • 打赏
  • 举报
回复
学习
0="0" 2010-04-27
  • 打赏
  • 举报
回复
加31是什么意思啊...现在能绘了,绘出来的却是一张空白的...
Eleven 2010-04-27
  • 打赏
  • 举报
回复
try
{
CFile file;
file.Open(szPath, CFile::modeCreate | CFile::typeBinary | CFile::modeWrite);

BITMAPINFOHEADER bih = {0};
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biBitCount = bmp.bmBitsPixel;
bih.biCompression = BI_RGB;
bih.biHeight = bmp.bmHeight;
bih.biPlanes = 1;
bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;
bih.biWidth = bmp.bmWidth;

BITMAPFILEHEADER bfh = {0};
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;
bfh.bfType = (WORD)0x4d42;
file.Write(&bfh, sizeof(BITMAPFILEHEADER));
file.Write(&bih, sizeof(BITMAPINFOHEADER));
BYTE* pByte = new BYTE[bmp.bmWidthBytes * bmp.bmHeight];
GetDIBits(memDC.m_hDC, (HBITMAP)bitmap.m_hObject, 0, nHeight, pByte, (LPBITMAPINFO)&bih, DIB_RGB_COLORS);
file.Write(pByte, bmp.bmWidthBytes * bmp.bmHeight);
file.Flush();
file.Close();
delete[] pByte;
}
catch (CFileException* e)
{
e->ReportError();
e->Delete();
}
wendysen 2010-04-27
  • 打赏
  • 举报
回复
bmfh.bfSize=bmfh.bfOffBits+(iWidth+iHeight)*iPixel/8;
这里错了,答案就是楼上的所说
快乐鹦鹉 2010-04-27
  • 打赏
  • 举报
回复
int iBMPBytes=iWidth*iHeight*iPixel/8;
改为;int iBMPBytes=(iWidth*iHeight*iPixel+31)/32;
快乐鹦鹉 2010-04-27
  • 打赏
  • 举报
回复
bmfh.bfSize=bmfh.bfOffBits+(iWidth+iHeight)*iPixel/8;
这个大小的计算方法有点问题。位图是四字节对齐的,并不直接等于宽度和高度的乘积。
0="0" 2010-04-27
  • 打赏
  • 举报
回复
自己顶一个

16,467

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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