嵌入式基于Linux、ARM的LCD的BMP图片的缩小、任意位置显示
更多资料请点击:我的目录本篇仅用于记录自己所学知识及应用,代码仍可优化,仅供参考,如果发现有错误的地方,尽管留言于我,谢谢。这一片是关于开发板800480的LCD显示屏显示BMP图片的,可以通过参数设置,将各种像素大小的BMP图片在任意位置显示,在800480像素范围内的BMP图像可以直接在任意位置显示,而大于800*480像素范围的则需要先将BMP图片先缩小,再设置位置。显示方式是使用内存映射方
更多资料请点击:我的目录
本篇仅用于记录自己所学知识及应用,代码仍可优化,仅供参考,如果发现有错误的地方,尽管留言于我,谢谢。
这一片是关于开发板800480的LCD显示屏显示BMP图片的,可以通过参数设置,将各种像素大小的BMP图片在任意位置显示,在800480像素范围内的BMP图像可以直接在任意位置显示,而大于800*480像素范围的则需要先将BMP图片先缩小,再设置位置。显示方式是使用内存映射方式(mmap),刷图显示速度比较快。
下面为封装好的BMP图像显示函数
//显示任意位置大小缩放的BMP图片
bool showbmp(char *bmppath, int n) //调用函数传参,bmppath为路径名,n缩小倍数
{
int w = 0;
int h = 0;
int src = open(bmppath , O_RDWR); //打开BMP图片文件
lseek(src, 18 ,SEEK_SET); //获取BMP图片的宽w信息
read(src, &w, 4);
lseek(src, 22 ,SEEK_SET); //获取BMP图片的高h信息
read(src, &h, 4);
char bmpbuf[w*h*3];
int lcdbuf[w*h];
int tempbuf[w*h];
lseek(src, 54, SEEK_SET); //跳过BMP图片头信息字节
int rubbish = (4-(w*3)%4)%4; //BMP图片字节不能被4整除时,加入的垃圾字节数
for(int i = 0; i < h; i++)
{
read(src, &bmpbuf[w*i*3],w*3);
lseek(src, rubbish, SEEK_CUR); //在字节读入时,跳过垃圾字节
}
for(int i = 0; i < w*h; i++) //将RGB转换成BGR
{
lcdbuf[i] = 0x00<<24 | bmpbuf[i*3+2]<<16 | bmpbuf[i*3+1]<<8 | bmpbuf[i*3];
}
for(int i = 0; i < w; i++)
{
for(int j = 0; j < h; j++)
{
tempbuf[(h-1-j)*w+i] = lcdbuf[j*w+i]; //BMP像素点上下反转
}
}
//内存映射
int *mmap_bmp = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, dst, 0);
for(int i=0; i<h/n; i++) //图片的高度h / 缩放倍数n
{
for(int j=w*n*i,k=0; j<(w*n*i+w);j+=n,k++) //循环决定每行该取的像素点
{
//任意位置(480-h/n)/2)、(800-w/n)/2)、缩小倍数n
*(mmap_bmp+800*(((480-h/n)/2)+i)+((800-w/n)/2)+k) = tempbuf[j];
}
}
//解除内存映射
munmap(mmap_bmp, 800*480*4);
close(src);
}
拆分注释:
这个部分是用于解决BMP像素宽度W3字节数不能被4整除时出现下图的情况,因为宽度W3字节数不能被4整除时,系统会在文件每一行的末尾加上无效字节,当我们读取(read)图片文件时就会把无效字节读入,导致出现下图的情况。解决这个问题,只需要计算出每一行加入的无效字节数,在读取文件每一行数据时用lseek跳过那几个无效字节。
int rubbish = (4-(w*3)%4)%4; //BMP图片字节不能被4整除时,加入的垃圾字节数
for(int i = 0; i < h; i++)
{
read(src, &bmpbuf[w*i*3],w*3);
lseek(src, rubbish, SEEK_CUR); //在字节读入时,跳过垃圾字节
}
原图:
这个部分是用于解决BMP图片显示时存在色差的问题,需要将颜色通道重新置位,才能显示正常的图片颜色
for(int i = 0; i < w*h; i++) //将RGB转换成BGR
{
lcdbuf[i] = 0x00<<24 | bmpbuf[i*3+2]<<16 | bmpbuf[i*3+1]<<8 | bmpbuf[i*3];
}
这个部分是用于解决BMP图片显示时图片上下翻转的问题
for(int i = 0; i < w; i++)
{
for(int j = 0; j < h; j++)
{
tempbuf[(h-1-j)*w+i] = lcdbuf[j*w+i]; //BMP像素点上下反转
}
}
这个部分是用于设置任意位置、缩放倍数的,h为BMP图片的高度像素值,w为BMP图片的宽度像素值,n为缩小倍数,不需要缩小时给n传参1,即再下段代码
for(int i=0; i<h/n; i++) //图片的高度h / 缩放倍数n
{
for(int j=w*n*i,k=0; j<(w*n*i+w);j+=n,k++) //循环决定每行该取的像素点
{
//任意位置(480-h/n)/2)、(800-w/n)/2)、缩小倍数n
*(mmap_bmp+800*(((480-h/n)/2)+i)+((800-w/n)/2)+k) = tempbuf[j];
}
}
不需要缩小:
for(int i=0; i<h; i++)
{
for(int j=w*i; j<(w*i+w); j++)
{
*(mmap_bmp+800*(((480-h)/2)+i)+((800-w)/2)+j) = tempbuf[j];
}
}
移位则只需要对这两公式进行更改,可以加入变量,也可以设置为常数,如(480-h)/2),就是用显示屏480的高度像素值减去BMP图片的高度像素值再除以2,让图片刚好显示在纵轴的中间位置,同理(800-w)/2)就是让图片显示在横轴的中间位置。换成常数的话,就是图片的左上角坐标的起始点。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)