图片播放器(八):读取文件夹中的图片

版权声明:转载请声明 https://blog.csdn.net/qq_40732350/article/details/84327616

采用链表的方式保存图片文件的格式信息,文件名和大小。

 

重要结构体:

/* 图片文件类型 */
typedef enum image_type
{
	IMAGE_TYPE_BMP,
	IMAGE_TYPE_JPG,
	IMAGE_TYPE_PNG,
	IMAGE_TPPE_UNKNOWN, /* 不能识别 */
}image_type_e;



/* 图片文件信息 */
typedef struct iamge_file_info
{
	unsigned char       path_name[PATH_NAME_MAX];    /* 图片文件路径 */
	image_type_e        image_type;                  /* 图片文件类型 */
	unsigned long int   picture_size;                /* 图片文件的大小 */
}iamge_file_info_s;


/* 文件的双向链表的节点 */
typedef struct iamge_file_node
{
    iamge_file_info_s       iamge_file_data;
    struct iamge_file_node *prior;
    struct iamge_file_node *next;
}iamge_file_node_s;

全局变量和宏定义:

#define PATH_NAME_MAX 256  /* 路径名的最大字节数 */
#define FILE_NODE_MAX 256  /* 链表节点数量最大值 */

iamge_file_node_s    file_head;                    /* 文件头链表头 */
static unsigned int         now_file_num = 0;             /* 当前的图片文件数量 */
iamge_file_node_s          *tail_file_node = NULL;                /* 指向链表的尾节点*/

初始化:

功能:把所有的图片加入到链表中

/* 初始化 */
int im_manage_init(void)
{
	const char path[PATH_NAME_MAX] = {"/usr/picture"};/* 所有图片保存这个文件夹下 */

	file_head.next = NULL;
	file_head.prior = NULL;
	
	im_add_dir(path);

	DEBUG("现在有 [%d] 张图片\n", now_file_num);

	return 0;
}

path_name_dir 文件夹中的图片文件添加到链表中:

/* 把文件夹中的文件添加到链表中 */
static int im_add_dir(const char *path_name_dir)
{
	DIR *dir = NULL;
	struct dirent *ptr;
	char base[PATH_NAME_MAX];
	struct stat sta;

	if((dir = opendir(path_name_dir)) == NULL)
	{
		DERROR("Open dir error...\n");
		return -1;
	}

	while ((ptr = readdir(dir)) != NULL)
	{
		if(strcmp(ptr->d_name, ".")==0 || strcmp(ptr->d_name, "..")==0)    ///current dir OR parrent dir
			continue;
	
			// 用lstat来读取文件属性并判断文件类型
		memset(base,'\0',sizeof(base));
		strcpy(base,path_name_dir);
		strcat(base,"/");
		strcat(base,ptr->d_name);
		lstat(base, &sta);
	
		if (S_ISREG(sta.st_mode)){
			/* 添加普通文件 */
			im_add_file(base);	
		}else if(S_ISDIR(sta.st_mode)){
			im_add_dir(base);/* 读子文件夹 */
		}
	}

	return 0;
}

创建并初始化一个链表的节点:

/* 初始化一个链表的节点 */
static iamge_file_node_s *im_create_node(iamge_file_info_s *im_info_cr)
{
    iamge_file_node_s *p;
    p = (iamge_file_node_s*)malloc(sizeof(iamge_file_node_s));
    if(p == NULL){
        DERROR("动态内存分配失败!\n");
        exit(-1);
    }

	p->iamge_file_data.image_type = im_info_cr->image_type;
	memset(p->iamge_file_data.path_name, 0, PATH_NAME_MAX);
	memcpy(p->iamge_file_data.path_name, im_info_cr->path_name, strlen((const char *)im_info_cr->path_name));
	p->iamge_file_data.picture_size = im_info_cr->picture_size;
    p->prior = NULL;
    p->next = NULL;
    return (p);
} 

添加文件:

/* 添加文件 */
int im_add_file(char *path_name_add)
{
	struct stat buffer;
	iamge_file_info_s  f_in;
	iamge_file_node_s *f_p = NULL;

	if(0 != lstat((const char *)path_name_add, &buffer)){
		DERROR("读取文件错误\n");
		return -1;
	}

	memset(f_in.path_name, 0, PATH_NAME_MAX);
	memcpy(f_in.path_name, path_name_add, strlen(path_name_add));

	if('Y' == im_is_bmp((const char *)path_name_add)){//判断是否是bmp文件
		f_in.image_type = IMAGE_TYPE_BMP;
	}else if('Y' == im_is_jpg((const char *)path_name_add)){
		f_in.image_type = IMAGE_TYPE_JPG;
	}else if('Y' == im_is_png((const char *)path_name_add)){
		f_in.image_type = IMAGE_TYPE_PNG;
	}else{
		f_in.image_type = IMAGE_TYPE_PNG;
	}

	f_in.picture_size = buffer.st_size;//赋值文件的大小

	f_p = im_create_node(&f_in);//创建并初始化链表节点
	
	im_insert_list(f_p);//插入链表节点中

	return 0;
}

删除文件:

/* 删除文件 */
int im_remove_file(unsigned char *path_name_re)
{
	iamge_file_node_s *f_p = NULL;

	f_p = im_search_list(path_name_re);

	if(f_p == NULL){
		DERROR("没有此文件可以删除\n");
		return -1;
	}

	if(im_delect_list(f_p) < 0){
		DERROR("删除文件失败\n");
		return -1;
	}
	return 0;
}

在链表的头部插入结点

