天天看點

相冊子產品解析音樂相冊相冊的縮略圖視訊效果

此處專門為相冊子產品加上解析和效果視訊

其實很多事情隻是看起來困難,慢慢做起來就會不斷有思路了,關鍵是有目标就要動手

//縮放和圖檔(花樣)展示很多地方都要用到,就在用到的地方寫,不特地分開寫了

文章目錄

  • 音樂相冊
  • 相冊的縮略圖
  • 視訊效果

音樂相冊

首先是音樂相冊

//音樂相冊
#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

視訊效果

我的娛樂系統世界之相冊子產品

繼續閱讀