基于GEC6818开发板的相册

这篇具有很好参考价值的文章主要介绍了基于GEC6818开发板的相册。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一,实现的功能

1.图片的显示

2.上滑,下滑,左滑,右滑切换图片

3.幻灯片播放相册

4.显示图片的缩略图

二,代码实现

pic.h

#ifndef __PIC__H_
#define __PIC__H_

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/input.h>

typedef enum DIRECTION{
    UP,DOWN,LEFT,RIGHT
}DIRECTION;

typedef struct point{
	int x;
	int y;
}point;

struct node{
	char pics[20];
	struct node *next;
};

struct Linked{
	struct node *first;
	struct node *last;
	int nodeNum;
};

int save_color[800][800];
extern void add_node(struct Linked *l,struct node *p);//增加数据结点
extern struct Linked *Create_link(struct Linked *l);//创建链表存储图片文件名
void show_bmp(int x0,int y0,char * pic,int flag);//显示图片


extern void lcd_draw_point(int x,int y,int color);//画点
extern int get_slip_way();//获取滑动方式
void print_test(struct Linked *l);
void show_mulu(int x0,int y0,struct Linked *l);//显示目录
void lcd_draw_point_mulu(int w,int h,int x,int y,int color);//目录画点
point touch();//获取点击事件
void control();//控制整个程序的运行
int touch_bool();//判断是否点击
void show_left(int i,char *pic);//左滑显示下一张
void show_right(int i,char *pic);//右滑显示上一张
void show_up(int i,char *pic);//上滑显示下一张
void show_down(int i,char *pic);//下滑显示上一张

void play_pic(struct Linked * l);//幻灯片播放

void show_cril(int i,char *pic);//画圆显示


#endif

main.c

#include "pic.h"


int *plcd = NULL;
/*
	lcd_draw_point:画点
		@x:横坐标
		@y:纵坐标
		@color:颜色
*/

void lcd_draw_point(int x,int y,int color)
{
    if(x>=0 && x <800 && y >= 0 && y<480)
    {
        *(plcd+y*800+x) = color;
    }

}

int main()
{

	struct Linked *l = Create_link(l);
    int lcd_fd = open("/dev/fb0",O_RDWR);
    if(lcd_fd == -1)
    {
        perror("open error\n");
        return -1;
    }
    plcd = mmap(NULL,800*480*4,PROT_READ | PROT_WRITE, MAP_SHARED,lcd_fd,0);
    show_bmp(0,0,"mu.bmp",1);
    touch();
	show_mulu(0, 0,l);
	
    munmap(plcd,800*480*4);
    close(lcd_fd);
}

获取滑动方向,控制图片切换

#include "pic.h"

/*
	get_slip_way:获取滑动方向
*/

int get_slip_way()
{
    point p1;
    p1.x = -1;
    p1.y = -1;

    point p2;
    p1.x = -1;
    p1.y = -1;

    int fd = open("/dev/input/event0",O_RDWR);
    if(fd == 0)
    {
        perror("open error\n");
        return -1;
    }

    struct  input_event ev;

    int ret;
    int flag = 0;
    int count = 0;
    while(1)
    {
        ret = read(fd,&ev,sizeof(ev));
        if(ret != sizeof(ev))
        {
            close(fd);
            perror("read error");
            return -1;
        }
   
        //判断触摸事件,并获取X值
        if(ev.type == EV_ABS && ev.code == ABS_X)
        {
            if(p1.x < 0)
            {
                p1.x = ev.value;
            }
            else
            {
                p2.x = ev.value;
            }
        }
        if(ev.type == EV_ABS && ev.code == ABS_Y)
        {
            if(p1.y < 0)
            {
                p1.y = ev.value;
            }
            else
            {
                p2.y = ev.value;
            }
        }

        if(ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value==0)
        {
            int dt_x = abs(p1.x - p2.x);
            int dt_y = abs(p1.y - p2.y);

            if(dt_x > 2*dt_y)
            {
                if(p1.x > p2.x)
                {
                    return LEFT;
                }
                if(p1.x < p2.x)
                {
                    return RIGHT;
                }
            }
            else if (2*dt_x < dt_y)
            {
                if(p1.y > p2.y)
                {
                    return UP;
                }
                if(p1.y < p2.y)
                {
                    return DOWN;
                }
            }
            else
            {
                p1.x = -1;
                p1.y = -1; 
                p2.x = -1;
                p2.y = -1; 
            }
            
        }
    }
}

