更多资料请点击:我的目录
本篇仅用于记录自己所学知识及应用,代码仍可优化,仅供参考,如果发现有错误的地方,尽管留言于我,谢谢。
本篇记录LCD显示屏加入百叶窗特效显示BMP图片,通过双线程并行显示,实现百叶窗特效。在显示函数中,已对BMP图片显示位置进行了居中设置,而缩小倍数只需通过在调用函数时进行传参即可。具体代码如下:
在代码尝试运行的过程中也遇到过问题:lcd多线程显示bmp图片出现内存问题中断
myhead.h部分
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <linux/input.h>
#include <errno.h>
#include <dirent.h>
#ifndef MYHEAD_H
#define MYHEAD_H
int dst; //显示屏驱动
//打开显示屏
int display_open()
{
dst = open("/dev/fb0",O_RDWR); //打开显示屏驱动
if(dst == -1)
{
printf("显示屏打开失败!\n");
return -1;
}
}
//关闭显示屏
int display_close()
{
close(dst);
}
//显示任意位置大小缩放的BMP图片
bool showbmp(char *bmppath, int n)
{
int w = 0;
int h = 0;
int src = open(bmppath , O_RDWR);
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];
int lcdbuf1[] = {0};
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);
pid_t id1;
int status;
id1 = fork();
if(id1 > 0)
{
for(int i=0; i<h/2/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];
}
sleep(0.1);
}
sleep(1);
}
else if(id1 == 0)
{
for(int i=h/2/n-2; 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];
}
sleep(0.1);
}
exit(1);
}
pid_t otherid=waitpid(id1,&status,0); //阻塞等待
//解除内存映射
munmap(mmap_bmp, 800*480*4);
close(src);
}
//设置节点
struct node
{
char *data;
struct node *next;
struct node *prev;
};
//初始化链表
struct node *list_init(char *newdata)
{
struct node *head = malloc(sizeof(struct node));
head->data = newdata;
head->next = head;
head->prev = head;
return head;
}
//创建新节点
struct node *newnode(char *newdata)
{
struct node *new = malloc(sizeof(struct node));
new->data = newdata;
new->next = NULL;
new->prev = NULL;
}
//加入新节点
int addnode(struct node *new,struct node *list)
{
struct node *p = list;
while(p->next != list)
{
p = p->next;
}
new->prev = list->prev;
new->next = list;
list->prev = new;
new->prev->next = new;
}
#endif
main.c部分
#include "myhead.h"
int main()
{
char buf[30];
display_open();
struct node *list = list_init("010.bmp"); //初始化双向循环链表
char *path = "bmp";
DIR *dp = opendir(path);
struct dirent *p;
while(p = readdir(dp)) //遍历目录文件
{
if(p->d_type == DT_REG)
{
if(strstr(p->d_name,".bmp")) //判断是否为.bmp文件
{
struct node *new = newnode(p->d_name); //创建新节点
addnode(new,list); //插入新节点
}
}
}
struct node *head = list->next;
display_open();
while(1)
{
head = head->next;
bzero(buf,20);
sprintf(buf,"%s/%s",path,head->data);
showbmp("background.bmp",1); //背景图刷屏,传参“1”意为原大小显示,“2”即缩小到原来的1/2
showbmp(buf,1); //显示BMP图片,传参“1”意为原大小显示,“2”即缩小到原来的1/2
sleep(1);
}
display_close();
}