exif-int.h \
exif-common.c \
exiv2.cc \
+ filecache.c \
+ filecache.h \
filedata.c \
filedata.h \
filefilter.c \
}
}
- exif_free(exif);
+ exif_free_fd(eb->fd, exif);
}
static void bar_exif_clear(ExifBar *eb)
}
}
- exif_free(exif);
+ exif_free_fd(fd, exif);
return (comment && *comment) || (keywords && *keywords);
}
success = exif_write(exif);
- exif_free(exif);
+ exif_free_fd(fd, exif);
return success;
}
}
g_free(text);
}
- exif_free(exif);
+ exif_free_fd(cl->fd, exif);
}
cl->cd->date = date;
#include "filedata.h"
#include "filefilter.h"
+#include "filecache.h"
#include "format_raw.h"
#include "ui_fileops.h"
return NULL;
}
+
+static FileCacheData *exif_cache;
+
+void exif_release_cb(FileData *fd)
+{
+ exif_free(fd->exif);
+ fd->exif = NULL;
+}
+
ExifData *exif_read_fd(FileData *fd)
{
gchar *sidecar_path = NULL;
if (!fd) return NULL;
+
+ if (!exif_cache) exif_cache = file_cache_new(exif_release_cb, 4);
+
+ if (file_cache_get(exif_cache, fd)) return fd->exif;
if (filter_file_class(fd->extension, FORMAT_CLASS_RAWIMAGE))
{
}
- // FIXME: some caching would be nice
- return exif_read(fd->path, sidecar_path);
+ fd->exif = exif_read(fd->path, sidecar_path);
+ return fd->exif;
}
-
+void exif_free_fd(FileData *fd, ExifData *exif)
+{
+ if (!fd) return;
+ g_assert(fd->exif == exif);
+
+ file_cache_put(exif_cache, fd, 1);
+}
/* embedded icc in jpeg */
typedef struct _ExifItem ExifItem;
-typedef struct _ExifData ExifData;
-
typedef struct _ExifRational ExifRational;
struct _ExifRational
{
ExifData *exif_read(gchar *path, gchar *sidecar_path);
ExifData *exif_read_fd(FileData *fd);
+void exif_free_fd(FileData *fd, ExifData *exif);
int exif_write(ExifData *exif);
--- /dev/null
+/*
+ * Geeqie
+ * Copyright (C) 2008 The Geeqie Team
+ *
+ * Author: Vladimir Nadvornik
+ *
+ * This software is released under the GNU General Public License (GNU GPL).
+ * Please read the included file COPYING for more information.
+ * This software comes with no warranty of any kind, use at your own risk!
+ */
+
+
+#include "main.h"
+#include "filecache.h"
+
+/* this implements a simple LRU algorithm */
+
+struct _FileCacheData {
+ FileCacheReleaseFunc release;
+ GList *list;
+ gulong max_size;
+ gulong size;
+ };
+
+
+FileCacheData *file_cache_new(FileCacheReleaseFunc release, gulong max_size)
+{
+ FileCacheData *fc = g_new(FileCacheData, 1);
+ fc->release = release;
+ fc->list = NULL;
+ fc->max_size = max_size;
+ fc->size = 0;
+ return fc;
+}
+
+gint file_cache_get(FileCacheData *fc, FileData *fd)
+{
+ GList *work;
+ if ((work = g_list_find(fc->list, fd)))
+ {
+ fc->list = g_list_remove_link(fc->list, work);
+ fc->list = g_list_concat(work, fc->list);
+ DEBUG_1("cache hit: %s", fd->path);
+ return TRUE;
+ }
+ DEBUG_1("cache miss: %s", fd->path);
+ return FALSE;
+}
+
+void file_cache_put(FileCacheData *fc, FileData *fd, gulong size)
+{
+ GList *work;
+ FileData *last_fd;
+ if ((work = g_list_find(fc->list, fd)))
+ {
+ /* entry already exists, move it to the beginning */
+ fc->list = g_list_remove_link(fc->list, work);
+ fc->list = g_list_concat(work, fc->list);
+ return;
+ }
+
+ DEBUG_1("cache add: %s", fd->path);
+ file_data_ref(fd);
+ fc->list = g_list_prepend(fc->list, fd);
+ fc->size++; /* FIXME: use size */
+
+ if (fc->size < fc->max_size) return;
+
+ fc->size--;
+ work = g_list_last(fc->list);
+ last_fd = work->data;
+ fc->list = g_list_delete_link(fc->list, work);
+ DEBUG_1("cache remove: %s", last_fd->path);
+ fc->release(last_fd);
+ file_data_unref(last_fd);
+}
--- /dev/null
+/*
+ * Geeqie
+ * Copyright (C) 2008 The Geeqie Team
+ *
+ * Author: Vladimir Nadvornik
+ *
+ * This software is released under the GNU General Public License (GNU GPL).
+ * Please read the included file COPYING for more information.
+ * This software comes with no warranty of any kind, use at your own risk!
+ */
+
+#ifndef FILECACHE_H
+#define FILECACHE_H
+
+#include "main.h"
+#include "filedata.h"
+
+typedef struct _FileCacheData FileCacheData;
+typedef void (*FileCacheReleaseFunc)(FileData *fd);
+
+
+FileCacheData *file_cache_new(FileCacheReleaseFunc release, gulong max_size);
+gint file_cache_get(FileCacheData *fc, FileData *fd);
+void file_cache_put(FileCacheData *fc, FileData *fd, gulong size);
+
+#endif
g_free(data);
}
- exif_free(exif);
+ exif_free_fd(imd->image_fd, exif);
/* search and destroy empty lines */
end = new->str;
while ((start = strchr(end, '\n')))
if (!imd->cm) image_post_process_alter(imd, clamp);
- exif_free(exif);
+ exif_free_fd(fd, exif);
#endif
}
if (imd->color_profile_use_image) exif = exif_read_fd(imd->image_fd);
// image_post_process_color(imd, imd->prev_color_row, exif, TRUE);
- exif_free(exif);
+ exif_free_fd(imd->image_fd, exif);
}
success = TRUE;
}
}
}
- exif_free(exif);
+ exif_free_fd(imd->image_fd, exif);
if (imd->cm || imd->desaturate)
pixbuf_renderer_set_post_process_func((PixbufRenderer *)imd->pr, image_post_process_tile_color_cb, (gpointer) imd, (imd->cm != NULL) );
}
}
- exif_free(exif);
+ exif_free_fd(fd, exif);
}
static void pan_info_update(PanWindow *pw, PanItem *pi)
tl->fd->exif_orientation = orientation;
else
tl->fd->exif_orientation = EXIF_ORIENTATION_TOP_LEFT;
- exif_free(exif);
+ exif_free_fd(tl->fd, exif);
}
if (tl->fd->exif_orientation != EXIF_ORIENTATION_TOP_LEFT)
tl->fd->exif_orientation = orientation;
else
tl->fd->exif_orientation = EXIF_ORIENTATION_TOP_LEFT;
- exif_free(exif);
+ exif_free_fd(tl->fd, exif);
}
if (tl->fd->exif_orientation != EXIF_ORIENTATION_TOP_LEFT)
typedef struct _SecureSaveInfo SecureSaveInfo;
+typedef struct _ExifData ExifData;
+
typedef struct _Editor Editor;
struct _Editor {
gchar *name;
gint version; /* increased when any field in this structure is changed */
gint user_orientation;
gint exif_orientation;
+
+ ExifData *exif;
};
struct _LayoutWindow