/*
	control:控制图片的转换


*/
void control()
{

	char pic[100] = {0};
	int i = 1;
	struct Linked *l = Create_link(l);
	while(1)
	{
		DIRECTION x = get_slip_way();
		switch (x)
		{
			case UP: 
				if(++i >= 14)
				{
					i = 1;
				}
				show_cril(i,pic);
				show_bmp(0,0,"100.bmp",1);
				break;
			case LEFT:
				if(++i >= 14)
				{
					i = 1;
				}
				show_left(i,pic);
				show_bmp(0,0,"100.bmp",1);
				break;
			case DOWN:
				if(--i == 0)
				{
					i = 13;
				}
				show_down(i,pic);
				show_bmp(0,0,"100.bmp",1);
				break;
			case RIGHT:
				if(--i == 0)
				{
					i = 13;
				}
				show_right(i,pic);
				show_bmp(0,0,"100.bmp",1);
				break;
		
			default:
				break;
		}

		point p = touch();
		printf("x = %d y = %d\n",p.x,p.y);
		if(p.x>=0&&p.x<90&&p.y>=0&&p.y<90)
		{
			show_mulu(0, 0, l);
			show_bmp(360, 0, "play.bmp", 1);
			p = touch();
			printf("x = %d y = %d\n",p.x,p.y);
			if(p.x>360&&p.x<=460&&p.y>=0&&p.y<=90)
			{

				play_pic(l);
			}
		}

	
		
	}


}

幻灯片播放

#include "pic.h"

/*
	play_pic:播放图片
		@l:存储数据的链表
*/

void play_pic(struct Linked *l)
{
	
	struct node *p = l->first;
	int flag = 1;//控制不同的播放方式
	char pic[100];
	int i = 1;
	while(p)
	{
		if(flag == 1)
		{
			show_down(i,pic);
			flag++;
		}else if(flag == 2)
		{
			show_left(i,pic);
			flag++;
		}else if(flag == 3)
		{
			show_up(i,pic);
			flag++;
		}else if(flag == 4)
		{
			show_right(i,pic);
			flag ++;
		}else if(flag == 5)
		{
			flag = 1;
		}
		
		i++;
 		p = p->next;
	}
	
}

保存图片到链表

#include "pic.h"
/*
	add_node:增加数据结点
		@l:要添加到的链表
		@p:需要添加的数据结点
*/
void add_node(struct Linked *l,struct node *p)
{
	if(l->first == NULL && l->last == NULL)
	{
		l->first = p;
		l->last = p;
		l->nodeNum++;
	}
	else
	{
		l->last->next = p;
		l->last = p;
		l->nodeNum++;
	}

}

/*
	Create_link:创建链表
		@l:初始化的链表
*/
struct Linked *Create_link(struct Linked *l)
{
	l = malloc(sizeof(*l));
	l->first = NULL;
	l->last = NULL;
	l->nodeNum = 0;
	int i = 1;
	while(1)
	{
		struct node *p = malloc(sizeof(*p));
		sprintf(p->pics,"%d.bmp",i);
		puts(p->pics);
		p->next = NULL;
		add_node(l,p);
		i++;
		if(i == 13)
		{
			break;
		}
	}

	return l;

}
/*
	print_test:打印链表数据
		@l:打印的链表
*/

void print_test(struct Linked *l)
{
	struct node *p = l->first;
	while(p)
	{
		puts(p->pics);
		p = p->next;
	
	}


}

显示图片

#include "pic.h"

/*
	show_cril:圆形切换
		@i:图片的名字
		@*pic:空数组用来存储完整文件名

*/
void show_cril(int i,char *pic)
{
	sprintf(pic,"%d.bmp",i);
	puts(pic);
	show_bmp(0, 0,pic,0);
	int num = 0;
	int r = 15;
	for(int k=0;k<35;k++)
	{
		for(int m=0;m<480;m++)
		{
			for(int n=0;n<800;n++)
			{
				if((m-240)*(m-240)+(n-400)*(n-400)<=r*r*num)
				lcd_draw_point(n, 479-m, save_color[m][n]);
			}
		}
		num = num+30;
	}


}

