相册模块解析

此处专门为相册模块加上解析和效果视频
其实很多事情只是看起来困难,慢慢做起来就会不断有思路了,关键是有目标就要动手
//缩放和图片(花样)展示很多地方都要用到,就在用到的地方写,不特地分开写了

音乐相册

首先是音乐相册

//音乐相册
#include "myiohead.h"

//获取触摸屏坐标
int get_x_y(int *touch_x,int *touch_y)
{
    int flag = 0;

    int to = open ("/dev/input/event0",O_RDWR);
    
    if (-1 == to)
    {
        perror("打开触摸屏的驱动失败!");
        exit(0);
    }

    struct input_event myevent;
    while(1)
    {
        read(to,&myevent,sizeof(struct input_event));
        if (myevent.type == EV_ABS)
        {
            if(myevent.code==ABS_X) //x坐标
            //由于新开发板的坐标范围跟800*480不一致,按比例修正
            //printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
            {
                flag++;
                * touch_x = (myevent.value*800)/1024;
            }
                
            if(myevent.code==ABS_Y) //y坐标
            {
                flag++;
                * touch_y = (myevent.value*480)/600;
            }

            if (2 == flag)
            {
                flag = 0;
                break;
            }
            
        }   
    }
    close(to);
}

//普通展示图片
int showbmp(char *bmppath)
{
	int bmpfd;
	int lcdfd;
	int w,h;
	int i;
	int x,y;
	
	//打开你要显示的w*h大小的bmp
	bmpfd=open(bmppath,O_RDWR);
	if(bmpfd==-1)
	{
		perror("打开图片失败!\n");
		return -1;
	}

	//读取图片的宽和高
	lseek(bmpfd,18,SEEK_SET);
	read(bmpfd,&w,4);//读取宽
	read(bmpfd,&h,4);//读取高

	//定义一个数组,依据图片的大小
	char bmpbuf[w*h*3]; //char占1个字节
	//定义另外一个数组,存放转换得到的ARGB数据
	int lcdbuf[w*h]; //int占4字节
	//定义中间变量。临时存放数据
	int tempbuf[w*h];

	//打开lcd驱动
	lcdfd=open("/dev/fb0",O_RDWR);
	if(lcdfd==-1)
	{
		perror("打开lcd失败!\n");
		return -1;
	}

	//映射得到lcd的首地址
	int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
	if(lcdmem==NULL)
	{
		perror("映射lcd失败!\n");
		return -1;
	}

	
	
	//跳过bmp图片头信息54字节,从55字节开始读取
	lseek(bmpfd,54,SEEK_SET);
	
	//读取bmp图片的RGB数据
	//每三个字节为一组,构成一个像素点的RGB数据
	read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
                                  //    B            G       R	
	                              //bmpbuf[3] bmpbuf[4] bmpbuf[5]  
	//把三个字节--》转换成四个字节
	/*
		细节分析如下:
		    lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
		    lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5] 
	*/
	for(i=0; i<w*h; i++)
		lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
	
	//把颠倒的图片翻转过来
	/*
		细节分析如下:
		    lcdbuf[0] --->lcdbuf[479*800]
			
	*/
	for(x=0; x<w; x++)
		for(y=0; y<h; y++)
			//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
			tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
		
	//把转换后的数据写入lcd中(一一对应)
	for (int j = 0; j < h; j++)
	{
		for(int i = 0,n = 0;i < w;i++)
		{
			*(lcdmem+(j*800)+i)=tempbuf[j*w+i];  
			//n++;           
		}
	}
	
	
	//关闭
	close(bmpfd);
	close(lcdfd);
	return 0;
}

 //定义一个结构体表示双向循环列表,为了省事把此双向链表类型定义为dlist
typedef struct doublelist
{
	char data[100];
	struct doublelist *next;
	struct doublelist *fnext;
}dlist;

dlist * init_list()
{
	dlist *head = calloc(1,sizeof(dlist));
	// head->data = "1.bmp";
	strcpy(head->data, "1.bmp");
	head->next = head;
	head->fnext = head;

	return head;
}

