我写的BMP位图打开读取数据与保存函数 为什么最后得到的BMP图片绘图失败?

superbblue 2008-10-28 04:45:43
这是我写的BMP位图读取函数
BYTE * readImageDatabmp(LPSTR strFileName,int * pwidth,int * pheight)
{
int filesize;
FILE * pFile;
struct tagBITMAPFILEHEADER bmpFileHdr;
struct tagBITMAPINFOHEADER bmpInfoHdr;
struct tagRGBTRIPLE rgb;
BYTE * DataBuf;
long BufSize;
int offset;
if((pFile=fopen(strFileName,"rb"))==NULL) //打开图象文件
return NULL;

fseek( pFile,0,SEEK_SET); //找到文件头
fread(&bmpFileHdr,sizeof(tagBITMAPFILEHEADER),1, pFile); //读取文件头
filesize=bmpFileHdr.bfSize;
if(bmpFileHdr.bfType==0x4d42) //判断是否为BMP图片
{
fread(&bmpInfoHdr,sizeof(tagBITMAPINFOHEADER),1, pFile); //读取信息头
fread(&rgb,sizeof(tagRGBTRIPLE),1,pFile);
Bps=bmpInfoHdr.biBitCount;
*pwidth=bmpInfoHdr.biWidth; //文件的宽度(以像素为单位)
*pheight=bmpInfoHdr.biHeight; //文件的长度(以像素为单位)
offset=sizeof(bmpFileHdr)+sizeof(bmpInfoHdr)+(int)pow(2,Bps)*sizeof(rgb);

BufSize=(*pwidth)*(*pheight)/(8/Bps);
DataBuf=new BYTE[BufSize];
fseek( pFile,offset,SEEK_SET);//指针指到位图像素值起始位置
fread(&DataBuf,sizeof(BYTE),BufSize, pFile);
fclose(pFile); //关闭图象文件
return DataBuf;
}
else
return NULL;
}


这是我写的BMP位图保存函数
int different::saveBmp(LPSTR bmpFile,int width,int height,BYTE* Data,int bmpBps)
{
struct tagBITMAPFILEHEADER bmpFileHdr;
struct tagBITMAPINFOHEADER bmpInfoHdr;
struct tagRGBQUAD rgb;
//FileHeader
bmpFileHdr.bfType=0x4D42;
bmpFileHdr.bfSize=(width/(8/bmpBps))*height+sizeof(bmpFileHdr)+sizeof(bmpInfoHdr)+(int)pow(2,bmpBps)*sizeof(rgb);
bmpFileHdr.bfReserved1=0;
bmpFileHdr.bfReserved2=0;
bmpFileHdr.bfOffBits=(DWORD)(sizeof(bmpFileHdr)+sizeof(bmpInfoHdr)+(int)pow(2,bmpBps)*sizeof(rgb));

//
bmpInfoHdr.biSize=sizeof(BITMAPINFOHEADER);
bmpInfoHdr.biWidth=width;
bmpInfoHdr.biHeight=height;
bmpInfoHdr.biPlanes=1;
bmpInfoHdr.biBitCount=bmpBps;
bmpInfoHdr.biCompression=0;
bmpInfoHdr.biSizeImage=0;
bmpInfoHdr.biXPelsPerMeter=200;
bmpInfoHdr.biYPelsPerMeter=200;
bmpInfoHdr.biClrUsed=(int)pow(2,bmpBps);
bmpInfoHdr.biClrImportant=0;

FILE* BmpOut=fopen(bmpFile,"wb");
fwrite(&bmpFileHdr,sizeof(tagBITMAPFILEHEADER),1,BmpOut); //写文件头
fwrite(&bmpInfoHdr,sizeof(tagBITMAPINFOHEADER),1,BmpOut); //写信息头

for (int k=255;k>=0;k=k-255/((int)pow(2,bmpBps)-1))
{
rgb.rgbBlue=255-k;
rgb.rgbGreen=255-k;
rgb.rgbRed=255-k;

rgb.rgbReserved=0;
fwrite(&rgb,sizeof(rgb),1,BmpOut);
}

//写每个像素值信息
int size=(width*height)/(8/Bps);
fwrite(&Data,size,1,BmpOut);

fclose(BmpOut);
return 0;
}


为什么经过读取后执行保存函数之后得到的图片似乎是只有文件头、信息头、颜色表数据的文件 打开图片,显示绘图失败 望指教!!!
...全文
366 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2012-03-20
  • 打赏
  • 举报
回复
据说bmp的像素数据每行是按4字节对齐的。
scutflying_fish 2012-03-20
  • 打赏
  • 举报
回复
想请问楼主,问题解决了吗?我也碰到一模一样的问题
once_and_again 2008-10-29
  • 打赏
  • 举报
回复
c的简单 明显一些。
yuliyang 2008-10-29
  • 打赏
  • 举报