/*
	show_left:图片从右向左覆盖
		@i:图片的名字
		@*pic:空数组用来存储完整文件名

*/

void show_left(int i,char *pic)
{
	sprintf(pic,"%d.bmp",i);
	 puts(pic);
	show_bmp(0, 0,pic,0);
	for(int m=799;m>=0;m--)
	{
		for(int n=479;n>=0;n--)
		{

			lcd_draw_point(m, 479-n, save_color[n][m]);
		}
		usleep(5);
	}
}


/*
	show_up:图片从上向下覆盖
		@i:图片的名字
		@*pic:空数组用来存储完整文件名

*/

void show_up(int i,char *pic)
{
	sprintf(pic,"%d.bmp",i);
	puts(pic);
	show_bmp(0, 0,pic,0);
	for(int m=0;m<480;m++)
	{
		for(int n=0;n<800;n++)
		{
			lcd_draw_point(n, 479-m, save_color[m][n]);
		}
		usleep(5);
	}

}

/*
	show_down:图片从下向上覆盖
		@i:图片的名字
		@*pic:空数组用来存储完整文件名

*/

void show_down(int i,char *pic)
{
	sprintf(pic,"%d.bmp",i);
	 puts(pic);
	show_bmp(0, 0,pic,0);
	for(int m=479;m>=0;m--)
	{
		for(int n=0;n<800;n++)
		{
			lcd_draw_point(n, 479-m, save_color[m][n]);
		}
		usleep(5);
	}


}

/*
	show_right:图片从左向到覆盖
		@i:图片的名字
		@*pic:空数组用来存储完整文件名

*/

void show_right(int i,char *pic)
{
	sprintf(pic,"%d.bmp",i);
	show_bmp(0, 0,pic,0);
	for(int m=0;m<800;m++)
	{
		for(int n=0;n<480;n++)
		{

			lcd_draw_point(m, 479-n, save_color[n][m]);
		}
		usleep(5);
	}
}

/*
	show_bmp:显示图片
		@x0:初始横坐标
		@y0:初始纵坐标
		@*pic:图片文件名
		@flag:为0保存像素,为1立即显示

*/


void show_bmp(int x0,int y0,char * pic,int flag)
{
    int fd = open(pic,O_RDWR);
    int hight,width;
    short depth;
    unsigned char buf[4] = {0};

    lseek(fd,0x0A,SEEK_SET);
    read(fd, buf,4);
	int save = buf[3] <<24 | buf[2] <<16 | buf[1]<<8 |buf[0] <<0;
  
    lseek(fd,0x12,SEEK_SET);
    read(fd, buf,4);
    width = buf[3] <<24 | buf[2] <<16 | buf[1]<<8 |buf[0] <<0;
    
    lseek(fd,0x16,SEEK_SET);
    read(fd, buf,4);
    hight = buf[3] <<24 | buf[2] <<16 | buf[1]<<8 |buf[0] <<0;
    
    lseek(fd,0x1c,SEEK_SET);
    read(fd, buf,2);
    depth = buf[1] <<8 | buf[0];

	
    int laizi = 0;
    if((width/8) % 4 != 0)
    {
        laizi = 4 - (width/8)%4;
    }

    int  real_width = laizi + abs(width);
    int total_by = real_width *abs(hight) *(depth/8);

    unsigned char* pixel = malloc(total_by);

    lseek(fd,54,SEEK_SET);
    read(fd,pixel,total_by);
    int m ,n,i = 0;
    unsigned int a,r,g,b;
    int color;
    printf("hight= %d, width = & %d\n",hight,width);
    for(m = 0;m<abs(hight);m++)
    {
        for(n=0;n<abs(width);n++)
        {
            b = pixel[i++];
            g = pixel[i++];
            r = pixel[i++];

            if(depth == 24)
            {
                a = 0;
            }
            else if (depth == 32 )
            {
                a = pixel[i++];
            }
            color = a<<24 | r <<16 | g<<8 | b;
			save_color[m][n] = color;
			if(flag==1)
			{
           		 lcd_draw_point( width>0 ?  x0+n : x0+abs(width)-n-1,hight>0? y0+hight-m-1 : y0+m,color);
         	 }
        }
        i  = i +laizi;
        usleep(50);
    }

    free(pixel);
    close(fd);
}


