Create thumbnail cache dir automatically
This commit is contained in:
parent
cd02f2dd86
commit
5cfae63620
16
sxiv.1
16
sxiv.1
@ -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
117
thumbs.c
@ -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, ×);
|
utime(cfile, ×);
|
||||||
} 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
11
util.c
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user