粤嵌Linux GEC6818开发板实现电子相册

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

前言

最近学校要求使用粤嵌的开发板实现电子相册,具体的功能要有点击特定的区域实现上一张、下一张、自动播放图片、黑屏退出应用程序、左右滑动切换图片相关功能。其中涉及到的知识点也比较多(文件IO、内存映射、触摸屏、bmp图片格式、进程、线程创建和同步、字符串操作等)。为理清思路和复习去年学的Linux C应用编程知识,特写下此文进行回顾和总结。

先看看效果

粤嵌Linux GEC6818开发板实现电子相册

整个工程文件和使用到的图片在下方链接

门牙会稍息 / 粤嵌GEC 6818开发板实现简易电子相册和音乐播放器 · GitCode

一:内存映射

存储映射 I/O(memory-mapped I/O)是一种基于内存区域的高级 I/O 操作,它能将一个文件映射到进程地址空间中的一块内存区域中,当从这段内存中读数据时,就相当于读文件中的数据(对文件进行 read 操作),将数据写入这段内存时,则相当于将数据直接写入文件中(对文件进行 write 操作)。用到的两个函数是mmap和munmap,函数原型如下:

linux电子相册,Linux,linux,学习,arm开发,c语言

简言之addr设置为NULL的话内核会自动找一内存空间,大小就是length,粤嵌的屏是800*480的,所以length就是800*480*4,4代表一个像素点由四字节构成(ARGB),port参数设为PROT_READ、PROT_WRITE就是可读可写,flags描述的是映射区的属性。

linux电子相册,Linux,linux,学习,arm开发,c语言

 二:BMP格式图片

linux电子相册,Linux,linux,学习,arm开发,c语言

 用hexdump查看一下bmp图片的数据(高度和宽度)

linux电子相册,Linux,linux,学习,arm开发,c语言

LCD屏显示BMP格式图片的函数

/**
 *lcd屏显示bmp格式图片函数
 *@param     pathname    图片名字
 *@param     x0          图片在LCD上显示的x起点坐标
 *@param     y0          图片在LCD上显示的y起点坐标
 *@return    函数返回值
 */
int lcd_show_bmp(char *pathname, int x0, int y0)
{
	//1、打开设备文件
	int lcd = open("/dev/fb0", O_RDWR);
	if(-1 == lcd)
	{
		printf("lcd open error!\n");
		return -2;
	}
	
	//2、内存映射
	char *ptr =  (char *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, 
	                MAP_SHARED, lcd, 0);
	if(NULL == ptr)
	{
		printf("mmap error!\n");
		return -3;
	}
	//清除背景色
	//bzero(ptr, 800*480*4);
	
	//打开图片
	int bmp = open(pathname, O_RDWR);
	if(-1 == bmp)
	{
		printf("bmp open error!\n");
		return -2;
	}
	
	//读取图片相关信息
	int bmp_size, bmp_width, bmp_height;
	//大小
	lseek(bmp, 2, SEEK_SET);
	read(bmp, &bmp_size, sizeof(bmp_size));
	
	//宽度和高度
	lseek(bmp, 18, SEEK_SET);
	read(bmp, &bmp_width, sizeof(bmp_width));
	read(bmp, &bmp_height, sizeof(bmp_height));
	
	//读取图片的颜色数据
	lseek(bmp, 54, SEEK_SET);
	char *bmp_buf = malloc(bmp_size);	//申请空间
	read(bmp, bmp_buf, bmp_width*bmp_height*3);

	
	//对颜色数据进行处理(上下颠倒以及数据混乱)
	int bmp_sum = 0;
	int lcd_sum = 0;
	for(int y=0; y+y0<480 && y<bmp_height; y++)
	{
		for(int x=0; x+x0<800 && x<bmp_width; x++)
		{
			bmp_sum = 3*(x+((bmp_height-1-y)*bmp_width));
			lcd_sum = 4*(800*(y+y0)+x+x0);
			
			//等号的坐标属于lcd屏幕, 等号的右边是bmp图像数据
			ptr[lcd_sum+0] = bmp_buf[bmp_sum+0]; //蓝色数据
			ptr[lcd_sum+1] = bmp_buf[bmp_sum+1]; //绿色数据
			ptr[lcd_sum+2] = bmp_buf[bmp_sum+2]; //红色数据
			ptr[lcd_sum+3] = bmp_buf[bmp_sum+3]; //透明度数据
		}
		//usleep(1);
	}
    //释放相关资源
	munmap(ptr, 800*480*4);
	free(bmp_buf);
	//3、关闭文件
	close(lcd);
	close(bmp);
}

 三:input_event接收触摸屏上报值

