求助c++读取BMP文件

这是我参照其他人的程序,写的一段读取BMP文件的程序,可是运行出来的图像发生了扭曲和色彩的变化,不知道是什么问题,下面是程序代码:
#include"iostream.h"
#include "stdio.h"
#include "stdlib.h"
typedef struct { // 长度12字节
// short bftype; // 固定为"BM",VC不能读取一个short,故省略
int bfSize; // 位图文件的大小,以字节为单位
short bfReserved1; // 位图文件保留字,必须为0
short bfReserved2; // 位图文件保留字,必须为0
int bfOffBits; // 位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER;
typedef struct { // 长度40字节
int biSize; // 本结构所占用字节数,长度40字节
int biWidth; // 位图的宽度,以像素为单位
int biHeight; // 位图的高度,以像素为单位
short biPlanes; // 目标设备的级别,必须为1
short biBitCount; // 每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一
int biCompression; // 位图压缩类型,必须是0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
int biSizeImage; // 位图的大小,以字节为单位
int biXPelsPerMeter; // 位图水平分辨率,每米像素数
int biYPelsPerMeter; // 位图垂直分辨率,每米像素数
int biClrUsed; // 位图实际使用的颜色表中的颜色数
int biClrImportant; // 位图显示过程中重要的颜色数
} BITMAPINFOHEADER;
void bitmapfileheadinitialize(BITMAPFILEHEADER &fh) // 初始化
{
fh.bfOffBits=0; fh.bfReserved1=0; fh.bfReserved2=0; fh.bfSize=0;

}
void bitmapimforheadinitialize(BITMAPINFOHEADER &ih) //初始化
{
ih.biBitCount=0;ih.biClrImportant=0;ih.biClrUsed=0;ih.biCompression=0;
ih.biHeight=0;ih.biPlanes=0;ih.biSize=0;ih.biSizeImage=0;ih.biWidth=0;
ih.biXPelsPerMeter=0;
}
void main()
{
FILE *rfile; //读入文件指针
FILE *wfile; //写入文件指针
short bmp_header=0x4D42; // bmp文件头字
short bmp_end=0x0000; // bmp文件尾字
BITMAPFILEHEADER fh, *pointfh; //文件头指针
BITMAPINFOHEADER ih, *pointih; //数据头指针
char *pointimage;// 图区域头指针
pointfh=&fh;pointih=&ih;
bitmapfileheadinitialize(fh); //初始化文件头
bitmapimforheadinitialize(ih);
而且读取的图像的水平分辨率和垂直分辨率是3780,但是我点击图片右键看图片的“摘要”“属性”的时候上面的水平和垂直分辨率是96,出现不一致的现象,这又是怎么回事呢????谢谢大侠了,感激涕零
if( ( rfile=fopen( "d:\\huojian256.bmp", "r" )) == NULL )
printf( "The file 'd:\\huojian256.bmp' was not opened\n" );
else
printf( "The file 'd:\\huojian256.bmp' was opened\n" );
if( ( wfile=fopen( "d:\\huojian.bmp", "w" )) == NULL )
printf( "The file 'd:\\huojian.bmp' was not opened\n" );
else
printf( "The file 'd:\\huojian.bmp' was opened\n" );

//读取头文件
fseek( rfile , sizeof(short) ,SEEK_SET );
fread( pointfh ,sizeof(BITMAPFILEHEADER) , 1 , rfile );
//读取信息头文件
fseek( rfile , sizeof(BITMAPFILEHEADER)+sizeof(short) ,SEEK_SET );
fread( pointih ,sizeof(BITMAPINFOHEADER),1, rfile );
//读位图信息
pointimage=(char*)calloc(ih.biSizeImage*3, sizeof(char));
fseek(rfile,fh.bfOffBits,SEEK_SET);//头指针移动到位图区
fread(pointimage,sizeof(char),ih.biSizeImage*3,rfile);

你好,我把问题补充一下,希望对你有帮助。如果还是不行,你再问我。

在你如下的程序段中:
//读取头文件
fseek( rfile , sizeof(short) ,SEEK_SET );
fread( pointfh ,sizeof(BITMAPFILEHEADER) , 1 , rfile );
//读取信息头文件
fseek( rfile , sizeof(BITMAPFILEHEADER)+sizeof(short) ,SEEK_SET );
fread( pointih ,sizeof(BITMAPINFOHEADER),1, rfile );
//读位图信息
pointimage=(char*)calloc(ih.biSizeImage*3, sizeof(char));
fseek(rfile,fh.bfOffBits,SEEK_SET);//头指针移动到位图区
fread(pointimage,sizeof(char),ih.biSizeImage*3,rfile);

第一句中,我觉得不要加sizeof(short),而是将其改为0。因为文件的前sizeof(BITMAPFILEHEADER)个字节就是 文件信息头,紧接其后的sizeof(BITMAPINFOHEADER)个字节是位图信息头,所以在你的第三条语句中,也应去掉sizeof(short)。另外,biSizeImage就是位图像素信息实际占用的存储空间长度,不需要乘以3,所以在上面第5和第7句中应将“*3”去掉。这时你在运行一下试试。

还有,24位位图每个像素用3个字节表示。你的256像素*256像素的图像的实际占用的字节数应是256*256*3 = 196608,这正是biSizeImage的值!

bmp文件分为四个部分:
文件信息头、位图信息头、调色板、位图信息数据。

你在读信息头文件后,应该读调色板数据。对于真彩色图像,因为没有调色板,所以不用读;但对于其他的图像就需要读了。这是你的代码存在的问题之一。解决办法是根据biBitCount的值判断调色板的大小:若biBitCount为1,调色板大小为2*sizeof(RGBQUAD)字节;若为4,调色板16*sizeof(RGBQUAD);若为8,调色板256*sizeof(RGBQUAD);若为24,调色板为0。

另外,位图信息数据每行存储的字节数一定是4字节的整数倍,不足的时候补0。比如你的图像每行只有一个像素,一个像素用三个字节存储,那么在实际存储该图像时需要在每行多补充一个字节,以使其达到4字节的整数倍。biSizeImage的值就是图像信息数据实际存储的字节数,读的时候直接读这么多字节的数据就行了,不需要乘以3。你的代码在读信图信息时并没考虑这一点,这是存在的问题之二。图像每行存储的实际字节数:nBytesPerLine = biSizeImage / biHeight,这个值在后续的处理中可能会用到。

你说读取的分辨率是3780,是指每米有3780个像素,单位是像素/米。而那个96的单位可能不是像素/米。

希望对你有帮助。来自:求助得到的回答
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-04-23
补充程序,上面的不完整
// 将bmp头字写入文件
fseek(wfile,0,SEEK_SET);
fwrite(&bmp_header,sizeof(short),1,wfile); //写入缺省short值

// 将模板bmp文件头文件写入生成文件
fseek(wfile,sizeof(short),SEEK_SET);
fwrite(&fh,sizeof(BITMAPFILEHEADER),1,wfile);
cout<<"sizeof file header"<<sizeof(BITMAPFILEHEADER)<<endl;
cout<<"sizeof infro header"<<sizeof(BITMAPINFOHEADER)<<endl;
// 将模板bmp文件信息头文件写入生成文件

fseek(wfile,sizeof(BITMAPFILEHEADER)+sizeof(short),SEEK_SET);
fwrite(&ih,sizeof(BITMAPINFOHEADER),1,wfile);
// 将图像数据pImage写入生成文件
fseek(wfile,fh.bfOffBits,SEEK_SET);
fwrite(pointimage,ih.biSizeImage*3,1,wfile);
// free(pointimage);
//poi=wfile; //文件指针不能赋值给其他类型的指针
// 将bmp尾字写入文件
fseek(wfile,0,SEEK_END);
fwrite(&bmp_end,sizeof(short),1,wfile);
fclose(rfile);
fclose(wfile);
}
相似回答