From: Andreas Eversberg Date: Sat, 10 Oct 2015 07:38:24 +0000 (+0200) Subject: load image sequence faster by parsing directory X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=colorize.git;a=commitdiff_plain;h=2c98bbe1df3f7981e49638263ce814667f4de032 load image sequence faster by parsing directory --- diff --git a/gui/timeline.c b/gui/timeline.c index c6590f0..ba06625 100644 --- a/gui/timeline.c +++ b/gui/timeline.c @@ -14,6 +14,94 @@ #include "../src/opticalflow.h" #endif +/* functions to load directory */ + +typedef struct dir_entry { + struct dir_entry *next; + char name[0]; +} dir_t; + +static int cmpstringp(const void *p1, const void *p2) +{ + dir_t *entry1 = *(dir_t **)p1; + dir_t *entry2 = *(dir_t **)p2; + + return strcmp(entry1->name, entry2->name); +} + +static dir_t *fetch_dir(const char *path) /* NOTE: if path is not empty, it must end with DIR_SEPERATOR */ +{ + int rc; + DIR *dir; + struct dirent dirent, *result; + dir_t *head = NULL, *entry, **entryp = &head; + int count = 0; + dir_t **list; + int i; + + /* read linked list */ + dir = opendir(path); + if (!dir) + return NULL; + while (1) { + rc = readdir_r(dir, &dirent, &result); + if (rc < 0) + break; + if (result == NULL) + break; + if (result->d_type != DT_REG && result->d_type != DT_LNK) + continue; + entry = calloc(1, sizeof(dir_t) + strlen(path) + strlen(result->d_name) + 1); + if (!entry) { + fprintf(stderr, "no memory"); + return NULL; + } + *entryp = entry; + entryp = &entry->next; + strcpy(entry->name, path); + strcat(entry->name, result->d_name); + count++; + } + closedir(dir); + + /* sort linked list */ + list = calloc(count, sizeof(*list)); + if (!list) { + fprintf(stderr, "no memory"); + return NULL; + } + count = 0; + for (entry = head; entry; entry = entry->next) { + list[count] = entry; + count++; + } + qsort(list, count, sizeof(*list), cmpstringp); + entryp = &head; + for (i = 0; i < count; i++) { + /* relink */ + entry = list[i]; + entry->next = NULL; + *entryp = entry; + entryp = &entry->next; + } + free(list); + + return head; +} + +static void free_dir(dir_t *dir) +{ + dir_t *entry, *next; + + entry = dir; + while (entry) { + next = entry->next; + free(entry); + entry = next; + } +} + + struct frame_list *frame_list = NULL; /* currently loaded image */ @@ -83,12 +171,29 @@ static void draw_timeline_frame(int frame) } } +/* get path of given file name */ +static char *get_path(const char *filename) +{ + static char path[256]; + + /* copy name */ + strcpy(path, filename); + /* remove until DIR_SEPERATOR */ + while (path[0]) { + if (path[strlen(path) - 1] == DIR_SEPERATOR) + break; + path[strlen(path) - 1] = '\0'; + } + + return path; +} + /* load directory and create pixbuf */ void create_timeline(const char *filename) { int i; const char *p, *q; - char temp[256], name[256], suffix[256]; + char temp[256], suffix[256]; FILE *fp; if (filename) { @@ -131,44 +236,61 @@ single_file: strcpy(frame_list[0].filename, filename); timeline_frames = 1; } else { - /* calculate image file name */ + /* create list of files that have same base name, same number of digits and suffix */ + int suffix_offset = strlen(filename) - strlen(suffix); + int digits_offset = p - filename; int digits = filename + strlen(filename) - strlen(suffix) - p; - int start, count = 0; - strncpy(temp, p, digits); - temp[digits] = '\0'; - start = atoi(temp); -// printf("count digits=%s num=%d start=%d\n", temp, digits, start); - strncpy(temp, filename, p - filename); - temp[p - filename] = '\0'; -// printf("prefix=%s\n", temp); - sprintf(strchr(temp, '\0'), "%%0%dd%s", digits, suffix); -// printf("complete=%s\n", temp); - /* look back for index */ - while (start > 0) { - sprintf(name, temp, start - 1); - fp = fopen(name, "r"); - if (!fp) - break; - fclose(fp); - start--; + const char *path = get_path(filename); + dir_t *dir_head = fetch_dir(path), *dir, **dirp; + int count; + if (!dir_head) + goto single_file; + dir = dir_head; + dirp = &dir_head; + while (dir) { + /* remove files that do not have equal prefix */ + if (!!strncmp(filename, dir->name, p - filename)) { +free_file: + /* remove entry */ + *dirp = dir->next; + free(dir); + dir = *dirp; + continue; + } + /* remove files that have no digits where expected */ + for (i = 0; i < digits; i++) { + if (dir->name[digits_offset+i] < '0' || dir->name[digits_offset+i] > '9') + break; + } + if (i < digits) { + goto free_file; + } + /* remove files that have different suffix */ + if (!!strcmp(suffix, dir->name + suffix_offset)) { + goto free_file; + } + dirp = &(dir->next); + dir = dir->next; } - /* count forward index */ - for (i = start; ; i++) { - sprintf(name, temp, start + count); - fp = fopen(name, "r"); - if (!fp) - break; - fclose(fp); + count = 0; + dir = dir_head; + while (dir) { count++; + dir = dir->next; } - if (count == 0) + if (count < 2) { + free_dir(dir_head); goto single_file; + } frame_list = malloc(sizeof(struct frame_list) * count); memset(frame_list, 0, sizeof(struct frame_list) * count); + dir = dir_head; for (i = 0; i < count; i++) { - sprintf(frame_list[i].filename, temp, start + i); + strcpy(frame_list[i].filename, dir->name); + dir = dir->next; } timeline_frames = count; + free_dir(dir_head); } /* get marked frames */ for (i = 0; i < timeline_frames; i++) { @@ -382,18 +504,12 @@ int timeline_clicked(int x, int y) } /* get filename of first grey image directory */ -static char *get_filename(const char *filename) +static char *get_sequence_name(const char *filename) { static char name[256]; /* copy name */ - strcpy(name, filename); - /* remove until DIR_SEPERATOR */ - while (name[0]) { - if (name[strlen(name) - 1] == DIR_SEPERATOR) - break; - name[strlen(name) - 1] = '\0'; - } + strcpy(name, get_path(filename)); /* add palette name */ strcat(name, "sequence"); @@ -412,7 +528,7 @@ int save_sequence(void) if (timeline_frames <= 1) return 0; - name = get_filename(frame_list[0].filename); + name = get_sequence_name(frame_list[0].filename); // printf("save sequence '%s'\n", name); fp = fopen(name, "w"); if (!fp) { @@ -444,11 +560,11 @@ int load_sequence(void) if (timeline_frames <= 1) return 0; - name = get_filename(frame_list[0].filename); + name = get_sequence_name(frame_list[0].filename); // printf("load sequence '%s'\n", name); fp = fopen(name, "r"); if (!fp) { - printf("failed to load sequence '%s'\n", name); + printf("no sequence file '%s' created yet\n", name); return -1; } for (i = 0; i < timeline_frames; i++) {