diff options
Diffstat (limited to 'src/thumbnail.c')
-rw-r--r-- | src/thumbnail.c | 197 |
1 files changed, 134 insertions, 63 deletions
diff --git a/src/thumbnail.c b/src/thumbnail.c index c806ce4..70af5e0 100644 --- a/src/thumbnail.c +++ b/src/thumbnail.c @@ -1,7 +1,7 @@ /* thumbnail.c Copyright (C) 1999-2003 Tom Gilbert. -Copyright (C) 2010-2011 Daniel Friesel. +Copyright (C) 2010-2024 Birte Kristina Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -71,7 +71,6 @@ void init_thumbnail_mode(void) gib_list *l, *last = NULL; int lineno; int index_image_width, index_image_height; - char *s; unsigned int thumb_counter = 0; gib_list *line, *lines; @@ -92,6 +91,8 @@ void init_thumbnail_mode(void) td.vertical = 0; td.max_column_w = 0; + if (!opt.thumb_title) + opt.thumb_title = "%n"; mode = "thumbnail"; if (opt.font) @@ -144,11 +145,21 @@ void init_thumbnail_mode(void) index_image_width = td.w; index_image_height = td.h + title_area_h; + D(("imlib_create_image(%d, %d)\n", index_image_width, index_image_height)); td.im_main = imlib_create_image(index_image_width, index_image_height); - gib_imlib_image_set_has_alpha(td.im_main, 1); - if (!td.im_main) - eprintf("Imlib error creating index image, are you low on RAM?"); + if (!td.im_main) { + if (index_image_height >= 32768 || index_image_width >= 32768) { + eprintf("Failed to create %dx%d pixels (%d MB) index image.\n" + "This is probably due to Imlib2 issues when dealing with images larger than 32k x 32k pixels.", + index_image_width, index_image_height, index_image_width * index_image_height * 4 / (1024*1024)); + } else { + eprintf("Failed to create %dx%d pixels (%d MB) index image. Do you have enough RAM?", + index_image_width, index_image_height, index_image_width * index_image_height * 4 / (1024*1024)); + } + } + + gib_imlib_image_set_has_alpha(td.im_main, 1); if (td.im_bg) gib_imlib_blend_image_onto_image(td.im_main, td.im_bg, @@ -165,20 +176,13 @@ void init_thumbnail_mode(void) td.h + title_area_h, 0, 0, 0, 255); } - /* Create title now */ - - if (!opt.title) - s = estrdup(PACKAGE " [thumbnail mode]"); - else - s = estrdup(feh_printf(opt.title, NULL, NULL)); if (opt.display) { - winwid = winwidget_create_from_image(td.im_main, s, WIN_TYPE_THUMBNAIL); + winwid = winwidget_create_from_image(td.im_main, WIN_TYPE_THUMBNAIL); + winwidget_rename(winwid, PACKAGE " [thumbnail mode]"); winwidget_show(winwid); } - /* make sure we have an ~/.thumbnails/normal directory for storing - permanent thumbnails */ td.cache_thumbnails = opt.cache_thumbnails; if (td.cache_thumbnails) { @@ -187,9 +191,15 @@ void init_thumbnail_mode(void) else td.cache_dim = opt.thumb_h; - if (td.cache_dim > 256) { - /* No caching as specified by standard. Sort of. */ + if (td.cache_dim > 1024) { + /* Not specified by XDG thumbnail standard */ td.cache_thumbnails = 0; + } else if (td.cache_dim > 512) { + td.cache_dim = 1024; + td.cache_dir = estrdup("xx-large"); + } else if (td.cache_dim > 256) { + td.cache_dim = 512; + td.cache_dir = estrdup("x-large"); } else if (td.cache_dim > 128) { td.cache_dim = 256; td.cache_dir = estrdup("large"); @@ -380,11 +390,13 @@ void init_thumbnail_mode(void) if (opt.output_dir) snprintf(output_buf, 1024, "%s/%s", opt.output_dir, opt.output_file); - else - strncpy(output_buf, opt.output_file, 1024); + else { + strncpy(output_buf, opt.output_file, 1023); + output_buf[1023] = '\0'; + } gib_imlib_save_image_with_error_return(td.im_main, output_buf, &err); if (err) { - feh_imlib_print_load_error(output_buf, td.im_main, err); + feh_print_load_error(output_buf, td.im_main, err, LOAD_ERROR_IMLIB); } else if (opt.verbose) { int tw, th; @@ -403,6 +415,7 @@ void init_thumbnail_mode(void) else if (opt.start_list_at) { for (l = thumbnails; l; l = l->next) { if (!strcmp(opt.start_list_at, FEH_THUMB(l->data)->file->filename)) { + free(opt.start_list_at); opt.start_list_at = NULL; feh_thumbnail_select(winwid, FEH_THUMB(l->data)); break; @@ -411,7 +424,6 @@ void init_thumbnail_mode(void) } - free(s); return; } @@ -563,6 +575,12 @@ int feh_thumbnail_get_thumbnail(Imlib_Image * image, feh_file * file, if (td.cache_thumbnails) { uri = feh_thumbnail_get_name_uri(file->filename); thumb_file = feh_thumbnail_get_name(uri); + + if (thumb_file == NULL) { + free(uri); + return feh_load_image(image, file); + } + status = feh_thumbnail_get_generated(image, file, thumb_file, orig_w, orig_h); @@ -579,21 +597,39 @@ int feh_thumbnail_get_thumbnail(Imlib_Image * image, feh_file * file, return status; } +static char *feh_thumbnail_get_prefix(void) +{ + char *dir = NULL, *home, *xdg_cache_home; + + // TODO: perhaps make sure that either of those paths aren't /-terminated + + xdg_cache_home = getenv("XDG_CACHE_HOME"); + if (xdg_cache_home && xdg_cache_home[0] == '/') { + dir = estrjoin("/", xdg_cache_home, "thumbnails", td.cache_dir, NULL); + } else { + home = getenv("HOME"); + if (home && home[0] == '/') { + dir = estrjoin("/", home, ".cache/thumbnails", td.cache_dir, NULL); + } + } + + return dir; +} + char *feh_thumbnail_get_name(char *uri) { - char *home = NULL, *thumb_file = NULL, *md5_name = NULL; + char *prefix, *thumb_file = NULL, *md5_name; /* FIXME: make sure original file isn't under ~/.thumbnails */ - md5_name = feh_thumbnail_get_name_md5(uri); - - home = getenv("HOME"); - if (home) { - thumb_file = estrjoin("/", home, ".thumbnails", td.cache_dir, md5_name, NULL); + prefix = feh_thumbnail_get_prefix(); + if (prefix) { + md5_name = feh_thumbnail_get_name_md5(uri); + thumb_file = estrjoin("/", prefix, md5_name, NULL); + free(md5_name); + free(prefix); } - free(md5_name); - return thumb_file; } @@ -604,9 +640,9 @@ char *feh_thumbnail_get_name_uri(char *name) /* FIXME: what happens with http, https, and ftp? MTime etc */ if (!path_is_url(name)) { - /* make sure it's an absoulte path */ + /* make sure it's an absolute path */ /* FIXME: add support for ~, need to investigate if it's expanded - somewhere else before adding (unecessary) code */ + somewhere else before adding (unnecessary) code */ if (name[0] != '/') { /* work around /some/path/./image.ext */ if ((strncmp(name, "./", 2)) == 0) @@ -636,7 +672,7 @@ char *feh_thumbnail_get_name_md5(char *uri) md5_finish(&pms, digest); /* print the md5 as hex to a string */ - md5_name = emalloc(32 + 4 + 1 * sizeof(char)); /* md5 + .png + '\0' */ + md5_name = emalloc(32 + 4 + 1); /* md5 + .png + '\0' */ for (i = 0, pos = md5_name; i < 16; i++, pos += 2) { sprintf(pos, "%02x", digest[i]); } @@ -652,6 +688,8 @@ int feh_thumbnail_generate(Imlib_Image * image, feh_file * file, Imlib_Image im_temp; struct stat sb; char c_width[8], c_height[8]; + char *tmp_thumb_file, *prefix; + int tmp_fd; if (feh_load_image(&im_temp, file) != 0) { *orig_w = w = gib_imlib_image_get_width(im_temp); @@ -665,6 +703,13 @@ int feh_thumbnail_generate(Imlib_Image * image, feh_file * file, thumb_h = td.cache_dim / ratio; else if (ratio != 1.0) thumb_w = td.cache_dim * ratio; + } else { + /* + * The image is smaller than the specified thumbnail size. + * Do not cache or transform it. + */ + *image = im_temp; + return 1; } *image = gib_imlib_create_cropped_scaled_image(im_temp, 0, 0, w, h, @@ -675,18 +720,32 @@ int feh_thumbnail_generate(Imlib_Image * image, feh_file * file, sprintf(c_mtime, "%d", (int)sb.st_mtime); snprintf(c_width, 8, "%d", w); snprintf(c_height, 8, "%d", h); - feh_png_write_png(*image, thumb_file, "Thumb::URI", uri, + prefix = feh_thumbnail_get_prefix(); + if (prefix == NULL) { + gib_imlib_free_image_and_decache(im_temp); + return 0; + } + tmp_thumb_file = estrjoin("/", prefix, ".feh_thumbnail_XXXXXX", NULL); + free(prefix); + tmp_fd = mkstemp(tmp_thumb_file); + if (!feh_png_write_png_fd(*image, tmp_fd, "Thumb::URI", uri, "Thumb::MTime", c_mtime, "Thumb::Image::Width", c_width, - "Thumb::Image::Height", c_height); + "Thumb::Image::Height", c_height)) { + rename(tmp_thumb_file, thumb_file); + } else { + unlink(tmp_thumb_file); + } + close(tmp_fd); + free(tmp_thumb_file); } gib_imlib_free_image_and_decache(im_temp); - return (1); + return 1; } - return (0); + return 0; } int feh_thumbnail_get_generated(Imlib_Image * image, feh_file * file, @@ -727,25 +786,32 @@ int feh_thumbnail_get_generated(Imlib_Image * image, feh_file * file, void feh_thumbnail_show_fullsize(feh_file *thumbfile) { winwidget thumbwin = NULL; - char *s; + gib_list *l; - if (!opt.thumb_title) - s = thumbfile->name; - else - s = feh_printf(opt.thumb_title, thumbfile, NULL); - + for (l = filelist; l; l = l->next) { + if (FEH_FILE(l->data) == thumbfile) { + break; + } + } + if (!l) { + eprintf("Cannot find %s in filelist, wtf", thumbfile->filename); + } thumbwin = winwidget_get_first_window_of_type(WIN_TYPE_THUMBNAIL_VIEWER); if (!thumbwin) { thumbwin = winwidget_create_from_file( - gib_list_add_front(NULL, thumbfile), - s, WIN_TYPE_THUMBNAIL_VIEWER); + l, + WIN_TYPE_THUMBNAIL_VIEWER); if (thumbwin) winwidget_show(thumbwin); } else if (FEH_FILE(thumbwin->file->data) != thumbfile) { - free(thumbwin->file); - thumbwin->file = gib_list_add_front(NULL, thumbfile); - winwidget_rename(thumbwin, s); - feh_reload_image(thumbwin, 1, 1); + thumbwin->file = l; +#ifdef HAVE_INOTIFY + winwidget_inotify_remove(thumbwin); +#endif + feh_reload_image(thumbwin, 1, 0); +#ifdef HAVE_INOTIFY + winwidget_inotify_add(thumbwin, thumbfile); +#endif } } @@ -827,13 +893,13 @@ void feh_thumbnail_select_prev(winwidget winwid, int jump) } } -void feh_thumbnail_show_selected() +void feh_thumbnail_show_selected(void) { if (td.selected && td.selected->file) feh_thumbnail_show_fullsize(td.selected->file); } -feh_file* feh_thumbnail_get_selected_file() +feh_file* feh_thumbnail_get_selected_file(void) { if (td.selected) return td.selected->file; @@ -844,31 +910,36 @@ int feh_thumbnail_setup_thumbnail_dir(void) { int status = 0; struct stat sb; - char *dir, *dir_thumbnails, *home; + char *dir, *p; - home = getenv("HOME"); - if (home != NULL) { - dir = estrjoin("/", home, ".thumbnails", td.cache_dir, NULL); + dir = feh_thumbnail_get_prefix(); + if (dir) { if (!stat(dir, &sb)) { if (S_ISDIR(sb.st_mode)) status = 1; else weprintf("%s should be a directory", dir); } else { - dir_thumbnails = estrjoin("/", home, ".thumbnails", NULL); + for (p = dir + 1; *p; p++) { + if (*p != '/') { + continue; + } - if (stat(dir_thumbnails, &sb) != 0) { - if (mkdir(dir_thumbnails, 0700) == -1) - weprintf("unable to create directory %s", dir_thumbnails); + *p = 0; + if (stat(dir, &sb) != 0) { + if (mkdir(dir, 0700) == -1) { + weprintf("unable to create directory %s", dir); + } + } + *p = '/'; } - free(dir_thumbnails); - - if (mkdir(dir, 0700) == -1) - weprintf("unable to create directory %s", dir); - else - status = 1; + if (stat(dir, &sb) != 0) { + if (mkdir(dir, 0700) == -1) { + weprintf("unable to create directory %s", dir); + } + } } free(dir); } |