BMP文件格式,也被称为位图图像文件或与设备无关的位图文件格式(DIB)或者只是一个位图,是
一个光栅图形 图像文件格式使用
来存储位图,数字,图片,独立的显示设备。
微软已经定义了一个特定的表示颜色的位图 不同的颜色深度,作为援助交换设备和之间的位图 应用程序与各种各样的内部表示。
他们称这些 与设备无关的位图或权利,叫做DIB文件格式 文件格式或BMP图像文件格式。 根据微软的支持:
与设备无关的位图(DIB)是一种用于定义格式 与设备无关的位图在各种颜色的决议。 的主要目的 权利是允许从一个设备转移到另一个位图(因此, 与设备无关的名字)的一部分。 DIB外部格式,形成鲜明对比 设备相关的位图,在系统作为一个位图对象 应用程序创建的(……)。 元的DIB通常运输 (通常使用StretchDIBits()函数),BMP文件,剪贴板 (CF_DIB数据格式)。
BMP图片格式图:
接下来来看一个代码对BMP头的封装,然后将rgb888转化成rgb565的现象的例程:
#include <stdio.h> #include <fcntl.h> #include <unistd.h> #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的嵌入式之旅