Create thumbnail cache dir automatically

This commit is contained in:
Bert Münnich 2014-06-10 23:15:04 +02:00
parent cd02f2dd86
commit 5cfae63620
3 changed files with 57 additions and 87 deletions

16
sxiv.1
View file

@ -27,9 +27,6 @@ sxiv has two modes of operation: image and thumbnail mode. The default is image
mode, in which only the current image is shown. In thumbnail mode a grid of mode, in which only the current image is shown. In thumbnail mode a grid of
small previews is displayed, making it easy to choose an image to open. small previews is displayed, making it easy to choose an image to open.
.P .P
sxiv can also cache its thumbnails. Please see the section THUMBNAIL CACHING
for information on how to enable this feature.
.P
Please note, that the fullscreen mode requires an EWMH/NetWM compliant window Please note, that the fullscreen mode requires an EWMH/NetWM compliant window
manager. manager.
.SH OPTIONS .SH OPTIONS
@ -371,18 +368,13 @@ keysym as listed in /usr/include/X11/keysymdef.h without the "XK_" prefix.
There is also an example script installed together with sxiv as There is also an example script installed together with sxiv as
.IR PREFIX/share/sxiv/exec/key-handler . .IR PREFIX/share/sxiv/exec/key-handler .
.SH THUMBNAIL CACHING .SH THUMBNAIL CACHING
To enable thumbnail caching, please make sure to create the directory sxiv stores all thumbnails under
.I $XDG_CACHE_HOME/sxiv/ .IR $XDG_CACHE_HOME/sxiv/ .
with write permissions. sxiv will then store all thumbnails inside this
directory, but it will not create this directory by itself. It rather uses the
existance of this directory as an affirmation, that the user wants thumbnails
to be cached.
.P .P
Use the command line option Use the command line option
.I \-c .I \-c
to keep the cache directory clean by removing all orphaned cache files. to remove all orphaned cache files. Additionally, run the following command
Additionally, run the following command afterwards inside the cache directory afterwards inside the cache directory to remove empty subdirectories:
to remove empty subdirectories:
.P .P
.RS .RS
find . \-depth \-type d \-empty ! \-name '.' \-exec rmdir {} \\; find . \-depth \-type d \-empty ! \-name '.' \-exec rmdir {} \\;

117
thumbs.c
View file