linux电子相册,Linux,linux,学习,arm开发,c语言

用hexdump命令查看触摸屏上报值

linux电子相册,Linux,linux,学习,arm开发,c语言

linux电子相册,Linux,linux,学习,arm开发,c语言

 此实验用到input子系统中的type、code(下面的图片来源Linux内核中的input.h文件)

linux电子相册,Linux,linux,学习,arm开发,c语言

linux电子相册,Linux,linux,学习,arm开发,c语言

linux电子相册,Linux,linux,学习,arm开发,c语言

获取触摸屏坐标返回值函数

/**
 *获取触摸屏坐标返回值函数
 *param    NULL
 *return   NULL
 */
void get_touch()
{
    //打开设备文件
    int touch_fd = open("/dev/input/event0", O_RDONLY);
    if(-1 == touch_fd)
    {
        printf("event0 open error!\n");
    }

    while(1)
    {
        read(touch_fd, &ts, sizeof(ts));
	    //获取X、Y坐标
        if(EV_ABS == ts.type) //判断是否为触摸屏事件
        {
            if(ABS_X == ts.code)//判断是否为x轴数据
            {
                ts_x = ts.value;
                flag_x = 1;	
            }
            else if(ABS_Y == ts.code) //判断是否为y轴数据
            {
                ts_y = ts.value;
                flag_y = 1;
            }
        }

	if(EV_KEY == ts.type)
	{
		//刚触碰的坐标/长按时
		if(ts.code == BTN_TOUCH && ts.value == 1)
		{
			old_x = ts_x;
			first_press_flag = 1;
		}
	}
	
	if(flag_x == 1 && flag_y == 1 && first_press_flag == 1) 
        {
		flag_x = 0;
		flag_y = 0;
		pthread_mutex_lock(&mutex);
		flag_x_y = 1;  
		//黑色底板才需要执行如下操作
		ts_x = ts_x*800/1024;
		ts_y = ts_y*480/600; 
		pthread_mutex_unlock(&mutex);
		pthread_cond_signal(&cond);
		//break;                    
        }

    if(EV_KEY == ts.type)
	{
		//松开
		if(ts.code == BTN_TOUCH && ts.value == 0)
		{
			//从左到右的滑动
			if(((ts_x > old_x) && (ts_x - old_x > 150) && (ts_x < 600)))
			{
				right_left_slide_flag = 1;
				slider_right = 1;			
				old_x = 300;
			}	
			//从右到左的滑动
			else if(((old_x > ts_x) && (old_x - ts_x > 150) && (old_x < 600)))
			{
				
				right_left_slide_flag = 1;
				slider_left = 1;
				old_x = 300;
			}
		}
	}

    }
    //4、关闭文件
    close(touch_fd);
}

四:创建线程,处理触摸屏坐标数据

阻塞式 I/O 的优点在于能够提升 CPU 的处理效率,当自身条件不满足时,进入阻塞状态,交出 CPU资源,将 CPU 资源让给别人使用;而非阻塞式则是抓紧利用 CPU 资源,譬如不断地去轮训,这样就会导致该程序占用了非常高的 CPU 使用率!我这里是想获得触摸点坐标之后再做相关的操作,当没有按下触摸屏的时候,相关线程就会阻塞挂起,节约资源,线程同步中使用互斥锁和条件变量就可以实现。

