BMP文件格式详解及利用C读取24位真彩色图片信息

欢迎来到我的博客>"萝卜驿站"<希望文章对你有所帮助,如有错误和遗漏,欢迎批评和指正。>ω<
# BMP文件格式详解 ## 你必须要懂得几点 - BMP(Bitmap、位图) - 位数:1、4、8、16、24(RGB真彩色)、32(RGBA[透明度]真彩色),指的是表示一个像素所用的bit位数。 - 在BMP文件中,如果一个数据需要用几个字节来表示的话,那么该数据的存放字节顺序为“低地址存放低位数据,高地址存放高位数据”。如数据0x1756在内存中从小到大存储为:
0x77 0x78
0x56 0x17

正文

  • BMP文件的数据按照从文件头开始先后分为四个部分
    BMP文件格式详解及利用C读取24位真彩色图片信息_第1张图片

文件头
  • Windows为bmp文件头定义了如下结构体
typedef struct tagBITMAPFILEHEADER 
{  
	UINT16 bfType;    
	DWORD bfSize; 
	UINT16 bfReserved1; 
	UINT16 bfReserved2; 
	DWORD bfOffBits;
} BITMAPFILEHEADER;

BMP文件格式详解及利用C读取24位真彩色图片信息_第2张图片


位图信息头

BMP文件格式详解及利用C读取24位真彩色图片信息_第3张图片


调色板
  • 调色板其实是一张映射表,调色板中放置所有需要使用的颜色,并通过计算地址建立索引关系。它在文件中的布局就像一个二维数组palette[N][4],其中N表示总的颜色索引数,每行的四个元素分别表示该索引对应的B、G、R和Alpha的值,每个分量占一个字节。如不设透明通道时,Alpha为0。索引号就是所在行的行号,对应的颜色就是所在行的四个元素。采用调色板的原因是对于#000000~#FFFFFF的255X255X255种颜色,人类的眼睛并不是全部都能分辨,也没有必要全部分辨,所有只需采用其中的某些颜色就可以显示同样的效果。

位图数据
  • 位图数据了,每个像素占一个字节,取得这个字节后,以该字节为索引查询相应的颜色,并显示到相应的显示设备上就可以了。若采用24位或32位真彩色位图,则无需使用调色板模块,位图数据中也不是每个像素用一个字节的索引表示,而是用3个字节(24位)的实际RGB值或者4个字节(32位)RGBA值来表示。
  • !!!位图数据在文件中的排列顺序是从左下角到右上角,以行为主序排列的。也就是说图片左下角第一个像素存储是放在第一位的,存储的第二个像素是图片最下面一行左数第二个,存储的最后一个是右上角的像素。
  • !!!对于24位真彩色数据,每个像素实际上是以BGR的顺序存放,并不是按照RGB的顺序,而32位真彩色是按照BGRA的顺序。
  • !!!因为32位的Windows操作系统处理4个字节(32位)的速度比较快,所以BMP的每一行颜色占用的字节数规定为4的整数倍,不足需补0。例:如果24位bmp文件每行有两个像素,即占用6字节,要补齐成4*2=8字节,就要再加两个0字节在后面。

C语言读取24位真彩色文件信息

  • 输入任意一幅24位真彩色BMP文件
  • 效果:
  1. 命令行输出位图宽度(像素数)、高度(像素数)、、位图信息地址偏移值。
  2. 输出每个像素的rgb值到Rgbdata.txt。
  • 代码如下:
#include 
#include 

#define BM 0x4D42
#define PATH "lena.bmp" //文件路径

int IsBitMap(FILE *fpIN);//判断是否为BM格式的BMP文件
unsigned int getBitmapWidth(FILE *fpIN);//读取文件宽度像素
unsigned int getBitmapHeight(FILE *fpIN);//读取文件高度像素
unsigned short getBit(FILE *fpIN);//读取图片单元像素表示位数
unsigned int getOffset(FILE *fpIN);//读取文件位图数据地址偏移
void getData(FILE *fpIN,unsigned int width,unsigned int height,unsigned short bit,unsigned int offset);//获取文件位图信息中的每个像素的rgb值,并存储到Rgbdata.txt中。

int main(){
	FILE *fpIN=fopen(PATH,"rb");
	unsigned int width,height,offset;
	unsigned short bit;
	if(fpIN==NULL){
		printf("[Error]Can not open file "PATH".\n");
		return -1;
	}
	bit=getBit(fpIN);
	if(IsBitMap(fpIN)&&(bit==24)){
		printf("The file is 24 bit BMP file.\nFile name: "PATH"\n");
	}
	else{
		printf("[Error]The file is not 24 bit BMP file.\n");
		return -1;
	}
	width=getBitmapWidth(fpIN);
	height=getBitmapHeight(fpIN);
	bit=getBit(fpIN);
	offset=getOffset(fpIN);
	printf("The width of bitmap is %ld.\n",width);
	printf("The height of bitmap is %ld.\n",height);
	printf("The offset of bitmap date is %d.\n",offset);
	getData(fpIN,width,height,bit,offset);
	fclose(fpIN);
	return 0;
}

int IsBitMap(FILE *fpIN){
	unsigned short mod;
	fseek(fpIN,0,SEEK_SET);
	fread(&mod,1,2,fpIN);
	if(mod==BM){
		return 1;
	}
	else{
		return 0;
	}
}

unsigned int getBitmapWidth(FILE *fpIN){
	long width;
	fseek(fpIN,18,SEEK_SET);
	fread(&width,1,4,fpIN);
	return width;
}

unsigned int getBitmapHeight(FILE *fpIN){
	long height;
	fseek(fpIN,22,SEEK_SET);
	fread(&height,1,4,fpIN);
	return height;
}

unsigned short getBit(FILE *fpIN){
	unsigned short bit;
	fseek(fpIN,28,SEEK_SET);
	fread(&bit,1,2,fpIN);
	return bit;
}

unsigned int getOffset(FILE *fpIN){
	unsigned int offset;
	fseek(fpIN,10L,SEEK_SET);
	fread(&offset,1,4,fpIN);
	return offset;
}

void getData(FILE *fpIN,unsigned int width,unsigned int height,unsigned short bit,unsigned int offset){
	int i,j,widthBytes,count;
	unsigned char *rgb,*data;
	FILE *fprgb=fopen("Rgbdata.txt","w+");
	widthBytes=(width*bit+31)/8;
	//上下两行代码用于行补齐,也可为widthBytes = (((width* bit) +31)>>5)<<2;
	widthBytes=widthBytes/4*4;
	data=(unsigned char*)malloc(widthBytes);
	rgb=(unsigned char*)malloc(width*height*3*2);
	fseek(fpIN,offset,SEEK_SET);
	for(i=0;i

大部分参考来源

链接 作者
https://www.cnblogs.com/wainiwann/p/7086844.html wainiwann
https://blog.csdn.net/qingchuwudi/article/details/25785307 qingchuwudi

By 萝卜饭  


你可能感兴趣的:(随笔)