圖片播放器(八):讀取資料夾中的圖片
阿新 • • 發佈:2018-11-25
採用連結串列的方式儲存圖片檔案的格式資訊,檔名和大小。
重要結構體:
/* 圖片檔案型別 */ 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;
}