「用c语言对bitmap文件进行读取(256灰度与24位色)」の編集履歴(バックアップ)一覧はこちら
追加された行は緑色になります。
削除された行は赤色になります。
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乱码