Linux应用开发 您所在的位置:网站首页 c语言显示bmp图像的代码 Linux应用开发

Linux应用开发

2023-11-26 00:46| 来源: 网络整理| 查看: 265

1. 前言

BMP是一种与硬件设备无关的图像文件格式,是Windows环境中交换与图有关的数据的一种标准,在Windows环境中运行的图形图像软件都支持BMP图像格式。BMP格式的图片存放的就是原始的RGB数据,一般没有做压缩,也就是图片的画质是最原始的,也导致BMP图片占用的内存非常大。现在常用的jpg、jpeg格式都是压缩格式,保存的时候通过算法编码压缩,显示的时候再解压成RGB数据渲染显示。

BMP格式在嵌入式设备里用的还是较多的,BMP虽然占用内存大,优点是显示速度快,因为不需要解码,在性能一般,不是很强的设备上使用BMP显示效率较高。

为了解BMP格式,这篇文章就采用Linux开发板作为实验平台,在LCD屏上读取BMP图片,完成绘制,不需要借助任何第三方库,全部由纯C语言代码一行一行敲出来,深入理解Linux下帧缓冲编程框架、BMP图片的存储结构原理。

一般BMP图片由以下4个部分组成: 1:文件头 2:图像参数 3:调色板 4:位图数据

现在一般采用的图片都是RGB888,24位真彩色,就没有调色板,只有3个部分组成。

其中文件头存放图片的属性,位图数据偏移量。图像参数存放图片的宽高、像素位数等信息。位图数据就是存储的原始RGB数据,可以直接在LCD屏上显示。

下面列出BMP图片的结构:

image-20220124001914847image-20220124001914847image-20220124001941914image-20220124001941914

位图数据存储规则:

(1)每行的字节数必须是4的倍数,如果不是,则需要用0补齐。 (2)BMP位图数据的存放是从下到上,从左到右的。先读最后一行,读完后在读倒数第二行。

image-20220124002345869image-20220124002345869

按照上面的介绍,就可以定义一个BMP解码专用的结构体,对应文件里每个字节数据,结构体成员变量必须按照上面截图里的说明定义。整个结构体还需要进行强制1个字节对齐,不然每个编译器对结构体的空间开辟规则有差异,会导致数据错位。

#pragma pack(1) //强制1个字节对齐 //BMP的文件头 struct _BMP_HEAD { char type[2]; //图片的类型 "BM" unsigned int size; //文件大小 unsigned short r1; //保留1 unsigned short r2; //保留2 unsigned int seek; //数据偏移字节(真实像素点数据) }; //BMP的参数信息 struct _BMP_INFO { unsigned int size; //当前结构体大小 unsigned int w; //宽度 unsigned int h; //高度 unsigned short flag; //固定为1 unsigned short bit; //像素点的位数 unsigned int r1; //压缩方式 0 unsigned int r2; //水平分辨率 unsigned int r3; //垂直分辨率 unsigned int r4; //垂直分辨率 unsigned int r5; //引用色彩 unsigned int r6; //关键色彩 };2. 实现代码

要在LCD屏上完成BMP图片的显示,编写代码需要分几步完成,先编写LCD屏的基本显示代码,封装画点函数,LCD屏测试没有问题之后,再编写BMP解码代码,完成图片的渲染显示。

2.1 封装LCD屏画点函数#include #include #include #include unsigned char *fb_mem; struct fb_var_screeninfo var;//可变参数 struct fb_fix_screeninfo fix;//固定参数 /*画点*/ void show_pixel(int x,int y,int color) { unsigned long *show32 = NULL; /* 定位到LCD屏上的位置*/ show32=(unsigned long*)(fb_mem+y*var.xres*var.bits_per_pixel/8 + x*var.bits_per_pixel/8); *show32 =color; /*向指向的LCD地址赋数据*/ } int main(int argc,char**argv) { int fb; fb=open("/dev/fb0",2); if(fb> 8)&0xff; blue = color&0xff; color = ((red>>3)2)3); *show16 = color; break; } case 32: { *show32 = color; break; } default:break; } } /*映射图片地址*/ static unsigned char *getbmpadd(char *name) { unsigned char *bmpmem = NULL; FILE* filp; int fd; struct stat t_stat; /* 以r+可读可写方式打开name */ filp = fopen(name,"r+"); if(filp == NULL) { printf("can't open %s\n",name); return NULL; } /* 把文件指针转化为文件描述符 */ fd = fileno(filp); /* 获取文件大小 */ fstat(fd, &t_stat); iFileSize = t_stat.st_size; /* 映射 */ bmpmem = mmap(NULL,iFileSize,PROT_READ|PROT_WRITE,MAP_SHARED,fd, 0); if(bmpmem == (unsigned char *)-1) { printf("can't mmap..\n"); return NULL; } return bmpmem; } void bmp_destroy(unsigned char *bmpmem) { munmap(bmpmem,iFileSize); } void Convert_One_Line(unsigned char *src,unsigned char *dst,int iWidth) { unsigned char *show8=NULL; unsigned short *show16=NULL; unsigned long *show32 = NULL; unsigned char *buf = src; int red; int green; int blue; int i; /* 定位到LCD屏上的位置 */ show8 = dst; show16 = (unsigned short *)show8; show32 = (unsigned long *)show8; for(i=0;i>3)2)3); show16++; break; } case 32: { *show32 = (redbfOffBits; /* 得到图片一行字节数 */ iLineWidth = iWidth*iBpp/8; /* 向4取整,保证一行必须是4的倍数 */ iRealLineWidth = (iLineWidth+3)&~0x3; // iLineWidth % 4 =0 /* src指向图片RGB数据最后一行的首地址*/ src += iRealLineWidth*(iHeight-1); /* LCD屏一行的总字节数 */ iFbLineWidth = var.xres * var.bits_per_pixel/8; /*dst指向LCD的首地址*/ dst = fbmem; for(i=0;i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有