/*
	show_bmp_small:显示目录缩略图
		@x0:初始横坐标
		@y0:初始纵坐标
		@*pic:图片文件名

*/

void show_bmp_small(double x0,double y0,char * pic)
{
    int fd = open(pic,O_RDWR);
    int hight,width;
    short depth;
    unsigned char buf[4] = {0};

    lseek(fd,0x0A,SEEK_SET);
    read(fd, buf,4);
	int save = buf[3] <<24 | buf[2] <<16 | buf[1]<<8 |buf[0] <<0;
  
    lseek(fd,0x12,SEEK_SET);
    read(fd, buf,4);
    width = buf[3] <<24 | buf[2] <<16 | buf[1]<<8 |buf[0] <<0;
    
    lseek(fd,0x16,SEEK_SET);
    read(fd, buf,4);
    hight = buf[3] <<24 | buf[2] <<16 | buf[1]<<8 |buf[0] <<0;
    
    lseek(fd,0x1c,SEEK_SET);
    read(fd, buf,2);
    depth = buf[1] <<8 | buf[0];

	
    int laizi = 0;
    if((width/8) % 4 != 0)
    {
        laizi = 4 - (width/8)%4;
    }

    int  real_width = laizi + abs(width);
    int total_by = real_width *abs(hight) *(depth/8);

    unsigned char* pixel = malloc(total_by);

    lseek(fd,54,SEEK_SET);
    read(fd,pixel,total_by);
    int m ,n,i = 0;
    unsigned int a,r,g,b;
    int color;
    for(m = 0;m<abs(hight);m=m+1)
    {
        for(n=0;n<abs(width);n=n+1)
        {
            b = pixel[i++];
            g = pixel[i++];
            r = pixel[i++];
			
            if(depth == 24)
            {
                a = 0;
            }
            else if (depth == 32 )
            {
                a = pixel[i++];
            }
            color = a<<24 | r <<16 | g<<8 | b;

       		lcd_draw_point( width>0 ?  (x0+n)/4.0 : (x0+abs(width)-n-1)/4.0,hight>0? (y0+hight-m-1)/3.0 : (y0+m)/3.0,color);
        }
        i  = i +laizi;
       
    }

    free(pixel);
    close(fd);
}


/*
	show_mulu:显示图片
		@x0:初始横坐标
		@y0:初始纵坐标
		@l :保存着图片文件名的链表

*/

void show_mulu(int x0,int y0,struct Linked *l)
{
	struct node *p = l->first;
	int w=0;
	int h=0;
	int flag = -1;
	while(p)
	{
		show_bmp_small(w*4, h*3, p->pics);
		w = w + 200;
		usleep(5);
		if(w==800)
		{
			w = 0;
			h = h +160;
		}
 		p = p->next;
	}
	show_bmp(360, 0, "play.bmp", 1);
	point p1 = touch();
	printf("x = %d y = %d\n",p1.x,p1.y);
	if(p1.x>360&&p1.x<=440&&p1.y>=0&&p1.y<=90)
	{

		play_pic(l);
	}
	if(p1.x>=0&&p1.x<200 && p1.y>=0&&p1.y<=160)
	{
		flag = 1;
	}
	if(p1.x>=200&&p1.x<400&& p1.y>=0&&p1.y<=160)
	{
		flag = 2;
	}
	if(p1.x>=400&&p1.x<600 && p1.y>=0&&p1.y<=160)
	{
		flag = 3;
	}
	if(p1.x>=600&&p1.x<800 && p1.y>=0&&p1.y<=160)
	{
		flag = 4;
	}
	if(p1.x>=0&&p1.x<200 && p1.y>=160&&p1.y<=320)
	{
		flag = 5;
	}
	if(p1.x>=200&&p1.x<400&& p1.y>=160&&p1.y<=320)
	{
		flag = 6;
	}
	if(p1.x>=400&&p1.x<600 && p1.y>=160&&p1.y<=320)
	{
		flag = 7;
	}
	if(p1.x>=600&&p1.x<800 && p1.y>=160&&p1.y<=320)
	{
		flag = 8;
	}
	if(p1.x>=0&&p1.x<200 && p1.y>=320&&p1.y<=480)
	{
		flag = 9;
	}
	if(p1.x>=200&&p1.x<400&& p1.y>=320&&p1.y<=480)
	{
		flag = 10;
	}
	if(p1.x>=400&&p1.x<600 &&  p1.y>=320&&p1.y<=480)
	{
		flag = 11;
	}
	if(p1.x>=600&&p1.x<800 &&  p1.y>=320&&p1.y<=480)
	{
		flag = 12;
	}

	char pic[32] = {0};
	sprintf(pic,"%d.bmp",flag);
	show_bmp(0,0,pic,1);
	show_bmp(0,0,"100.bmp",1);
	control();
	
	
}