左右滑动线程处理函数:

void *right_left_slide_func(void *arg)
{
	printf("enter right_left_slide_func\r\n");
	while(1){
		if(right_left_slide_flag == 1){
			if(slider_left == 1){
				touch_flag--;
				if(touch_flag <= 0)
					touch_flag = BMP_MAX_NUMBER;
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				slider_left = 0;
				right_left_slide_flag == 0;
			}
			else if(slider_right == 1){
				touch_flag++;
				if(touch_flag > BMP_MAX_NUMBER)
					touch_flag = 1;
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				slider_right = 0;
				right_left_slide_flag == 0;
			}
			right_left_slide_flag == 0;
		}	
	}
}

右侧选项框线程处理函数:

void *area_switch(void *arg)
{
	printf("enter area_switch\r\n");
	while(1){
		pthread_mutex_lock(&mutex);

		while(flag_x_y == 0)
			pthread_cond_wait(&cond, &mutex);
		while(flag_x_y == 1){
			//上一张
			if((ts_y > 0 && ts_y < 120) && (ts_x > 600))
			{
				touch_flag--;
				if(touch_flag <= 0)
					touch_flag = BMP_MAX_NUMBER;
		
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				ts_x = 0;
				ts_y = 0;
			}
			//下一张
			else if((ts_y > 120 && ts_y < 240) && (ts_x > 600))
			{
				touch_flag++;
				if(touch_flag > BMP_MAX_NUMBER)
					touch_flag = 1;
		
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				ts_x = 0;
				ts_y = 0;
			}
			//幻灯片
			else if((ts_y > 240 && ts_y < 360) && (ts_x > 600))
			{
				printf("click slider photo\r\n");
				if(slider_flag == 0){
					slider_flag = 1;
				}
				else{
					slider_flag = 0;
				}
				printf("slider_flag = %d\r\n", slider_flag);
				ts_x = 0;
				ts_y = 0;
			}
			//息屏
			else if((ts_y > 360 && ts_y < 480) && (ts_x > 600))
			{
				char command[] = "kill -9 ";
				char str[10];
				sprintf(str, "%d", pid);
				strcat(command, str);
				printf("command = %s\r\n", command);
				//方式一:显示一张黑色的图片
				lcd_show_bmp("black.bmp", 0, 0);
				system(command);
			}
			else{
				flag_x_y = 0;
				break;
			}
			flag_x_y = 0;
		}

		pthread_mutex_unlock(&mutex);
	}
	
}

 自动播放图片线程处理函数:

void *slider_func(void *arg)
{
	printf("enter slider_func : %d\r\n", pthread_self());
	while(1){
		if(slider_flag == 1){
			printf("enter slider_func\r\n");
			touch_flag++;
			if(touch_flag > BMP_MAX_NUMBER)
				touch_flag = 1;
			lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
			sleep(1);
		}
	}
}

五:Main函数

main函数就是一些线程、互斥锁、条件变量的创建和回收

int main()
{
	lcd_show_bmp("choice.bmp", 600, 0);
	lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
	pthread_t tid, tid_area_switch, tid_right_left_slide;
	int ret = 0;
	
	pthread_create(&tid, NULL, slider_func, NULL);
	pthread_create(&tid_area_switch, NULL, area_switch, NULL);
	pthread_create(&tid_right_left_slide, NULL, right_left_slide_func, NULL);

	pthread_mutex_init(&mutex, NULL);
	pthread_cond_init(&cond, NULL);
	
	printf("main thread = %ld\r\n", pthread_self());
	pid = getpid();
	printf("pid = %d\r\n", pid);

	while(1){
		get_touch();
	}
	
	
	pthread_join(tid, NULL);
	pthread_join(tid_area_switch, NULL);
	pthread_join(tid_right_left_slide, NULL);
	pthread_cond_destroy(&cond);
	exit(0);

}

六:完整代码

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

#define BMP_MAX_NUMBER 4

