用c语言对bitmap文件进行读取(256灰度与24位色)

※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

http://iiec.cqu.edu.cn/wiki/index.php?title=%E7%94%A8c%E8%AF%AD%E8%A8%80%E5%AF%B9bitmap%E6%96%87%E4%BB%B6%E8%BF%9B%E8%A1%8C%E8%AF%BB%E5%8F%96%28256%E7%81%B0%E5%BA%A6%E4%B8%8E24%E4%BD%8D%E8%89%B2%29&oldid=5050

用c语言对bitmap文件进行读取(256灰度与24位色)
在2008年7月17日 (四) 07:53由Zhouxl (对话 | 贡献)所做的修订版本
(差异) ←上一修订 | 当前修订 (差异) | 下一修订→ (差异)

1.关于BITMAP图像的结构:
24位色的BITMAP图像结构按顺序分为BITMAPFILEHEADER(文件头),BITMAPINFOHEADER(信息头),后面接着为象素信息;
非24位色在BITMAPINFOHEADER(信息头)之后还有一个RGBQUAD(调色板)结构信息,然后接着才是象素信息.
下面是三个结构体的信息:


struct BITMAPFILEHEADER
{

unsigned   int    bftype;//文件类型是否为BMP文件  
unsigned   long   bfsize;//文件大小,以字节为单位  
unsigned   int    bfreserverd1;//文件保留字,必须为0  
unsigned   int   bfreserverd2;//文件保留字,必须为0  
unsigned   long   bfOffBits;//文件头的偏移量表示,以字节为单位
};


struct BITMAPINFOHEADER

{

int   bisize;//本结构大小字节为单位
int   width;//图形宽度以象素为单位  
int   height;//图形高度以象素为单位  
int   planes;//目标设备的级别,必须为1  
int   bitcount;//每个象素所需要的位数  
int   SizeImage;   //   位图的大小,以字节为单位
int   compression;//是否为压缩  
int   xpermeter;//位图水平分辨率,每米像素数  
int   ypermeter;//   位图垂直分辨率,每米像素数  
int   ClrUsed;//   位图实际使用的颜色表中的颜色数  
int   ClrImportant;//   位图显示过程中重要的颜色数
};


struct RGBQUAD

{    

BYTE     rgbBlue;         //   蓝色的亮度(值范围为0-255)    
BYTE     rgbGreen;       //   绿色的亮度(值范围为0-255)  
BYTE     rgbRed;           //   红色的亮度(值范围为0-255)  
BYTE     rgbReserved;//   保留,必须为0  

};




关于调色板的原理:
如果对每一个象素都用RGB 3个分量表示,一幅100*100象素的16色图,若按3字节来储存,将占用100*100*3 = 30 000byte的空间,而一般图片都远大于100*100,这将导致大量的空间被占用,于是为颜色设计一个表:表的每行记录记录一种颜色的RGB值,当需要表示一象素颜色的时候,只要指定该颜色位于表中的位置即可.对于16色图,表的每种颜色只需要4位就可以就可以表示出来,因此整个图像只需要100*100*0.5 = 5 000byte, 再加上颜色表所用的3*16=48字节,一共5 048byte就可以将一个30 000byte的图片表示出来,这样就节约了空间.这个颜色表就叫调色盘.

关于象素点阵:
在24位真彩色的象素点中,每个像素点用3个字节表示RGB三个值,而在256级灰度色中,由于采用了调色板的模式,因调色板中的颜色需要8位才能表示完整,所以每个象素点用1个字节(即8bits)来标识调色板中对应的颜色.


2.对BITMAP文件的读取
根据以上对BITMAP结构体的描述,下面我将采用代码的形式进行介绍



#include<stdio.h>
#include<windows.h>

void main()