触屏判断文章来源地址https://www.toymoban.com/news/detail-519037.html

#include "pic.h"

/*
	touch:获得点击事件
	@retval:点击的坐标

*/

point touch()
{
    point p;
    p.x = -1;
    p.y = -1;

    int fd = open("/dev/input/event0",O_RDWR);
    if(fd == 0)
    {
        perror("open error\n");
        return p;
    }

    struct  input_event ev;

    int ret;
    while(1)
    {
        ret = read(fd,&ev,sizeof(ev));
        if(ret != sizeof(ev))
        {
            close(fd);
            perror("read error");
            return p;
        }
   
        //判断触摸事件,并获取X值
        if(ev.type == EV_ABS && ev.code == ABS_X)
        {
            if(p.x < 0)
            {
                p.x = ev.value*(800.0/1024);//EV_ABS默认1024,600
            }
        }
        if(ev.type == EV_ABS && ev.code == ABS_Y)
        {
            if(p.y < 0)
            {
                p.y = ev.value*(480.0/600);
       
            }
        }

        if(p.x>=0&&p.y>=0)
        {
            close(fd);
            return p;
        }
    }
}

/*
	touch_bool:判断是否点击

*/

int touch_bool()
{
	point p;
	p.x = -1;
	p.y = -1;
	int fd = open("/dev/input/event0",O_RDWR);
    if(fd == 0)
    {
        perror("open error");
        return 0;
    }

    struct input_event ev;
    int ret;
	int flag = -1;
    while(1)
    {
    	ret = read(fd,&ev,sizeof(ev));
    	if(ret != sizeof(ev))
    	{
    		close(fd);
			perror("read error");
			return 0;
    	}
    	if(ev.type == EV_ABS && ev.code == ABS_X)
    	{
			return 1;
    	}

    	if(ev.type == EV_ABS && ev.code == ABS_Y);
    	{
			return 1;
    	}

    	if(p.x>=0 && p.y>=0)
    	{
			return 0;
    	}

    }
    
}