//尾插
int insert_(char * newdata,dlist * head)
{
	dlist * p =head;
	while(p->next != head)
	{
		p = p->next;
	}
	dlist *newnode = calloc(1,sizeof(dlist));
	//newnode->data = newdata;
	strcpy(newnode->data, newdata);
	newnode->next = head;
	p->next = newnode;
	head->fnext = newnode;
	newnode->fnext = p;
}

//读取目录,获得图片名字
int read_dir(char *path,dlist * head)
{
	DIR * dir = opendir(path);
	if (NULL == dir)
	{
		perror("打开目录失败!");
		exit(0);
	}

	struct dirent * rd = NULL;
	while((rd = readdir(dir)) != NULL) 
	{ 
		//printf("d_name : %s\n", rd->d_name); 
		if (rd->d_type == DT_REG)
	 	{
	 		//printf("这是普通文件!\n");
	 		if (strstr(rd->d_name,".bmp") != 0)
	 		{
	 			insert_(rd->d_name,head);
	 		}
	 	}
	 }

	return 0;
}

void * task(void * n)//循环播放相册
{
	dlist * mydlist = init_list();
	read_dir("/myphoto",mydlist);
	char a[100] = "/myphoto/";

	dlist * p =mydlist;
	while(p->next != NULL)
	{
		p = p->next;
		if (p == mydlist)
		{
			p = p->next;
		}
		bzero(a,100);
		strcpy(a,"/myphoto/");
		strcat(a,p->data);
		showbmp(a);
		sleep(1);
	}	
}

void * task1(void * n)
{
	system("mplayer Apologize.mp3 &");
}

int main(int argc, char const *argv[])
{
	pthread_t id;
	pthread_create(&id,NULL,task, NULL);

	pthread_t id1;
	pthread_create(&id1,NULL,task1, NULL);

	int *touch_x = calloc(1,1000);
	int *touch_y = calloc(1,1000);

	while(1)
	{
		get_x_y(touch_x,touch_y);
		if ((*touch_x>742) && (*touch_y<36))
        {
        	pthread_cancel(id);
        	pthread_cancel(id1);
        	system("killall -9 mplayer");
        	raise(9);
           	break;
        }	
	}


	return 0;
}

相册的缩略图

#include "myiohead.h"

//获取滑动方向的触摸屏坐标
int yxget_x_y(int *touch_x,int *touch_x1,int *touch_y,int *touch_y1)
{
    int flag = 1;

    int to = open ("/dev/input/event0",O_RDWR);
    
    if (-1 == to)
    {
        perror("打开触摸屏的驱动失败!");
        exit(0);
    }

    struct input_event myevent;
    int count = 1;
    while(1)
    {   
        read(to,&myevent,sizeof(struct input_event));
        if (myevent.type == EV_ABS)
        {   
            if(myevent.code==ABS_X) //x坐标
            //由于新开发板的坐标范围跟800*480不一致,按比例修正
            //printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
            {   
                * touch_x1 = (myevent.value*800)/1024;
                if (count)
                {
                    * touch_x = (myevent.value*800)/1024;
                    count = 0;
                }                        
                
            }
                
            if(myevent.code==ABS_Y) //y坐标
            {
                * touch_y1 = (myevent.value*480)/600;
                if (flag)
                {
                    * touch_y = (myevent.value*480)/600;
                    flag = 0;
                }
                
                
            }
            
        }

        if(myevent.type==EV_KEY && myevent.code==BTN_TOUCH && myevent.value==0)
        {
            //count = 0;
            //printf("x0=%d,y0=%d\n", *touch_x,*touch_y);
            //printf("x1=%d,y1=%d\n", *touch_x1,*touch_y1);
            break;
        }

    }
    close(to);
}