{

BITMAPFILEHEADER bmpfileheader;//定义一个文件头的对象

BITMAPINFOHEADER bmpinfoheader;//定义一个信息头的对象

RGBQUAD bmpRGB[256];//定义的一个256级灰度的颜色表

FILE *stream;//BITMAP文件结构体读取操作流

FILE *store;//BITMAP文件象素读取操作流

FILE *clear;//为pic.txt文本文件清空内容

BYTE* pixelmatrix;//用以储存象素矩阵



int sum_pixel;//求出总共象素所占内存区域的大小

stream = fopen("test.bmp","r+b");//以可读写二进制形式打开test.bmp文件

if (stream == NULL)

{

cout<<"Open failed\n";

return;

}

else

cout<<"Open Successsfully\n";

/**

*取BMP文件头信息

*/

fread(&bmpfileheader,sizeof(BITMAPFILEHEADER),1,stream);//从stream文件流读取BMP文件头信息


printf("type=%d\nsize=%d\nreserverd1=%d\nreserverd2=%d\nbfOffBits=%d\n",

bmpfileheader.bfType,bmpfileheader.bfSize,bmpfileheader.bfReserved1,

bmpfileheader.bfReserved2,bmpfileheader.bfOffBits);

/**

*取BMP信息头信息

*/

fread(&bmpinfoheader,sizeof(BITMAPINFOHEADER),1,stream);//从stream文件流读取BMP文件头信息


printf("biSize=%d\nbiWidth=%d\nbiHeight=%d\nbiPlanes=%d\nbiBitCount=%d\nbiCompression=%

d\nbiSizeImage=%d\nbiXPelsPerMeter=%d\nbiYPelsPerMeter=%d\nbiClrUsed=%d\nbiClrImportant=%d\n",

bmpinfoheader.biSize,bmpinfoheader.biWidth,bmpinfoheader.biHeight,

bmpinfoheader.biPlanes,bmpinfoheader.biBitCount,bmpinfoheader.biCompression,

bmpinfoheader.biSizeImage,bmpinfoheader.biXPelsPerMeter,bmpinfoheader.biYPelsPerMeter,

bmpinfoheader.biClrUsed,bmpinfoheader.biClrImportant);

/**

*取BMP调色盘信息

*/

if (bmpinfoheader.biBitCount != 24)//当且仅当颜色位数不是24位色时才读取调色盘信息

{

fread(&bmpRGB,sizeof(RGBQUAD),256,stream);//读取256个调色板的每个的颜色

for (int k = 0 ; k<256 ; k++)

printf("rgbBlue=%d\nrgbGreen=%d\nrgbRed=%d\nrgbReserved=%d\n",

bmpRGB[k].rgbBlue,bmpRGB[k].rgbGreen,bmpRGB[k].rgbRed,bmpRGB[k].rgbReserved);

}

/**

*取象素信息

*/

pixelmatrix = new BYTE[bmpinfoheader.biSizeImage];//按照图片的大小给BYTE数组分配内存空间

memset(pixelmatrix,0,bmpinfoheader.biSizeImage);//对数组的每个值都进行初始化

fread(pixelmatrix,1,bmpinfoheader.biSizeImage,stream);//读取象素信息

fclose(stream);//关闭文件操作流

/**

*此处将象素信息写入txt文档

*1.首先清空TXT文档

*2.然后再写入

*/

clear = fopen("pic.txt","w");//以写("w")形式打开将会清空所打开的文件,详细见MSDN->fopen

fclose(clear);//关闭文件操作流

store = fopen("pic.txt","ab");

for (int j = 0;j<bmpinfoheader.biSizeImage;j++)//当前位置小于总的象素个数时继续循环

fprintf(store,"%d\n",pixelmatrix[j]);

fclose(store);//关闭文件操作流


/////////////////////////////////////////////////////////////////////////


char reply;//保持当前画面

cin>>reply;

}


3.注意事项 BITMAP的文件是按照固定的顺序组织起来的,所以不能随便更改结构体读取的顺序,不然将会导致信息错误
在向文本文件写入的时候,要使用fprintf进行格式化写入,不然将导致TXT乱码