char bmp_path[4][100] = {"1.1.bmp", "1.2.bmp", "1.3.bmp", "1.4.bmp"};
int slider_flag = 0;
pid_t pid;
pthread_mutex_t mutex;
pthread_cond_t cond;
//自定义函数:LCD屏幕显示bmp图片
//pathname:需要打开的图片路径
//x0:存放图片显示的x轴起点
//y0:存放图片显示的y轴起点
int lcd_show_bmp(char *pathname, int x0, int y0)
{
	//1、打开设备文件
	int lcd = open("/dev/fb0", O_RDWR);
	if(-1 == lcd)
	{
		printf("lcd open error!\n");
		return -2;
	}
	
	//2、内存映射
	char *ptr =  (char *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, 
	                MAP_SHARED, lcd, 0);
	if(NULL == ptr)
	{
		printf("mmap error!\n");
		return -3;
	}
	//清除背景色
	//bzero(ptr, 800*480*4);
	
	//打开图片
	int bmp = open(pathname, O_RDWR);
	if(-1 == bmp)
	{
		printf("bmp open error!\n");
		return -2;
	}
	
	//读取图片相关信息
	int bmp_size, bmp_width, bmp_height;
	//大小
	lseek(bmp, 2, SEEK_SET);
	read(bmp, &bmp_size, sizeof(bmp_size));
	
	//宽度和高度
	lseek(bmp, 18, SEEK_SET);
	read(bmp, &bmp_width, sizeof(bmp_width));
	read(bmp, &bmp_height, sizeof(bmp_height));
	
	//读取图片的颜色数据
	lseek(bmp, 54, SEEK_SET);
	char *bmp_buf = malloc(bmp_size);	//申请空间
	read(bmp, bmp_buf, bmp_width*bmp_height*3);

	
	//对颜色数据进行处理(上下颠倒以及数据混乱)
	int bmp_sum = 0;
	int lcd_sum = 0;
	for(int y=0; y+y0<480 && y<bmp_height; y++)
	{
		for(int x=0; x+x0<800 && x<bmp_width; x++)
		{
			bmp_sum = 3*(x+((bmp_height-1-y)*bmp_width));
			lcd_sum = 4*(800*(y+y0)+x+x0);
			
			//等号的坐标属于lcd屏幕, 等号的右边是bmp图像数据
			ptr[lcd_sum+0] = bmp_buf[bmp_sum+0]; //蓝色数据
			ptr[lcd_sum+1] = bmp_buf[bmp_sum+1]; //绿色数据
			ptr[lcd_sum+2] = bmp_buf[bmp_sum+2]; //红色数据
			ptr[lcd_sum+3] = bmp_buf[bmp_sum+3]; //透明度数据
		}
		//usleep(1);
	}

	munmap(ptr, 800*480*4);
	free(bmp_buf);
	//3、关闭文件
	close(lcd);
	close(bmp);
}


