LCD显示屏加入百叶窗特效显示BMP图片

更多资料请点击:我的目录
本篇仅用于记录自己所学知识及应用,代码仍可优化,仅供参考,如果发现有错误的地方,尽管留言于我,谢谢。

本篇记录LCD显示屏加入百叶窗特效显示BMP图片,通过双线程并行显示,实现百叶窗特效。在显示函数中,已对BMP图片显示位置进行了居中设置,而缩小倍数只需通过在调用函数时进行传参即可。具体代码如下:
在代码尝试运行的过程中也遇到过问题:lcd多线程显示bmp图片出现内存问题中断

myhead.h部分

#include 	
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#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();
}

你可能感兴趣的:(系统编程)