//花样展示图片
int special_showbmp(char *bmppath)
{
	int bmpfd;
	int lcdfd;
	int i;
	int x,y;
	int w,h;
	
	//打开你要显示的w*h大小的bmp
	bmpfd=open(bmppath,O_RDWR);
	if(bmpfd==-1)
	{
		perror("打开图片失败!\n");
		return -1;
	}

	//读取图片的宽和高
	lseek(bmpfd,18,SEEK_SET);
	read(bmpfd,&w,4);//读取宽
	read(bmpfd,&h,4);//读取高

	//定义一个数组,依据图片的大小
	char bmpbuf[w*h*3]; //char占1个字节
	//定义另外一个数组,存放转换得到的ARGB数据
	int lcdbuf[w*h]; //int占4字节
	//定义中间变量。临时存放数据
	int tempbuf[w*h];

	//打开lcd驱动
	lcdfd=open("/dev/fb0",O_RDWR);
	if(lcdfd==-1)
	{
		perror("打开lcd失败!\n");
		return -1;
	}

	//映射得到lcd的首地址
	int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
	if(lcdmem==NULL)
	{
		perror("映射lcd失败!\n");
		return -1;
	}
	
	//跳过bmp图片头信息54字节,从55字节开始读取
	lseek(bmpfd,54,SEEK_SET);
	
	//读取bmp图片的RGB数据
	//每三个字节为一组,构成一个像素点的RGB数据
	read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
                                  //    B            G       R	
	                              //bmpbuf[3] bmpbuf[4] bmpbuf[5]  
	//把三个字节--》转换成四个字节
	/*
		细节分析如下:
		    lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
		    lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5] 
	*/
	for(i=0; i<w*h; i++)
		lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
	
	//把颠倒的图片翻转过来
	/*
		细节分析如下:
		    lcdbuf[0] --->lcdbuf[479*800]
			
	*/
	for(x=0; x<w; x++)
		for(y=0; y<h; y++)
			//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
			tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
		
	// //把转换后的数据写入lcd中
	// for(int i = 0;i < h;i++)
	// {
	// 	usleep(4000);
	// 	write(lcdfd,&tempbuf[w*i],w*4);
	// 	// *(lcdmem+(j*800)+i)=tempbuf[j*w+i];  
	// 	lseek(lcdfd,(800-w)*4,SEEK_CUR);             
	// }

	//把转换后的数据写入lcd中
	for (int j = 0; j < h; j++)
	{
		usleep(4000);
		for(int i = 0,n = 0;i < w;i++)
		{
			*(lcdmem+(j*800)+i)=tempbuf[j*w+i];  
			//n++;           
		}
	}
	
	//关闭
	close(bmpfd);
	close(lcdfd);
	return 0;
}