int touch_flag = 1;
int ts_x, ts_y;
int old_x = 300;
int slider_left = 0;
int slider_right = 0;
int flag_x_y = 0;
int right_left_slide_flag = 0;
struct input_event ts;
int flag_x = 0, flag_y = 0, first_press_flag = 0;
//获取触摸屏坐标
//自定义函数:获取触摸屏的坐标
void get_touch()
{
    //1、打开设备文件
    int touch_fd = open("/dev/input/event0", O_RDONLY);
    if(-1 == touch_fd)
    {
        printf("event0 open error!\n");
    }

    while(1)
    {
        read(touch_fd, &ts, sizeof(ts));
	//3、分析数据
        if(EV_ABS == ts.type) //判断是否为触摸屏事件
        {
            if(ABS_X == ts.code)//判断是否为x轴数据
            {
                ts_x = ts.value;
                flag_x = 1;	
            }
            else if(ABS_Y == ts.code) //判断是否为y轴数据
            {
                ts_y = ts.value;
                flag_y = 1;
            }
        }

	if(EV_KEY == ts.type)
	{
		//刚触碰的坐标/长按时
		if(ts.code == BTN_TOUCH && ts.value == 1)
		{
			old_x = ts_x;
			first_press_flag = 1;
		}
	}
	
	if(flag_x == 1 && flag_y == 1 && first_press_flag == 1) 
        {
		flag_x = 0;
		flag_y = 0;
		pthread_mutex_lock(&mutex);
		flag_x_y = 1;  
		//黑色底板才需要执行如下操作
		ts_x = ts_x*800/1024;
		ts_y = ts_y*480/600; 
		pthread_mutex_unlock(&mutex);
		pthread_cond_signal(&cond);
		//break;                    
        }

    if(EV_KEY == ts.type)
	{
		//松开
		if(ts.code == BTN_TOUCH && ts.value == 0)
		{
			//从左到右的滑动
			if(((ts_x > old_x) && (ts_x - old_x > 150) && (ts_x < 600)))
			{
				right_left_slide_flag = 1;
				slider_right = 1;			
				old_x = 300;
			}	
			//从右到左的滑动
			else if(((old_x > ts_x) && (old_x - ts_x > 150) && (old_x < 600)))
			{
				
				right_left_slide_flag = 1;
				slider_left = 1;
				old_x = 300;
			}
		}
	}



    }
    //4、关闭文件
    close(touch_fd);
}

void *right_left_slide_func(void *arg)
{
	printf("enter right_left_slide_func\r\n");
	while(1){
		if(right_left_slide_flag == 1){
			if(slider_left == 1){
				touch_flag--;
				if(touch_flag <= 0)
					touch_flag = BMP_MAX_NUMBER;
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				slider_left = 0;
				right_left_slide_flag == 0;
			}
			else if(slider_right == 1){
				touch_flag++;
				if(touch_flag > BMP_MAX_NUMBER)
					touch_flag = 1;
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				slider_right = 0;
				right_left_slide_flag == 0;
			}
			right_left_slide_flag == 0;
		}	
	}
}

void *area_switch(void *arg)
{
	printf("enter area_switch\r\n");
	while(1){
		pthread_mutex_lock(&mutex);

		while(flag_x_y == 0)
			pthread_cond_wait(&cond, &mutex);
		while(flag_x_y == 1){
			//上一张
			if((ts_y > 0 && ts_y < 120) && (ts_x > 600))
			{
				touch_flag--;
				if(touch_flag <= 0)
					touch_flag = BMP_MAX_NUMBER;
		
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				ts_x = 0;
				ts_y = 0;
			}
			//下一张
			else if((ts_y > 120 && ts_y < 240) && (ts_x > 600))
			{
				touch_flag++;
				if(touch_flag > BMP_MAX_NUMBER)
					touch_flag = 1;
		
				lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
				ts_x = 0;
				ts_y = 0;
			}
			//幻灯片
			else if((ts_y > 240 && ts_y < 360) && (ts_x > 600))
			{
				printf("click slider photo\r\n");
				if(slider_flag == 0){
					slider_flag = 1;
				}
				else{
					slider_flag = 0;
				}
				printf("slider_flag = %d\r\n", slider_flag);
				ts_x = 0;
				ts_y = 0;
			}
			//息屏
			else if((ts_y > 360 && ts_y < 480) && (ts_x > 600))
			{
				char command[] = "kill -9 ";
				char str[10];
				sprintf(str, "%d", pid);
				strcat(command, str);
				printf("command = %s\r\n", command);
				//方式一:显示一张黑色的图片
				lcd_show_bmp("black.bmp", 0, 0);
				system(command);
			}
			else{
				flag_x_y = 0;
				break;
			}
			flag_x_y = 0;
		}

		pthread_mutex_unlock(&mutex);
	}
	
}


void *slider_func(void *arg)
{
	printf("enter slider_func : %d\r\n", pthread_self());
	while(1){
		if(slider_flag == 1){
			printf("enter slider_func\r\n");
			touch_flag++;
			if(touch_flag > BMP_MAX_NUMBER)
				touch_flag = 1;
			lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
			sleep(1);
		}
	}
}