到了这里,关于基于GEC6818开发板的相册的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于GEC6818的智能火锅点餐系统

    本次项目开发环境:gec6818,QT5.14.2,SecureCRT。 所使用的相关技术:c/s架构,STL库,C++封装,标准化代码编写 实现的功能:用户登录页面,食品分区在不同页面,用户点餐页面,用户买单页面,数据整合并发送至后台,后台成功接受数据,返回主页面。 1、gec6818开发板的特点

    2024年02月12日
    浏览(35)
  • 粤嵌 GEC-6818 蓝牙智能家庭影音 arm开发记录

    注意:未经允许不得转载,引用请注明出处 文件操作:创建、删除、复制、移动 环境:VMware15.5,ubantu16.04,串口驱动HI-340,secureCRT 设置共享文件夹,设置后ubantu系统和windows系统可以共享使用该文件夹里面的内容。 1.gcc编译:将c文件进行编译 2.交叉编译:将c文件编译成arm文

    2024年01月22日
    浏览(79)
  • 语音识别开源库 FastARS 移植到GEC6818开发版

    移植 安装fftw3 移植 OpenBLAS 移植 FastARS 3.编写交叉编译的cmake 脚本 4.生成makefile 脚本 5.编译安装 6.进入 examples 目录看看是否成功生成   1.把生成的 k2_rnnt2_cli 下载到开发板的 /bin 目录 2.把所有的库文件下载到开发板的 /lib 目录     3.下载语音网络模型到开发版中 (模型转换请看

    2023年04月23日
    浏览(30)
  • LCD(GEC6818)

    此篇博客是基于GEC6818开发板使用 1、液晶屏的基本概念 像素:屏幕上显示颜色的最小单位,英文叫pixel。注意,位图(jpg,bmp等格式的常见图片)也是由一个个的像素点构成的,跟屏幕的像素点的概念一样。原理上讲,将一张位图显示到屏幕上,就是将图片上的像素点一个个

    2024年02月09日
    浏览(32)
  • GEC6818科大讯飞离线语音识别

    在下载SDK时需要注意选择Linux的版本!! 在官网下载离线语音的包,解压后可以得到下面的一些文件夹: 解压后你需要知道自己命令放在下面的文件夹中 关于Make file文件: 关于asr_offline_sample.c文件: asr_offline_sample.c 文件是我们更改为自己的逻辑的文件,但是也不需要都了解

    2024年01月17日
    浏览(53)
  • 粤嵌Gec6818---小项目功能实现(RFID+图片显示+音乐+视频)

    项目设计开发环境: (1)VMware Workstation Pro软件 (2)ubuntu12 .04 (能交叉编译就行) (3)SecureCRT  (4)代码编译器(notepad++/Visual Studio Code) 项目功能描述: (1)幻灯片:开始进行图片幻灯片显示,结束后进入RFID刷卡开锁界面。 (2)RFID:刷卡成功和刷卡失败两种状态(

    2024年02月08日
    浏览(50)
  • OpenHarmony开发实战:电子相册(ArkTS)

    本篇Codelab介绍了如何实现一个简单的电子相册应用的开发,主要功能包括: 实现首页顶部的轮播效果。 实现页面跳转时共享元素的转场动画效果。 实现通过手势控制图片的放大、缩小、左右滑动查看细节等效果。 相关概念 Swiper:滑块视图容器,提供子组件滑动轮播显示的

    2024年04月28日
    浏览(37)
  • 粤嵌Gec6818---小项目功能实现简单步骤(RFID+图片显示+音乐+视频)

    项目设计开发环境: (1)VMware Workstation Pro软件 (2)ubuntu12 .04 (能交叉编译就行) (3)SecureCRT  (4)代码编译器(notepad++/Visual Studio Code) 项目功能描述: (1)幻灯片:开始进行图片幻灯片显示,结束后进入RFID刷卡开锁界面。 (2)RFID:刷卡成功和刷卡失败两种状态(

    2024年02月04日
    浏览(34)
  • 6.串口通信和传感器的使用----粤嵌gec6818开发板上实现智能家居(光照气度,压强,海拔,湿度,温度达到临界值蜂鸣器自动警报等)

    串口是一种简单的通信接口,也是单片机中最常用,最简单的通信方式 通常传感器都是采用串口作为与上位机的通信接口 ARM板上提供了三个可以外接传感器的串口接口,位于开发板的右上角, 从上到下分别是: ​ 串口号 串口驱动设备文件名 ​ CON2 “/dev/ttySAC1” ​ CON3 “

    2024年02月16日
    浏览(144)
  • GEC6818网络编程——服务器端与客户端tcp的双向通信

    网络编程之实现服务器和客户端的tcp双向通信,前面是双向通信的详细流程介绍,后面附上完整的代码o(  ̄▽ ̄ )ブ 1.1 服务器端双向通信的详细流程叙述 创建TCP套接字 : 使用 socket 函数创建一个TCP套接字。这里使用了IPv4地址族 AF_INET 和流式套接字 SOCK_STREAM 。 绑定IP和端口

    2024年02月21日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包