首先,我们应该对BMP文件的格式有了解。
BMP(全称Bitmap)是Windows操作系统中的标准图像文件格式,使用非常广,并采用位映射存储格式。
最常见的就是24位图,也称真彩色,就是说一个像素的颜色信息用24位来表示。对于三原色BRG,每一个颜色都用以字节(8 bit)来表示,颜色顺序为BGR。
除了24位图,还有1位(单色),2位(4色,CGA),4位(16色,VGA),8位(256色),16位(增强色)和32位(BGRA)等。
BMP格式的文件从头到尾依次是如下信息:
bmp文件头(bmp file header):共14字节;
位图信息头(bitmap information):共40字节;
调色板(color palette):可选;
像素数组;
1.判断是否位BMP文件
lseek(fd, 0x0, SEEK_SET);//fd为打开的图片文件,lseek移动光标到文件开头
read(fd, buf, 2);//读出信息到一个大小为2字节的buf里
if((buf[0] != 0x42) || (buf[1] != 0x4D)) //文件开头的两个字节必须是0x42, 0x4D
{
printf("It is not bmp format file\n");
return;
}
参考如下表:
2. 解析出BMP文件的相关信息
宽(width),高(height),深度(depth)。
width = (buf[0] & 0xFF) |
(( buf[1] & 0xFF) << 8) |
(( buf[2] & 0xFF) << 16) |
(( buf[3] & 0xFF) << 24);
lseek(fd, 0x16, SEEK_SET);
read(fd, buf, 4);
height = (buf[0] & 0xFF) |
((buf[1] & 0xFF) << 8 ) |
((buf[2] & 0xFF) << 16) |
((buf[3] & 0xFF) << 24);
lseek(fd, 0x1C, SEEK_SET);
read(fd, buf, 2);
depth = (buf[0] & 0xFF) |
((buf[1] & 0xFF) << 8);
//size表示图像真正的像素数据
size = abs(width*height*depth/8);//height有可能是负数
参考如下表:
3.解析出每个像素点的信息
//pixel用于保存像素信息
pixel = (unsigned char *) malloc (size *sizeof(unsigned char));
lseek(fd, 54, SEEK_SET); //真正的像素信息在54个字节的偏移量
read(fd, pixel, size);
int x, y;//(x, y)表示当前从pixel取颜色的坐标
unsigned char r, g, b, a;
int i = 0, real_y; //real_y表示屏幕的坐标
int color; //因为屏幕的每个像素是32bit
for(y = 0; y < abs(height); y++)
{
for(x = 0;x < abs(width);x++)
{
//b, g, r的顺序是按bmp格式要求
b = (pixel[i++] & 0xFF);
g = (pixel[i++] & 0xFF);
r = (pixel[i++] & 0xFF);
if(32 == depth) //depth是图片的深度
a = (pixel[i++] & 0xFF);
else//depth为24
a = 0x0;
color = (a<<24) | (r<<16) | (g<<8) | b;
if(height > 0) //height为正的时候,表示存储的第一行是要显示到屏幕上的最后一行
real_y = height -1 - y;
else
real_y = y;
//Draw_Point( x, real_y, color);
}
}
free(pixel);//free掉malloc到的存储空间能防止内存泄漏
Draw_Point( x, real_y, color)为我自定义的描点函数,通过交叉编译最终可在开发板上显示图片。