BMP文件格式,也被称为位图图像文件或与设备无关的位图文件格式(DIB)或者只是一个位图,是 一个光栅图形 图像文件格式使用 来存储位图,数字,图片,独立的显示设备。
微软已经定义了一个特定的表示颜色的位图 不同的颜色深度,作为援助交换设备和之间的位图 应用程序与各种各样的内部表示。 他们称这些 与设备无关的位图或权利,叫做DIB文件格式 文件格式或BMP图像文件格式。 根据微软的支持:
与设备无关的位图(DIB)是一种用于定义格式 与设备无关的位图在各种颜色的决议。 的主要目的 权利是允许从一个设备转移到另一个位图(因此, 与设备无关的名字)的一部分。 DIB外部格式,形成鲜明对比 设备相关的位图,在系统作为一个位图对象 应用程序创建的(……)。 元的DIB通常运输 (通常使用StretchDIBits()函数),BMP文件,剪贴板 (CF_DIB数据格式)。
BMP图片格式图:
接下来来看一个代码对BMP头的封装,然后将rgb888转化成rgb565的现象的例程:
#include
#include
#include
#define RGB(r,g,b) (((r>>3)<<11)|((g>>2)<<5)|(b>>3))
typedef unsigned char U8 ;
typedef unsigned short U16 ;
typedef unsigned int U32 ;
#pragma pack(1)
struct bmp_header //这个结构体就是对上面那个图做一个封装。
{
//bmp header
U8 Signatue[2] ; // B M
U32 FileSize ; //文件大小
U16 Reserv1 ;
U16 Reserv2 ;
U32 FileOffset ; //文件头偏移量
//DIB header
U32 DIBHeaderSize ; //DIB头大小
U32 ImageWidth ; //文件宽度
U32 ImageHight ; //文件高度
U16 Planes ;
U16 BPP ; //每个相素点的位数
U32 Compression ;
U32 ImageSize ; //图文件大小
U32 XPPM ;
U32 YPPM ;
U32 CCT ;
U32 ICC ;
};
#pragma pack()
int main(int argc , char **argv)
{
//判断参数,传进来的参数不等于两个,那么就报错 ./a.out xxx
if(argc != 2)
return -1 ;
int fd ;
int dest_fd ;
//以只读的方式打开一个文件 这个文件是rgb888
fd = open(argv[1] , O_RDONLY);
if(-1 == fd)
{
perror("open bmp file fail");
return -2 ;
}
//打开一个rgb565.bmp的图片
dest_fd = open("rgb565.bmp" , O_RDWR | O_CREAT|O_TRUNC , 0777);
if(dest_fd < 0 )
{
perror("open rgb565 fail");
return -3 ;
}
//定义一个bmp的头
struct bmp_header header ;
int ret ;
//读出bmp文件头的数据
ret = read(fd , &header , sizeof(struct bmp_header));
//以下是bmp图的相关数据
printf(" Signatue[0] : %c \n " , header.Signatue[0] );
printf(" Signatue[1] : %c \n " , header.Signatue[1] );
printf(" FileSize : %d \n " , header.FileSize );
printf(" Reserv1 : %d \n " , header.Reserv1 );
printf(" Reserv2 : %d \n " , header.Reserv2 );
printf(" FileOffset : %d \n " , header.FileOffset );
printf(" DIBHeaderSize : %d \n " , header.DIBHeaderSize);
printf(" ImageWidth : %d \n " , header.ImageWidth );
printf(" ImageHight : %d \n " , header.ImageHight );
printf(" Planes : %d \n " , header.Planes );
printf(" BPP : %d \n " , header.BPP );
printf(" Compression : %d \n " , header.Compression );
printf(" ImageSize : %d \n " , header.ImageSize );
printf(" XPPM : %d \n " , header.XPPM );
printf(" YPPM : %d \n " , header.YPPM );
printf(" CCT : %d \n " , header.CCT );
printf(" ICC : %d \n " , header.ICC );
char buffer[header.ImageSize] ;
read(fd , buffer , header.ImageSize);
close(fd);
//改变地方
header.BPP = 16 ;
header.FileSize = header.ImageWidth*header.ImageHight*2+54 ;
header.ImageSize = header.ImageWidth*header.ImageHight*2;
write(dest_fd , &header , sizeof(struct bmp_header));
int row , col ;
short data ;
char *p = NULL ;
for(row = 0 ; row < header.ImageHight ; row++)
{
for(col = 0 ; col < header.ImageWidth ; col++)
{
p =( buffer+(row*header.ImageWidth + col)*3);
data = RGB((unsigned char)(*(p+2)) , (unsigned char)(*(p+1)) ,
(unsigned char )(*(p)));
write(dest_fd , &data , 2);
}
}
close(dest_fd);
return 0 ;
}
接下来我们来对这幅图进行操作,看看打印出什么信息:这副图就是1.bmp----->格式rgb888
运行结果:获取到bmp图的包头,顺便将rgb888的bmp图转化为rgb565
生成rgb565的bmp图:是不是发现像素差了一点?
后续还会有bmp图相关的操作,例如BMP图旋转(左右转),bmp图的灰度处理
,欢迎继续关注Bruce.yang的嵌入式之旅