//缩放图片
int zoom1_showbmp(char *bmppath,int num)
{
	int bmpfd;
	int lcdfd;
	int w,h;
	
	//打开你要显示的w*h大小的bmp
	bmpfd=open(bmppath,O_RDWR);
	if(bmpfd==-1)
	{
		perror("打开图片失败!\n");
		return -1;
	}

	//读取图片的宽和高
	lseek(bmpfd,18,SEEK_SET);
	read(bmpfd,&w,4);//读取宽
	read(bmpfd,&h,4);//读取高

	//定义一个数组,依据图片的大小
	char bmpbuf[w*h*3]; //char占1个字节
	//定义另外一个数组,存放转换得到的ARGB数据
	int lcdbuf[w*h]; //int占4字节
	//定义中间变量。临时存放数据
	int tempbuf[w*h];

	//打开lcd驱动
	lcdfd=open("/dev/fb0",O_RDWR);
	if(lcdfd==-1)
	{
		perror("打开lcd失败!\n");
		return -1;
	}

	//映射得到lcd的首地址
	int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
	if(lcdmem==NULL)
	{
		perror("映射lcd失败!\n");
		return -1;
	}
	
	//跳过bmp图片头信息54字节,从55字节开始读取
	lseek(bmpfd,54,SEEK_SET);
	
	//读取bmp图片的RGB数据
	//每三个字节为一组,构成一个像素点的RGB数据
	read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
                                  //    B            G       R	
	                              //bmpbuf[3] bmpbuf[4] bmpbuf[5]  
	//把三个字节--》转换成四个字节
	/*
		细节分析如下:
		    lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
		    lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5] 
	*/
	for(int i=0; i<w*h; i++)
		lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
	
	//把颠倒的图片翻转过来
	/*
		细节分析如下:
		    lcdbuf[0] --->lcdbuf[479*800]
			
	*/
	for(int x=0; x<w; x++)
		for(int y=0; y<h; y++)
			//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
			tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
		
	/*//把转换后的数据写入lcd中,高缩小2倍,宽缩小2倍
	for (int j = 0,m = 0; j < (h/2); j++,m = m+2)
	{

		for(int i = 0,n = 0;i < (w/2);i++,n = n+2)
		{
			*(lcdmem+(j*800)+i)=tempbuf[m*w+n];             
		}
	}
	*/

	/* 要做到缩放,就要舍弃一些字节。如果行要缩小2分之1,列也是缩小2分之1,那么
	行每2个只能映射一个,列每2个只能映射一个。一样的道理,如果行要缩小5分之1,列
	要缩小3分之1,那么行每5个只能映射一个,列每3个只能映射一个。(间隔舍弃一些像
	素点,人眼看不出他们太大的差别)*/
	
	// 把转换后的数据写入lcd中,高缩小(h/160)倍,宽缩小w/160倍
	int a = (num%5)*160;//800*480的屏幕一行最多放5张160*160的图片
	int b = (num/5)*160;//800*480的屏幕一行最多放5张160*160的图片
	for (int j = 0,m = 0; j < (h/(h/160)); j = j-b+1,m = m+(h/160))
	{
		j = j+b;//j不能一开始就等于b,所以转个弯
		for(int i = 0,n = 0;i < (w/(w/160));i = i-a+1,n = n+(w/160))
		{
			i = i + a;//i不能一开始就等于a,所以转个弯
			*(lcdmem+(j*800)+i)=tempbuf[m*w+n];             
		}
	}		
	
	//关闭
	close(bmpfd);
	close(lcdfd);
	return 0;
}


//定义一个结构体表示双向循环列表,为了省事把此双向链表类型定义为dlist
typedef struct doublelist
{
	char data[100];
	struct doublelist *next;
	struct doublelist *fnext;
}dlist;

dlist * init_list()
{
	dlist *head = calloc(1,sizeof(dlist));
	// head->data = "1.bmp";
	//strcpy(head->data, "1.bmp");
	head->next = head;
	head->fnext = head;

	return head;
}

//尾插
int insert_(char * newdata,dlist * head)
{
	dlist * p =head;
	while(p->next != head)
	{
		p = p->next;
	}
	dlist *newnode = calloc(1,sizeof(dlist));
	//newnode->data = newdata;
	strcpy(newnode->data, newdata);
	newnode->next = head;
	p->next = newnode;
	head->fnext = newnode;
	newnode->fnext = p;
}

//读取目录,获得图片名字
int read_dir(char *path,dlist * head)
{
	DIR * dir = opendir(path);
	if (NULL == dir)
	{
		perror("打开目录失败!");
		exit(0);
	}

	struct dirent * rd = NULL;
	while((rd = readdir(dir)) != NULL) 
	{ 
		//printf("d_name : %s\n", rd->d_name); 
		if (rd->d_type == DT_REG)
	 	{
	 		//printf("这是普通文件!\n");
	 		if (strstr(rd->d_name,".bmp") != 0)
	 		{
	 			insert_(rd->d_name,head);
	 		}
	 	}
	 }

	return 0;
}