int main()
{
	lcd_show_bmp("choice.bmp", 600, 0);
	lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0);
	pthread_t tid, tid_area_switch, tid_right_left_slide;
	int ret = 0;
	
	pthread_create(&tid, NULL, slider_func, NULL);
	pthread_create(&tid_area_switch, NULL, area_switch, NULL);
	pthread_create(&tid_right_left_slide, NULL, right_left_slide_func, NULL);

	pthread_mutex_init(&mutex, NULL);
	pthread_cond_init(&cond, NULL);
	
	printf("main thread = %ld\r\n", pthread_self());
	pid = getpid();
	printf("pid = %d\r\n", pid);

	while(1){
		get_touch();
	}
	
	
	pthread_join(tid, NULL);
	pthread_join(tid_area_switch, NULL);
	pthread_join(tid_right_left_slide, NULL);
	pthread_cond_destroy(&cond);
	exit(0);

}



总结

以上就是本文的全部内容, 希望能够帮助到你。文章来源地址https://www.toymoban.com/news/detail-756678.html

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

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

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

相关文章

  • 粤嵌Gec6818---小项目功能实现简单步骤(RFID+图片显示+音乐+视频)

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

    2024年02月04日
    浏览(33)
  • 基于GEC6818开发板的相册

    1.图片的显示 2.上滑,下滑,左滑,右滑切换图片 3.幻灯片播放相册 4.显示图片的缩略图 pic.h main.c 获取滑动方向,控制图片切换 幻灯片播放 保存图片到链表 显示图片 触屏判断

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

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

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

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

    2024年02月16日
    浏览(144)
  • 基于Java电子相册图片分享网站系统设计与实现(Springboot框架)毕业设计论文提纲参考

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。 项目配有对应开发文档、

    2024年02月19日
    浏览(63)
  • 基于Java(SpringBoot框架)毕业设计作品成品(17)电子相册、摄影图片分享管理系统设计与实现

    博主介绍: 《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、PPT、论文模版

    2024年02月07日
    浏览(54)
  • 怎样制作一本旅游电子相册呢?

    ​随着数码技术的发展,旅游电子相册已成为越来越多旅游爱好者的必备工具。它不仅能让您随时随地欣赏自己的旅行回忆,还能分享给亲朋好友,甚至上传到社交媒体上,让更多人了解您的旅行故事。那么,如何制作一本精美的旅游电子相册呢? 一、选择合适的软件 制作

    2024年01月18日
    浏览(48)
  • 艾奇免费KTV电子相册视频制作软件

    不得不承认功能特色支持添加导入图形、视频、歌曲、卡啦ok动态歌词字幕文件:图形文件格式支持导入jpg/jpeg/png/bmp/gif等静态图形;视频文件支持导入AVI/MP4/FLV/MTS/MPG/RMVB等几乎所有常见视频文件;歌曲格式支持mp3/wma/acc/ogg/wav等几乎所有常见音频文件,同时支持输入有歌曲的

    2024年02月06日
    浏览(50)
  • 干货|小白也能自制电子相册赶紧码住~

    你是否想拥有一个独一无二的电子相册,却又苦于不知道如何下手?今天教你一个简单的方法,即使你是小白,也能轻松自制电子相册! 一、选择合适的工具 首先,你需要选择一个合适的工具来制作电子相册。有很多工具可供选择,包括手机APP、在线制作网站等。推荐大家

    2024年02月07日
    浏览(36)
  • 原地封神!一个只用套模板即可制作电子相册的网站

    对于忙碌的年轻人来说,一键操作的模板意味着无需复杂的操作步骤,就能轻松制作出精美的电子相册。 但是一个好的工具也是事关重要,最近发现了一款非常适合年轻人的模板--- FLBOOK在线制作电子杂志平台 ,只需要找到合适的模板即可制作电子相册 1.打开FLBOOK在线制作电

    2024年02月06日
    浏览(47)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包