欢迎来到我的博客>"萝卜驿站"<希望文章对你有所帮助,如有错误和遗漏,欢迎批评和指正。>ω< |
# BMP文件格式详解 ## 你必须要懂得几点 - BMP(Bitmap、位图) - 位数:1、4、8、16、24(RGB真彩色)、32(RGBA[透明度]真彩色),指的是表示一个像素所用的bit位数。 - 在BMP文件中,如果一个数据需要用几个字节来表示的话,那么该数据的存放字节顺序为“低地址存放低位数据,高地址存放高位数据”。如数据0x1756在内存中从小到大存储为:
正文
- BMP文件的数据按照从文件头开始先后分为四个部分
文件头
typedef struct tagBITMAPFILEHEADER
{
UINT16 bfType;
DWORD bfSize;
UINT16 bfReserved1;
UINT16 bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
位图信息头
调色板
- 调色板其实是一张映射表,调色板中放置所有需要使用的颜色,并通过计算地址建立索引关系。它在文件中的布局就像一个二维数组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位真彩色文件信息
- 命令行输出位图宽度(像素数)、高度(像素数)、、位图信息地址偏移值。
- 输出每个像素的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 萝卜饭