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

「用c语言对bitmap文件进行读取(256灰度与24位色)」の編集履歴(バックアップ)一覧に戻る

用c语言对bitmap文件进行读取(256灰度与24位色) - (2011/10/11 (火) 22:55:16) のソース

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乱码