@ -36,18 +36,9 @@
void exif_auto_orientate(const fileinfo_t*); void exif_auto_orientate(const fileinfo_t*);
#endif #endif
static char *cache_dir;
static const int thumb_dim = THUMB_SIZE + 10; static const int thumb_dim = THUMB_SIZE + 10;
static char *cache_dir = NULL;
bool tns_cache_enabled(void)
{
struct stat stats;
return cache_dir != NULL && stat(cache_dir, &stats) == 0 &&
S_ISDIR(stats.st_mode) && access(cache_dir, W_OK) == 0;
}
char* tns_cache_filepath(const char *filepath) char* tns_cache_filepath(const char *filepath)
{ {
size_t len; size_t len;
@ -107,19 +98,15 @@ void tns_cache_write(thumb_t *t, bool force)
err = r_mkdir(cfile); err = r_mkdir(cfile);
*dirend = '/'; *dirend = '/';
} }
if (err == 0) { if (err == 0) {
imlib_context_set_image(t->im); imlib_context_set_image(t->im);
imlib_image_set_format("png"); imlib_image_set_format("png");
imlib_save_image_with_error_return(cfile, &err); imlib_save_image_with_error_return(cfile, &err);
} }
if (err == 0) { if (err == 0) {
times.actime = fstats.st_atime; times.actime = fstats.st_atime;
times.modtime = fstats.st_mtime; times.modtime = fstats.st_mtime;
utime(cfile, &times); utime(cfile, &times);
} else {
warn("could not cache thumbnail: %s", t->file->name);
} }
} }
free(cfile); free(cfile);
@ -177,7 +164,6 @@ void tns_init(tns_t *tns, int cnt, win_t *win)
} else { } else {
tns->thumbs = NULL; tns->thumbs = NULL;
} }
tns->cap = cnt; tns->cap = cnt;
tns->cnt = tns->first = tns->sel = 0; tns->cnt = tns->first = tns->sel = 0;
tns->win = win; tns->win = win;
@ -226,7 +212,7 @@ bool tns_load(tns_t *tns, int n, const fileinfo_t *file,
bool force, bool silent) bool force, bool silent)
{ {
int w, h; int w, h;
bool use_cache, cache_hit = false; bool cache_hit = false;
float z, zw, zh; float z, zw, zh;
thumb_t *t; thumb_t *t;
Imlib_Image im = NULL; Imlib_Image im = NULL;
@ -246,64 +232,63 @@ bool tns_load(tns_t *tns, int n, const fileinfo_t *file,
imlib_free_image(); imlib_free_image();
} }
if ((use_cache = tns_cache_enabled())) { if (!force && (im = tns_cache_load(file->path)) != NULL) {
if (!force && (im = tns_cache_load(file->path)) != NULL) cache_hit = true;
cache_hit = true; } else {
}
if (!cache_hit) {
#if HAVE_LIBEXIF #if HAVE_LIBEXIF
int pw = 0, ph = 0, x = 0, y = 0; if (!force) {
bool err; int pw = 0, ph = 0, x = 0, y = 0;
ExifData *ed; bool err;
ExifEntry *entry; ExifData *ed;
ExifContent *ifd; ExifEntry *entry;
ExifByteOrder byte_order; ExifContent *ifd;
int tmpfd; ExifByteOrder byte_order;
char tmppath[] = "/tmp/sxiv-XXXXXX"; int tmpfd;
Imlib_Image tmpim; char tmppath[] = "/tmp/sxiv-XXXXXX";
Imlib_Image tmpim;
if ((ed = exif_data_new_from_file(file->path)) != NULL && if ((ed = exif_data_new_from_file(file->path)) != NULL &&
ed->data != NULL && ed->size > 0) ed->data != NULL && ed->size > 0)
{ {
if ((tmpfd = mkstemp(tmppath)) >= 0) { if ((tmpfd = mkstemp(tmppath)) >= 0) {
err = write(tmpfd, ed->data, ed->size) != ed->size; err = write(tmpfd, ed->data, ed->size) != ed->size;
close(tmpfd); close(tmpfd);
if (!err && (tmpim = imlib_load_image(tmppath)) != NULL) { if (!err && (tmpim = imlib_load_image(tmppath)) != NULL) {
byte_order = exif_data_get_byte_order(ed); byte_order = exif_data_get_byte_order(ed);
ifd = ed->ifd[EXIF_IFD_EXIF]; ifd = ed->ifd[EXIF_IFD_EXIF];
entry = exif_content_get_entry(ifd, EXIF_TAG_PIXEL_X_DIMENSION); entry = exif_content_get_entry(ifd, EXIF_TAG_PIXEL_X_DIMENSION);
if (entry != NULL) if (entry != NULL)
pw = exif_get_long(entry->data, byte_order); pw = exif_get_long(entry->data, byte_order);
entry = exif_content_get_entry(ifd, EXIF_TAG_PIXEL_Y_DIMENSION); entry = exif_content_get_entry(ifd, EXIF_TAG_PIXEL_Y_DIMENSION);
if (entry != NULL) if (entry != NULL)
ph = exif_get_long(entry->data, byte_order); ph = exif_get_long(entry->data, byte_order);
imlib_context_set_image(tmpim); imlib_context_set_image(tmpim);
w = imlib_image_get_width(); w = imlib_image_get_width();
h = imlib_image_get_height(); h = imlib_image_get_height();
if (pw > w && ph > h && (pw - ph >= 0) == (w - h >= 0)) { if (pw > w && ph > h && (pw - ph >= 0) == (w - h >= 0)) {
zw = (float) pw / (float) w; zw = (float) pw / (float) w;
zh = (float) ph / (float) h; zh = (float) ph / (float) h;
if (zw < zh) { if (zw < zh) {
pw /= zh; pw /= zh;
x = (w - pw) / 2; x = (w - pw) / 2;
w = pw; w = pw;
} else if (zw > zh) { } else if (zw > zh) {
ph /= zw; ph /= zw;
y = (h - ph) / 2; y = (h - ph) / 2;
h = ph; h = ph;
}
} }
if ((im = imlib_create_cropped_image(x, y, w, h)) == NULL)
die("could not allocate memory");
imlib_free_image_and_decache();
} }
if ((im = imlib_create_cropped_image(x, y, w, h)) == NULL) unlink(tmppath);
die("could not allocate memory");
imlib_free_image_and_decache();
} }
unlink(tmppath); exif_data_unref(ed);
} }
exif_data_unref(ed);
} }
#endif #endif
if (im == NULL && (access(file->path, R_OK) < 0 || if (im == NULL && (access(file->path, R_OK) < 0 ||
@ -337,7 +322,7 @@ bool tns_load(tns_t *tns, int n, const fileinfo_t *file,
imlib_free_image_and_decache(); imlib_free_image_and_decache();
if (use_cache && !cache_hit) if (!cache_hit)
tns_cache_write(t, true); tns_cache_write(t, true);
tns->dirty = true; tns->dirty = true;

11
util.c
View file

@ -324,14 +324,8 @@ int r_mkdir(const char *path)
if (path == NULL || *path == '\0') if (path == NULL || *path == '\0')
return -1; return -1;
if (stat(path, &stats) == 0) { if (stat(path, &stats) == 0)
if (S_ISDIR(stats.st_mode)) { return S_ISDIR(stats.st_mode) ? 0 : -1;
return 0;
} else {
warn("not a directory: %s", path);
return -1;
}
}
d = dir = (char*) s_malloc(strlen(path) + 1); d = dir = (char*) s_malloc(strlen(path) + 1);
strcpy(dir, path); strcpy(dir, path);
@ -346,7 +340,6 @@ int r_mkdir(const char *path)
err = -1; err = -1;
} }
} else if (stat(dir, &stats) < 0 || !S_ISDIR(stats.st_mode)) { } else if (stat(dir, &stats) < 0 || !S_ISDIR(stats.st_mode)) {
warn("not a directory: %s", dir);
err = -1; err = -1;
} }
if (d != NULL) if (d != NULL)