/* 在链表的头部插入结点 */
static void im_insert_list(iamge_file_node_s *file_node_in)
{
	if(file_head.next != NULL){
		file_head.next->prior = file_node_in;
		file_node_in->next = file_head.next;
	    file_head.next = file_node_in;
		file_node_in->prior = &file_head;
	}else{
		file_head.next = file_node_in;
		file_node_in->next = NULL;
		file_node_in->prior = &file_head;
		tail_file_node = file_node_in;
	}

	++now_file_num;
} 

删除文件结点:

/* 删除文件结点 */
static int im_delect_list(iamge_file_node_s *file_node_de)
{
    if(file_head.next == NULL){
        DERROR("现在播放器中没有文件\n");
		return -1;
	}else{
		if(file_node_de->next == NULL){
			file_node_de->prior->next = NULL;
			if(file_node_de->prior == &file_head){
				tail_file_node = NULL;
			}else{
				tail_file_node = file_node_de->prior;
			}
			file_node_de->prior = NULL;
		}else{
			file_node_de->prior->next = file_node_de->next;
			file_node_de->next->prior = file_node_de->prior;
			file_node_de->next = file_node_de->prior = NULL;
		}

		--now_file_num;
		free(file_node_de);
		return 0;
	}
} 

搜索遍历一个链表:

/* 搜索遍历一个链表 */
static iamge_file_node_s * im_search_list(unsigned char *path_name_se)
{
	iamge_file_node_s *p_file;

    if(file_head.next == NULL)
    {
        DERROR("现在播放器中没有文件\n");
		return NULL;
    }
    else
    {
        p_file = file_head.next;
        while(p_file != NULL)
        {
        	if(0 == memcmp(p_file->iamge_file_data.path_name, (const char *)path_name_se, strlen(((const char *)path_name_se)))){
				DEBUG("找到文件 [%s]\n", path_name_se);
				return (p_file);

			}else{
				p_file = p_file->next;
			}
            
        }
		return NULL;
    }
} 

由于不想引用图片显示部分的函数,于是此文件中定义了判断文件格式的函数:

/* 判断是否为 bmp 文件*/
static char im_is_bmp(const char *path)
{
	int ret;
	int fd = -1;
	char picture[2];

	if ((fd = open(path, O_RDONLY)) < 0 ){
		DERROR("NO [%s] file\n", path);
		return 'O';
	}

	if ((ret = read(fd, picture, 2)) < 2){
		DERROR("read [%s] file error\n", path);
		close(fd);
		return 'R';
	}

	if((picture[0] != 'B') || (picture[1] != 'M')){ /*判断能前两给字节是否是 BM */
		DERROR("It's not a BMP file\n");
		close(fd);
		return 'N';
	}else{
		close(fd);
		return 'Y';
	}
}

/* 判断是否为 jpg 文件 */
static char im_is_jpg (const char *path)
{
	int ret;
	int fd = -1;
	char picture[2];

	if ((fd = open(path, O_RDONLY)) < 0 ){
		DERROR("NO [%s] file\n", path);
		return 'O';
	}

	/* 读文件的头两个字节 */
	if ((ret = read(fd, picture, 2)) < 2){
		DERROR("read [%s] file error\n", path);
		close(fd);
		return 'R';
	}

	if((picture[0] != 0xff) || (picture[1] != 0xd8)){
		DERROR("It's not a JPG file\n");
		close(fd);
		return 'N';
	}

	lseek(fd, -2, SEEK_END);

	/* 读文件的最后两个字节 */
	if ((ret = read(fd, picture, 2)) < 2){
		DERROR("read [%s] file error\n", path);
		close(fd);
		return 'R';
	}

	if((picture[0] != 0xff) || (picture[1] != 0xd9)){
		DERROR("It's not a BMP file\n");
		close(fd);
		return 'N';
	}else{
		close(fd);
		return 'Y';
	}
}


/* 判断是否为 png 文件*/
static char im_is_png(const     char *path)
{
	unsigned char *buf = malloc(sizeof(8));
	unsigned char png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
	int fd = -1;

	if ((fd = open(path, O_RDONLY)) < 0){
		DERROR("NO [%s] file\n", path);
		return 'O';
	}

	if (read(fd, buf, 8) != 8){
		DERROR("read [%s] file error\n", path);
		close(fd);
		return 'R';
	}

	/*判断前 PNG_BYTES_TO_CHECK 个字节是否是 (89 50 4E 47 0D 0A 1A 0A 16进制) */
	if(memcmp(buf, png_signature, 8) != 0){ 
		DERROR("It's not a PNG file\n");
		close(fd);
		return 'N';
	}else{
		close(fd);
		return 'Y';
	}
}

读取链表尾节点:

由于多文件程序中,用指针做全局变量会带来一些问题,因此这里用函数的形式来进行多文件之间的沟通。

/* 读取链表尾节点 */
iamge_file_node_s   *im_read_fail(void)
{
	return tail_file_node;
}

销毁链表:

/* 销毁链表 */
int im_manage_destroy(void)
{
	iamge_file_node_s *p_node_1 = NULL;
	iamge_file_node_s *p_node_2 = NULL;
	
	if(file_head.next == NULL){
		DEBUG("不用销毁\n");
		return 0;
	}

	p_node_1 = file_head.next;
	p_node_2 = file_head.next->next;
	
	while(p_node_2 != NULL)
	{
		free(p_node_1);
		p_node_1 = p_node_2;
		p_node_2 = p_node_1->next;
	}

	free(p_node_1);

	p_node_1 = p_node_2 = file_head.next = NULL;

	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40732350/article/details/84327616