//我的相册缩略图和点击跳转
int myphoto()
{
	int *touch_x1 = calloc(1,1000);
    int *touch_y1 = calloc(1,1000);
    int *touch_x = calloc(1,1000);
    int *touch_y = calloc(1,1000);

	dlist *mydlist=init_list();
	read_dir("/myphoto/",mydlist);
	//我的相片会出现中文名而且特别长,100个字节会溢出,给500个字节
	char a[500] = "/myphoto/";
	int page = 0;
	int count = 0;
	int num = 0;

	//计算总共有多少张图片
	dlist * p = mydlist;
	while(p->next != mydlist)
	{
		p = p->next;
		count++;
	}

	//开头显示第一页缩略图
	int k = 0;
	page = 0;
	p = mydlist;
	while(p->next != mydlist && k<15)
	{	
		k++;
		p = p->next;
		num++;
		bzero(a,500);
		strcpy(a,"/myphoto/");
		strcat(a,p->data);
		zoom1_showbmp(a,num-1);
	}
	num = 0;

	p = mydlist;
	while(1)
	{
		//到while循环的顶部了
		yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);

		//向左划,下一页缩略图
		if((*touch_x>*touch_x1)&&((*touch_x-*touch_x1)>=80))
		{	
			if (count<=15)
			{
				printf("所有图片都在这里了噢。\n");
				continue;
			}

			if (page <= count/15)
			{
				page++;
			}

			if (page > count/15)
			{
				if (count%15 == 0)
				{
					printf("这已经是最后一页了。\n");
					if (page > count/15)
					{
						page--;
					}
					continue;
				}
			}					
			
			p = mydlist;
			for (int i = 0; i < 15*page; i++)
			{
				p = p->next;
			}
			k = 0;		
			while(p->next != mydlist && k<15)
			{	
				k++;
				p = p->next;
				num++;
				bzero(a,500);
				strcpy(a,"/myphoto/");
				strcat(a,p->data);
				zoom1_showbmp(a,num-1);
			}
		}
		num = 0;

		//向右划,上一页
		if( ((*touch_x1-*touch_x) >=80) && (*touch_x1>=*touch_x) )
		{	
			if (page==0)
			{
				printf("当前已经是第一页了。\n");
				continue;
			}
			
			page--;		

			p = mydlist;
			for (int i = 0; i < 15*page; i++)
			{
				p = p->next;
			}
			k = 0;		
			while(p->next != mydlist && k<15)
			{	
				k++;
				p = p->next;
				num++;
				bzero(a,500);
				strcpy(a,"/myphoto/");
				strcat(a,p->data);
				zoom1_showbmp(a,num-1);
			}
		}
		num = 0;

		//跳转点击到的图片
		if( ((*touch_x1-*touch_x) <80) && (*touch_x1>=*touch_x) )
		{
			int h = (*touch_x1/160) + (*touch_y1/160)*5;
			p = mydlist->next;
			for (int i = 0; i < 15*page; i++)
			{
				p = p->next;
			}

			for (int i = 0; i < h; i++)
			{
				if (p->next != mydlist)
				{
					p = p->next;
				}
				else
				{
					printf("当前位置没有对应图片,自动跳转到最后一张图片。\n");
					break;
				}
			}

			bzero(a,500);
			strcpy(a,"/myphoto/");
			strcat(a,p->data);
			special_showbmp(a);
			break;
		}

		//跳转点击到的图片
		if( ((*touch_x-*touch_x1) <80) && (*touch_x>=*touch_x1) )
		{
			int h = (*touch_x1/160) + (*touch_y1/160)*5;
			p = mydlist->next;
			for (int i = 0; i < 15*page; i++)
			{
				p = p->next;
			}

			for (int i = 0; i < h; i++)
			{
				if (p->next != mydlist)
				{
					p = p->next;
				}
				else
				{
					printf("当前位置没有对应图片,自动跳转到最后一张图片。\n");
					break;
				}
			}

			bzero(a,500);
			strcpy(a,"/myphoto/");
			strcat(a,p->data);
			special_showbmp(a);
			break;
		}

		//到while循环的底部了
	}
	
	//printf("退出了我的相册\n");
}

int main(int argc, char const *argv[])
{
	myphoto();
	return 0;
}

用数据结构的链表存储图片路径名,用上文件io,系统编程的知识,综合起来(其实内容挺多的,这里写少了,都写出来就又很复杂了,所以就在阅读代码中理解吧。),就形成了我第一篇博客中的相册模块。

我的第一篇博客链接(相册模块包含其中):
https://blog.csdn.net/weixin_43764094/article/details/107720347

视频效果

我的娱乐系统世界之相册模块

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值