回复
我觉得绘图失败很有可能是文件头和信息头的问题。。用Zeromemory试一下吧。
yuliyang 2008-10-29
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 superbblue 的回复:]
to yuliyang :
ms不是你说的原因哦!!!
[/Quote]
哦。。我说的第一条确实不对。不过你试没试一下把文件头和信息头都先用零初始化一下?
superbblue 2008-10-29
  • 打赏
  • 举报
回复
to yuliyang :
ms不是你说的原因哦!!!
superbblue 2008-10-29
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 zmlovelx 的回复:]
up 发到vc/mfc 比较合适
[/Quote]

不错的建议!!!谢谢ZC!!!
yuliyang 2008-10-29
  • 打赏
  • 举报
回复
1、
struct tagRGBQUAD rgb;
如果你是要用它来存储调色板的话,那么后面这几句
for (int k=255;k>=0;k=k-255/((int)pow(2,bmpBps)-1))
{
rgb.rgbBlue=255-k;
rgb.rgbGreen=255-k;
rgb.rgbRed=255-k;

rgb.rgbReserved=0;
fwrite(&rgb,sizeof(rgb),1,BmpOut);
}
始终在对同一个结构体重复赋值啊。
是不是应该定义一个结构体数组呢?
2、
在向文件头和信息头里面写东西之前,我觉得最好用Zeromemory初始化一下。
我前两天也写了一个,是把24位保存为8位位图的。
void CDemoDlg::OnDlgBaocun()
{

CString msg;
CFileDialog dlg(FALSE,"*.BMP","", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT
,"BMP Files (*.bmp)|*.bmp||", NULL );
int iResult;
iResult=dlg.DoModal();
if(iResult==IDOK)
{
msg+=dlg.GetFileName();
}
CFile *fp=new CFile();
fp->Open(msg,CFile::modeWrite | CFile::modeCreate);
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
ZeroMemory(&bf,sizeof(BITMAPFILEHEADER));
ZeroMemory(&bi,sizeof(BITMAPINFOHEADER));
bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(bmp.bmWidth*8+31)/32*4*bmp.bmHeight+1032;
bf.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+1032;
bf.bfReserved1=0;
bf.bfReserved2=0;
bf.bfType=(WORD)('M'<<8|'B');
fp->Write(&bf,sizeof(BITMAPFILEHEADER));
bi.biSize=sizeof(BITMAPINFOHEADER);
bi.biWidth=bmp.bmWidth;
bi.biHeight=bmp.bmHeight;
bi.biPlanes=1;
bi.biBitCount=8;
bi.biCompression=BI_RGB;
bi.biSizeImage=bmp.bmHeight*(((bmp.bmWidth)+31)/32*4);
//bi.biXPelsPerMeter=0;
//bi.biYPelsPerMeter=0;
bi.biClrUsed=0;
bi.biClrImportant=0;
fp->Write(&bi,sizeof(BITMAPINFOHEADER));

LPLOGPALETTE lpPal;
HANDLE hLogPal;

hLogPal=::GlobalAlloc(GHND,sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*256);
lpPal=(LPLOGPALETTE)::GlobalLock((HGLOBAL)hLogPal);
lpPal->palVersion=0x300;
lpPal->palNumEntries=256;
for(int i=0;i<256;i++)
{
lpPal->palPalEntry[i].peRed=i;
lpPal->palPalEntry[i].peGreen=i;
lpPal->palPalEntry[i].peBlue=i;
lpPal->palPalEntry[i].peFlags=0;
}

fp->WriteHuge(lpPal,sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*256);



LPBYTE lpPtr,lptemp; //指向原图像数据,保存内存的中间图像数据
int x,y;
unsigned char blue,green,red;
void * lp8Bits;
lp8Bits=malloc(bmp.bmHeight*bmp.bmWidth);


for(y=0;y<bmp.bmHeight;y++)
{

lpPtr=(LPBYTE)lpBits+y*bmp.bmWidthBytes;
lptemp=(LPBYTE)lp8Bits+(bmp.bmHeight-1-y)*bmp.bmWidth;
for(x=0;x<bmp.bmWidth;x++)
{
red=(unsigned char )(*lpPtr++);
green=(unsigned char )(*lpPtr++);
blue=(unsigned char )(*lpPtr++);

*lptemp++=(BYTE)(red*0.299+green*0.587+blue*0.114);
}
for(x=bmp.bmWidth;x%4!=0;x++)
{
lpPtr++;
}

}

fp->WriteHuge(lp8Bits,bmp.bmHeight*bmp.bmWidth);


fp->Close();

delete fp;


}
帅得不敢出门 2008-10-29
  • 打赏
  • 举报
回复
up 发到vc/mfc 比较合适
superbblue 2008-10-29
  • 打赏
  • 举报
回复
自己顶一下!!!!

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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