前言
在图像处理中经常会遇到BMP格式图的解析问题,本文简单介绍了bmp格式图的解析方式,并附上相应的C代码。
一、bmp格式图的特点
bmp图通常由图片的头文件信息和像素数据组成,如图1所示,是bmp图的部分数据,
图1 bmp示例图数据
图2 bmp的大小以及分辨率
其中,424D,十进制为66和77是BM字符的ascii值,表示是BMP文件;
2~5字节表示整个BMP文件的大小,0X00031866即202854个字节,与图2的bmp图大小相同;
6~9字节是保留数据段,一般是0;
10~13字节表示图像存储的位置,0X00000036,即第54个字节;
14~17字节表示位图数据头,0X00000028,即40;
18~21字节表示图像宽度,0X00000104,即260;
22~25表示图像高度,0X00000104,即260;
26~27表示色彩平面数,必须为1,即0X0001;
28~29表示每个像素存储的位数,0X0018,即24;
30~33表示字节压缩方式,0表示不压缩;
34~37表示原始位图数据的大小,0X00031830;
38~41表示横向分辨率,0X00000B13;
42~45表示纵向分辨率,0X00000B13;
46~49表示调色板颜色数,0X00000000;
50~53表示重要颜色数,0X01000000;
从54字节开始为像素数据。
二、bmp格式图的解析
解析bmp图中RGB三通道数据的C代码如下所示,首先读出文件头信息,然后读出像素数据。bmp的像素数据是从下往上从左往右存储的,即读出的第一个数据是左下角的像素值,最后一个数据是右上角的像素值。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct myBITMAPFILEHEADER
{
unsigned int uiSize;
unsigned int uiReserved;
unsigned int uiOffBits;
unsigned int uiSize1;
unsigned int uiWidth;
unsigned int uiHeight;
unsigned short usPlanes;
unsigned short usBitcount;
unsigned int uiCompression;
unsigned int uiSizeImage;
unsigned int uiXPelsPerMeter;
unsigned int uiYPelsPerMeter;
unsigned int uiClrUsed;
unsigned int uiClrImportant;
};
int main()
{
int iWidth,iHeight;
FILE *pf;
myBITMAPFILEHEADER fileheader;//存放bmp图头文件信息的结构体
char acBmpName[256];
sprintf(acBmpName,"1.bmp");
pf=fopen(acBmpName,"rb");//此处如果以r打开可能会导致数据读不完整
if(NULL==pf)
{
perror("fopen");
return -1;
}
unsigned char ucTmp1,ucTmp2;
ucTmp1=fgetc(pf);
ucTmp2=fgetc(pf);
if((ucTmp1!='B')||(ucTmp2!='M'))
{
printf("The file is not a bmp file!");
return -1;
}
//读取文件头信息
fread(&fileheader,sizeof(fileheader),1,pf);
iWidth=fileheader.uiWidth;
iHeight=fileheader.uiHeight;
unsigned char *pusData=(unsigned char *)malloc(iHeight*iWidth*sizeof(unsigned char)*3);
unsigned char *pusR=(unsigned char *)malloc(iHeight*iWidth*sizeof(unsigned char));
unsigned char *pusG=(unsigned char *)malloc(iHeight*iWidth*sizeof(unsigned char));
unsigned char *pusB=(unsigned char *)malloc(iHeight*iWidth*sizeof(unsigned char));
memset(pusData,0,iHeight*iWidth*sizeof(unsigned char)*3);
memset(pusR,0,iHeight*iWidth*sizeof(unsigned char));
memset(pusG,0,iHeight*iWidth*sizeof(unsigned char));
memset(pusB,0,iHeight*iWidth*sizeof(unsigned char));
//读取像素数据
fread(pusData,iHeight*iWidth*sizeof(unsigned char)*3,1,pf);
fclose(pf);
pf=NULL;
//解析出R、G和B通道
int i,j;
for(i=0;i<iHeight;i++)
{
for(j=0;j<iWidth;j++)
{
pusR[iWidth*(iHeight-i-1)+j]=pusData[i*iWidth*3+j*3+2];
pusG[iWidth*(iHeight-i-1)+j]=pusData[i*iWidth*3+j*3+1];
pusB[iWidth*(iHeight-i-1)+j]=pusData[i*iWidth*3+j*3+0];
}
}
free(pusData);
pusData=NULL;
free(pusR);
pusR=NULL;
free(pusG);
pusG=NULL;
free(pusB);
pusB=NULL;
return 0;
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了bmp格式图的解析方式,后续还会继续介绍bmp图的存储方式。