相册模块解析

编程入门 行业动态 更新时间:2024-10-25 18:31:47

相册<a href=https://www.elefans.com/category/jswz/34/1771428.html style=模块解析"/>

相册模块解析

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

文章目录

  • 音乐相册
  • 相册的缩略图
  • 视频效果

音乐相册

首先是音乐相册

//音乐相册
#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大小的bmpbmpfd=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大小的bmpbmpfd=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大小的bmpbmpfd=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,系统编程的知识,综合起来(其实内容挺多的,这里写少了,都写出来就又很复杂了,所以就在阅读代码中理解吧。),就形成了我第一篇博客中的相册模块。

我的第一篇博客链接(相册模块包含其中):

视频效果

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

更多推荐

相册模块解析

本文发布于:2024-03-08 10:35:08,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1720633.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模块   相册

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!