From: Vladimir Nadvornik Date: Sat, 7 Feb 2009 19:01:21 +0000 (+0000) Subject: use metadata_read_* functions where possible X-Git-Tag: v1.0.0~515 X-Git-Url: http://geeqie.org/cgi-bin/gitweb.cgi?p=geeqie.git;a=commitdiff_plain;h=22f5a68f75212287ff3924432df1902bec16feba use metadata_read_* functions where possible switch exiv2 to utf8 charset support for exiv2 formatting that depends on other tags: http://dev.robotbattle.com/bugs/view.php?id=0000516 --- diff --git a/src/bar_exif.c b/src/bar_exif.c index d7d1ebeb..c64ef237 100644 --- a/src/bar_exif.c +++ b/src/bar_exif.c @@ -15,6 +15,7 @@ #include "bar_exif.h" #include "exif.h" +#include "metadata.h" #include "filedata.h" #include "history_list.h" #include "misc.h" @@ -180,27 +181,25 @@ static gint bar_exif_row_enabled(const gchar *name) static void bar_exif_update(ExifBar *eb) { - ExifData *exif_processed; ExifData *exif; gint i; - exif_processed = exif_read_fd(eb->fd); + /* do we have any exif at all ? */ + exif = exif_read_fd(eb->fd); - if (!exif_processed) + if (!exif) { bar_exif_sensitive(eb, FALSE); return; } - - if (eb->advanced_scrolled) - { - /* show the original values from the file */ - exif = exif_get_original(exif_processed); - } else { - exif = exif_processed; + /* we will use high level functions so we can release it for now. + it will stay in the cache */ + exif_free_fd(eb->fd, exif); + exif = NULL; } + bar_exif_sensitive(eb, TRUE); @@ -210,7 +209,6 @@ static void bar_exif_update(ExifBar *eb) for (i = 0; ExifUIList[i].key; i++) { gchar *text; - gchar *utf8_text; if (ExifUIList[i].current == EXIF_UI_OFF) { @@ -218,21 +216,19 @@ static void bar_exif_update(ExifBar *eb) gtk_widget_hide(eb->keys[i]); continue; } - text = exif_get_data_as_text(exif, ExifUIList[i].key); - utf8_text = utf8_validate_or_convert(text); - g_free(text); + text = metadata_read_string(eb->fd, ExifUIList[i].key, METADATA_FORMATTED); if (ExifUIList[i].current == EXIF_UI_IFSET - && (!utf8_text || !*utf8_text)) + && (!text || !*text)) { gtk_widget_hide(eb->labels[i]); gtk_widget_hide(eb->keys[i]); - g_free(utf8_text); + g_free(text); continue; } gtk_widget_show(eb->labels[i]); gtk_widget_show(eb->keys[i]); - gtk_label_set_text(GTK_LABEL(eb->labels[i]), utf8_text); - g_free(utf8_text); + gtk_label_set_text(GTK_LABEL(eb->labels[i]), text); + g_free(text); } list = g_list_last(history_list_get_by_key("exif_extras")); @@ -248,7 +244,6 @@ static void bar_exif_update(ExifBar *eb) while (list && i < EXIF_BAR_CUSTOM_COUNT) { gchar *text; - gchar *utf8_text; gchar *name; gchar *buf; gchar *description; @@ -256,9 +251,7 @@ static void bar_exif_update(ExifBar *eb) name = list->data; list = list->prev; - text = exif_get_data_as_text(exif, name); - utf8_text = utf8_validate_or_convert(text); - g_free(text); + text = metadata_read_string(eb->fd, name, METADATA_FORMATTED); description = exif_get_tag_description_by_key(name); if (!description || *description == '\0') @@ -271,8 +264,8 @@ static void bar_exif_update(ExifBar *eb) gtk_label_set_text(GTK_LABEL(eb->custom_name[i]), buf); g_free(buf); - gtk_label_set_text(GTK_LABEL(eb->custom_value[i]), utf8_text); - g_free(utf8_text); + gtk_label_set_text(GTK_LABEL(eb->custom_value[i]), text); + g_free(text); gtk_widget_show(eb->custom_name[i]); gtk_widget_show(eb->custom_value[i]); @@ -297,12 +290,18 @@ static void bar_exif_update(ExifBar *eb) { GtkListStore *store; GtkTreeIter iter; + ExifData *exif_original; ExifItem *item; + exif = exif_read_fd(eb->fd); + if (!exif) return; + + exif_original = exif_get_original(exif); + store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(eb->listview))); gtk_list_store_clear(store); - item = exif_get_first_item(exif); + item = exif_get_first_item(exif_original); while (item) { gchar *tag; @@ -341,11 +340,11 @@ static void bar_exif_update(ExifBar *eb) g_free(elements); g_free(description); g_free(tag_name); - item = exif_get_next_item(exif); + item = exif_get_next_item(exif_original); } + exif_free_fd(eb->fd, exif); } - exif_free_fd(eb->fd, exif_processed); } static void bar_exif_clear(ExifBar *eb) diff --git a/src/bar_info.c b/src/bar_info.c index a8f0346d..37a4152b 100644 --- a/src/bar_info.c +++ b/src/bar_info.c @@ -509,12 +509,12 @@ static void bar_info_update(BarInfoData *bd) gtk_label_set_text(GTK_LABEL(bd->label_file_time), (bd->fd) ? text_from_time(bd->fd->date) : ""); } - comment = metadata_read_string(bd->fd, COMMENT_KEY); + comment = metadata_read_string(bd->fd, COMMENT_KEY, METADATA_PLAIN); gtk_text_buffer_set_text(comment_buffer, (comment) ? comment : "", -1); g_free(comment); - keywords = metadata_read_list(bd->fd, KEYWORD_KEY); + keywords = metadata_read_list(bd->fd, KEYWORD_KEY, METADATA_PLAIN); keyword_list_push(bd->keyword_view, keywords); bar_keyword_list_sync(bd, keywords); string_list_free(keywords); diff --git a/src/cache-loader.c b/src/cache-loader.c index 3dcc68b9..24c87474 100644 --- a/src/cache-loader.c +++ b/src/cache-loader.c @@ -16,6 +16,7 @@ #include "filedata.h" #include "exif.h" +#include "metadata.h" #include "md5-util.h" #include "ui_fileops.h" @@ -125,31 +126,24 @@ static gboolean cache_loader_process(CacheLoader *cl) !cl->cd->have_date) { time_t date = -1; - ExifData *exif; + gchar *text; - exif = exif_read_fd(cl->fd); - if (exif) + text = metadata_read_string(cl->fd, "formatted.DateTime", METADATA_FORMATTED); + if (text) { - gchar *text; + struct tm t; - text = exif_get_data_as_text(exif, "formatted.DateTime"); - if (text) - { - struct tm t; - - memset(&t, 0, sizeof(t)); + memset(&t, 0, sizeof(t)); - if (sscanf(text, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon, &t.tm_mday, - &t.tm_hour, &t.tm_min, &t.tm_sec) == 6) - { - t.tm_year -= 1900; - t.tm_mon -= 1; - t.tm_isdst = -1; - date = mktime(&t); - } - g_free(text); + if (sscanf(text, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon, &t.tm_mday, + &t.tm_hour, &t.tm_min, &t.tm_sec) == 6) + { + t.tm_year -= 1900; + t.tm_mon -= 1; + t.tm_isdst = -1; + date = mktime(&t); } - exif_free_fd(cl->fd, exif); + g_free(text); } cl->cd->date = date; diff --git a/src/exif.c b/src/exif.c index e7f41e28..459257d7 100644 --- a/src/exif.c +++ b/src/exif.c @@ -1311,13 +1311,8 @@ ExifItem *exif_get_item(ExifData *exif, const gchar *key) #define EXIF_DATA_AS_TEXT_MAX_COUNT 16 -gchar *exif_item_get_string(ExifItem *item, gint idx) -{ - return exif_item_get_data_as_text(item); -} - -gchar *exif_item_get_data_as_text(ExifItem *item) +static gchar *exif_item_get_data_as_text_full(ExifItem *item, MetadataFormat format) { const ExifMarker *marker; gpointer data; @@ -1342,7 +1337,7 @@ gchar *exif_item_get_data_as_text(ExifItem *item) case EXIF_FORMAT_BYTE_UNSIGNED: case EXIF_FORMAT_BYTE: case EXIF_FORMAT_UNDEFINED: - if (ne == 1 && marker->list) + if (ne == 1 && marker->list && format == METADATA_FORMATTED) { gchar *result; guchar val; @@ -1370,7 +1365,7 @@ gchar *exif_item_get_data_as_text(ExifItem *item) if (item->data) string = g_string_append(string, (gchar *)(item->data)); break; case EXIF_FORMAT_SHORT_UNSIGNED: - if (ne == 1 && marker->list) + if (ne == 1 && marker->list && format == METADATA_FORMATTED) { gchar *result; @@ -1453,6 +1448,16 @@ gchar *exif_item_get_data_as_text(ExifItem *item) return text; } +gchar *exif_item_get_string(ExifItem *item, gint idx) +{ + return exif_item_get_data_as_text_full(item, METADATA_PLAIN); +} + +gchar *exif_item_get_data_as_text(ExifItem *item) +{ + return exif_item_get_data_as_text_full(item, METADATA_FORMATTED); +} + gint exif_item_get_integer(ExifItem *item, gint *value) { if (!item) return FALSE; @@ -1596,13 +1601,25 @@ gint exif_update_metadata(ExifData *exif, const gchar *key, const GList *values) return 0; } -GList *exif_get_metadata(ExifData *exif, const gchar *key) +GList *exif_get_metadata(ExifData *exif, const gchar *key, MetadataFormat format) { gchar *str; - ExifItem *item = exif_get_item(exif, key); + ExifItem *item; + + if (!key) return NULL; + + if (format == METADATA_FORMATTED) + { + gchar *text; + gint key_valid; + text = exif_get_formatted_by_key(exif, key, &key_valid); + if (key_valid) return g_list_append(NULL, text); + } + + item = exif_get_item(exif, key); if (!item) return NULL; - str = exif_item_get_string(item, 0); + str = exif_item_get_data_as_text_full(item, format); if (!str) return NULL; @@ -1692,6 +1709,9 @@ void exif_free_preview(guchar *buf) g_assert_not_reached(); } +void exif_init(void) +{ +} #endif /* not HAVE_EXIV2 */ diff --git a/src/exif.h b/src/exif.h index 6882ee7f..71550dd7 100644 --- a/src/exif.h +++ b/src/exif.h @@ -92,7 +92,6 @@ typedef enum { EXIF_UNIT_CENTIMETER = 3 } ExifUnitType; - typedef struct _ExifFormattedText ExifFormattedText; struct _ExifFormattedText { @@ -107,6 +106,8 @@ struct _ExifFormattedText *----------------------------------------------------------------------------- */ +void exif_init(void); + ExifData *exif_read(gchar *path, gchar *sidecar_path, GHashTable *modified_xmp); ExifData *exif_read_fd(FileData *fd); @@ -151,7 +152,7 @@ gchar *exif_get_tag_description_by_key(const gchar *key); gchar *exif_get_formatted_by_key(ExifData *exif, const gchar *key, gint *key_valid); gint exif_update_metadata(ExifData *exif, const gchar *key, const GList *values); -GList *exif_get_metadata(ExifData *exif, const gchar *key); +GList *exif_get_metadata(ExifData *exif, const gchar *key, MetadataFormat format); guchar *exif_get_color_profile(ExifData *exif, guint *data_len); diff --git a/src/exiv2.cc b/src/exiv2.cc index d9d66c6a..42427390 100644 --- a/src/exiv2.cc +++ b/src/exiv2.cc @@ -350,6 +350,16 @@ public: extern "C" { + +void exif_init(void) +{ +#ifdef EXV_ENABLE_NLS + bind_textdomain_codeset (EXV_PACKAGE, "UTF-8"); +#endif +} + + + static void _ExifDataProcessed_update_xmp(gpointer key, gpointer value, gpointer data) { exif_update_metadata((ExifData *)data, (gchar *)key, (GList *)value); @@ -604,7 +614,7 @@ char *exif_item_get_description(ExifItem *item) { try { if (!item) return NULL; - return g_locale_to_utf8(((Exiv2::Metadatum *)item)->tagLabel().c_str(), -1, NULL, NULL, NULL); + return utf8_validate_or_convert(((Exiv2::Metadatum *)item)->tagLabel().c_str()); } catch (std::exception& e) { // std::cout << "Caught Exiv2 exception '" << e << "'\n"; @@ -678,7 +688,7 @@ gchar *exif_item_get_data_as_text(ExifItem *item) if (!item) return NULL; Exiv2::Metadatum *metadatum = (Exiv2::Metadatum *)item; #if EXIV2_TEST_VERSION(0,17,0) - return g_locale_to_utf8(metadatum->print().c_str(), -1, NULL, NULL, NULL); + return utf8_validate_or_convert(metadatum->print().c_str()); #else std::stringstream str; Exiv2::Exifdatum *exifdatum; @@ -695,7 +705,7 @@ gchar *exif_item_get_data_as_text(ExifItem *item) str << *xmpdatum; #endif - return g_locale_to_utf8(str.str().c_str(), -1, NULL, NULL, NULL); + return utf8_validate_or_convert(str.str().c_str()); #endif } catch (Exiv2::AnyError& e) { @@ -720,8 +730,7 @@ gchar *exif_item_get_string(ExifItem *item, int idx) if (pos != std::string::npos) str = str.substr(pos+1); } -// return g_locale_to_utf8(str.c_str(), -1, NULL, NULL, NULL); // FIXME - return g_strdup(str.c_str()); + return utf8_validate_or_convert(str.c_str()); } catch (Exiv2::AnyError& e) { return NULL; @@ -764,7 +773,7 @@ gchar *exif_get_tag_description_by_key(const gchar *key) { try { Exiv2::ExifKey ekey(key); - return g_locale_to_utf8(Exiv2::ExifTags::tagLabel(ekey.tag(), ekey.ifdId ()), -1, NULL, NULL, NULL); + return utf8_validate_or_convert(Exiv2::ExifTags::tagLabel(ekey.tag(), ekey.ifdId ())); } catch (Exiv2::AnyError& e) { std::cout << "Caught Exiv2 exception '" << e << "'\n"; @@ -875,11 +884,12 @@ gint exif_update_metadata(ExifData *exif, const gchar *key, const GList *values) } -static GList *exif_add_value_to_glist(GList *list, Exiv2::Metadatum &item) +static GList *exif_add_value_to_glist(GList *list, Exiv2::Metadatum &item, MetadataFormat format, const Exiv2::ExifData *metadata) { #if EXIV2_TEST_VERSION(0,16,0) Exiv2::TypeId id = item.typeId(); - if (id == Exiv2::asciiString || + if (format == METADATA_FORMATTED || + id == Exiv2::asciiString || id == Exiv2::undefined || id == Exiv2::string || id == Exiv2::date || @@ -891,11 +901,48 @@ static GList *exif_add_value_to_glist(GList *list, Exiv2::Metadatum &item) { #endif /* read as a single entry */ - std::string str = item.toString(); - if (str.length() > 5 && str.substr(0, 5) == "lang=") + std::string str; + + if (format == METADATA_FORMATTED) { - std::string::size_type pos = str.find_first_of(' '); - if (pos != std::string::npos) str = str.substr(pos+1); +#if EXIV2_TEST_VERSION(0,17,0) + str = item.print( +#if EXIV2_TEST_VERSION(0,18,0) + metadata +#endif + ); +#else + std::stringstream stream; + Exiv2::Exifdatum *exifdatum; + Exiv2::Iptcdatum *iptcdatum; +#if EXIV2_TEST_VERSION(0,16,0) + Exiv2::Xmpdatum *xmpdatum; +#endif + if ((exifdatum = dynamic_cast(metadatum))) + stream << *exifdatum; + else if ((iptcdatum = dynamic_cast(metadatum))) + stream << *iptcdatum; +#if EXIV2_TEST_VERSION(0,16,0) + else if ((xmpdatum = dynamic_cast(metadatum))) + stream << *xmpdatum; +#endif + str = stream.str(); +#endif + if (str.length() > 1024) + { + /* truncate very long strings, they cause problems in gui */ + str.erase(1024); + str.append("..."); + } + } + else + { + str = item.toString(); + if (str.length() > 5 && str.substr(0, 5) == "lang=") + { + std::string::size_type pos = str.find_first_of(' '); + if (pos != std::string::npos) str = str.substr(pos+1); + } } list = g_list_append(list, utf8_validate_or_convert(str.c_str())); #if EXIV2_TEST_VERSION(0,16,0) @@ -911,16 +958,15 @@ static GList *exif_add_value_to_glist(GList *list, Exiv2::Metadatum &item) return list; } -static GList *exif_get_metadata_simple(ExifData *exif, const gchar *key) +static GList *exif_get_metadata_simple(ExifData *exif, const gchar *key, MetadataFormat format) { GList *list = NULL; try { try { Exiv2::ExifKey ekey(key); - Exiv2::ExifData::iterator pos = exif->exifData().findKey(ekey); if (pos != exif->exifData().end()) - list = exif_add_value_to_glist(list, *pos); + list = exif_add_value_to_glist(list, *pos, format, &exif->exifData()); } catch (Exiv2::AnyError& e) { @@ -930,7 +976,7 @@ static GList *exif_get_metadata_simple(ExifData *exif, const gchar *key) while (pos != exif->iptcData().end()) { if (pos->key() == key) - list = exif_add_value_to_glist(list, *pos); + list = exif_add_value_to_glist(list, *pos, format, NULL); ++pos; } @@ -940,7 +986,7 @@ static GList *exif_get_metadata_simple(ExifData *exif, const gchar *key) Exiv2::XmpKey ekey(key); Exiv2::XmpData::iterator pos = exif->xmpData().findKey(ekey); if (pos != exif->xmpData().end()) - list = exif_add_value_to_glist(list, *pos); + list = exif_add_value_to_glist(list, *pos, format, NULL); #endif } } @@ -951,23 +997,33 @@ static GList *exif_get_metadata_simple(ExifData *exif, const gchar *key) return list; } -GList *exif_get_metadata(ExifData *exif, const gchar *key) +GList *exif_get_metadata(ExifData *exif, const gchar *key, MetadataFormat format) { GList *list = NULL; - - list = exif_get_metadata_simple(exif, key); + + if (!key) return NULL; + + if (format == METADATA_FORMATTED) + { + gchar *text; + gint key_valid; + text = exif_get_formatted_by_key(exif, key, &key_valid); + if (key_valid) return g_list_append(NULL, text); + } + + list = exif_get_metadata_simple(exif, key, format); /* the following code can be ifdefed out as soon as Exiv2 supports it */ if (!list) { const AltKey *alt_key = find_alt_key(key); if (alt_key && alt_key->iptc_key) - list = exif_get_metadata_simple(exif, alt_key->iptc_key); + list = exif_get_metadata_simple(exif, alt_key->iptc_key, format); #if !EXIV2_TEST_VERSION(0,17,0) /* with older Exiv2 versions exif is not synced */ if (!list && alt_key && alt_key->exif_key) - list = exif_get_metadata_simple(exif, alt_key->exif_key); + list = exif_get_metadata_simple(exif, alt_key->exif_key, format); #endif } return list; diff --git a/src/image-overlay.c b/src/image-overlay.c index d0a00768..93ec3310 100644 --- a/src/image-overlay.c +++ b/src/image-overlay.c @@ -178,7 +178,7 @@ static gchar *keywords_to_string(FileData *fd) g_assert(fd); - keywords = metadata_read_list(fd, KEYWORD_KEY); + keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN); if (keywords) { @@ -278,24 +278,14 @@ static gchar *image_osd_mkinfo(const gchar *str, ImageWindow *imd, GHashTable *v } else if (strcmp(name, "comment") == 0) { - data = metadata_read_string(imd->image_fd, COMMENT_KEY); + data = metadata_read_string(imd->image_fd, COMMENT_KEY, METADATA_PLAIN); } else { - /* - keywords and comment can't be read between exif_read_fd and exif_free_fd calls - because fd->exif does not count references - on the other hand, it is OK to call it in the loop because it is cached - */ - - ExifData *exif; - exif = exif_read_fd(imd->image_fd); - data = g_strdup(g_hash_table_lookup(vars, name)); if (data && strcmp(name, "zoom") == 0) imd->overlay_show_zoom = TRUE; - if (!data && exif) - data = exif_get_data_as_text(exif, name); - exif_free_fd(imd->image_fd, exif); + if (!data) + data = metadata_read_string(imd->image_fd, name, METADATA_FORMATTED); } if (data && *data && limit > 0 && strlen(data) > limit + 3) diff --git a/src/image.c b/src/image.c index 5d4e3e45..ec601c81 100644 --- a/src/image.c +++ b/src/image.c @@ -18,6 +18,7 @@ #include "collect.h" #include "color-man.h" #include "exif.h" +#include "metadata.h" #include "histogram.h" #include "image-load.h" #include "image-overlay.h" @@ -999,31 +1000,20 @@ GdkPixbuf *image_get_pixbuf(ImageWindow *imd) void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom, gint lazy) { - ExifData *exif = NULL; - gint read_exif_for_color_profile = (imd->color_profile_enable && imd->color_profile_use_image); - gint read_exif_for_orientation = FALSE; /* read_exif and similar functions can actually notice that the file has changed and triger a notification that removes the pixbuf from cache and unref it. Therefore we must ref it here before it is taken over by the renderer. */ if (pixbuf) g_object_ref(pixbuf); - if (imd->image_fd && imd->image_fd->user_orientation) - imd->orientation = imd->image_fd->user_orientation; - else if (options->image.exif_rotate_enable) - read_exif_for_orientation = TRUE; - - if (read_exif_for_color_profile || read_exif_for_orientation) + if (imd->image_fd) { - gint orientation; - - exif = exif_read_fd(imd->image_fd); - - if (exif && read_exif_for_orientation) + if (imd->image_fd->user_orientation) + { + imd->orientation = imd->image_fd->user_orientation; + } + else if (options->image.exif_rotate_enable) { - if (exif_get_integer(exif, "Exif.Image.Orientation", &orientation)) - imd->orientation = orientation; - else - imd->orientation = 1; + imd->orientation = metadata_read_int(imd->image_fd, "Exif.Image.Orientation", EXIF_ORIENTATION_TOP_LEFT); imd->image_fd->exif_orientation = imd->orientation; } } @@ -1049,15 +1039,18 @@ void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom, gint if (imd->color_profile_enable) { + ExifData *exif = NULL; + + if (imd->color_profile_use_image) exif = exif_read_fd(imd->image_fd); + if (!image_post_process_color(imd, 0, exif, FALSE)) { /* fixme: note error to user */ // image_state_set(imd, IMAGE_STATE_COLOR_ADJ); } - } + if (exif) exif_free_fd(imd->image_fd, exif); - if (read_exif_for_color_profile || read_exif_for_orientation) - 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) ); diff --git a/src/main.c b/src/main.c index 273afd45..2d99632d 100644 --- a/src/main.c +++ b/src/main.c @@ -32,6 +32,7 @@ #include "thumb.h" #include "metadata.h" #include "editors.h" +#include "exif.h" #include /* for keyboard values */ @@ -728,6 +729,8 @@ gint main(gint argc, gchar *argv[]) textdomain(PACKAGE); #endif + exif_init(); + /* setup random seed for random slideshow */ srand(time(NULL)); diff --git a/src/metadata.c b/src/metadata.c index 1c30babc..685502de 100644 --- a/src/metadata.c +++ b/src/metadata.c @@ -447,14 +447,14 @@ static GList *remove_duplicate_strings_from_list(GList *list) return g_list_reverse(newlist); } -GList *metadata_read_list(FileData *fd, const gchar *key) +GList *metadata_read_list(FileData *fd, const gchar *key, MetadataFormat format) { ExifData *exif; GList *list = NULL; if (!fd) return NULL; /* unwritten data overide everything */ - if (fd->modified_xmp) + if (fd->modified_xmp && format == METADATA_PLAIN) { list = g_hash_table_lookup(fd->modified_xmp, key); if (list) return string_list_copy(list); @@ -480,14 +480,14 @@ GList *metadata_read_list(FileData *fd, const gchar *key) exif = exif_read_fd(fd); /* this is cached, thus inexpensive */ if (!exif) return NULL; - list = exif_get_metadata(exif, key); + list = exif_get_metadata(exif, key, format); exif_free_fd(fd, exif); return list; } -gchar *metadata_read_string(FileData *fd, const gchar *key) +gchar *metadata_read_string(FileData *fd, const gchar *key, MetadataFormat format) { - GList *string_list = metadata_read_list(fd, key); + GList *string_list = metadata_read_list(fd, key, format); if (string_list) { gchar *str = string_list->data; @@ -497,10 +497,23 @@ gchar *metadata_read_string(FileData *fd, const gchar *key) } return NULL; } + +guint64 metadata_read_int(FileData *fd, const gchar *key, guint64 fallback) +{ + guint64 ret; + gchar *endptr; + gchar *string = metadata_read_string(fd, key, METADATA_PLAIN); + if (!string) return fallback; + + ret = g_ascii_strtoull(string, &endptr, 10); + if (string == endptr) ret = fallback; + g_free(string); + return ret; +} gboolean metadata_append_string(FileData *fd, const gchar *key, const char *value) { - gchar *str = metadata_read_string(fd, key); + gchar *str = metadata_read_string(fd, key, METADATA_PLAIN); if (!str) { @@ -518,7 +531,7 @@ gboolean metadata_append_string(FileData *fd, const gchar *key, const char *valu gboolean metadata_append_list(FileData *fd, const gchar *key, const GList *values) { - GList *list = metadata_read_list(fd, key); + GList *list = metadata_read_list(fd, key, METADATA_PLAIN); if (!list) { @@ -598,7 +611,7 @@ gboolean meta_data_get_keyword_mark(FileData *fd, gint n, gpointer data) { GList *keywords; gboolean found = FALSE; - keywords = metadata_read_list(fd, KEYWORD_KEY); + keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN); if (keywords) { GList *work = keywords; @@ -625,7 +638,7 @@ gboolean meta_data_set_keyword_mark(FileData *fd, gint n, gboolean value, gpoint gboolean found = FALSE; gboolean changed = FALSE; GList *work; - keywords = metadata_read_list(fd, KEYWORD_KEY); + keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN); work = keywords; diff --git a/src/metadata.h b/src/metadata.h index 6e674288..1ea4955e 100644 --- a/src/metadata.h +++ b/src/metadata.h @@ -27,8 +27,9 @@ gint metadata_queue_length(void); gboolean metadata_write_list(FileData *fd, const gchar *key, const GList *values); gboolean metadata_write_string(FileData *fd, const gchar *key, const char *value); -GList *metadata_read_list(FileData *fd, const gchar *key); -gchar *metadata_read_string(FileData *fd, const gchar *key); +GList *metadata_read_list(FileData *fd, const gchar *key, MetadataFormat format); +gchar *metadata_read_string(FileData *fd, const gchar *key, MetadataFormat format); +guint64 metadata_read_int(FileData *fd, const gchar *key, guint64 fallback); gboolean metadata_append_string(FileData *fd, const gchar *key, const char *value); gboolean metadata_append_list(FileData *fd, const gchar *key, const GList *values); diff --git a/src/pan-view.c b/src/pan-view.c index 4619867e..15fba2f9 100644 --- a/src/pan-view.c +++ b/src/pan-view.c @@ -18,6 +18,7 @@ #include "dnd.h" #include "editors.h" #include "exif.h" +#include "metadata.h" #include "fullscreen.h" #include "history_list.h" #include "img-view.h" @@ -1434,13 +1435,10 @@ static gint pan_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpoin static void pan_info_add_exif(PanTextAlignment *ta, FileData *fd) { - ExifData *exif; GList *work; gint i; if (!fd) return; - exif = exif_read_fd(fd); - if (!exif) return; pan_text_alignment_add(ta, NULL, NULL); @@ -1449,11 +1447,11 @@ static void pan_info_add_exif(PanTextAlignment *ta, FileData *fd) gchar *label; gchar *desc; gchar *text; - gchar *utf8_text; if (ExifUIList[i].current == EXIF_UI_OFF) continue; - text = exif_get_data_as_text(exif, ExifUIList[i].key); + text = metadata_read_string(fd, ExifUIList[i].key, METADATA_FORMATTED); + if (ExifUIList[i].current == EXIF_UI_IFSET && (!text || !*text)) { g_free(text); @@ -1463,11 +1461,9 @@ static void pan_info_add_exif(PanTextAlignment *ta, FileData *fd) desc = exif_get_description_by_key(ExifUIList[i].key); label = g_strdup_printf("%s:", desc); g_free(desc); - utf8_text = utf8_validate_or_convert(text); - g_free(text); - pan_text_alignment_add(ta, label, utf8_text); + pan_text_alignment_add(ta, label, text); g_free(label); - g_free(utf8_text); + g_free(text); } work = g_list_last(history_list_get_by_key("exif_extras")); @@ -1480,20 +1476,15 @@ static void pan_info_add_exif(PanTextAlignment *ta, FileData *fd) name = work->data; work = work->prev; - text = exif_get_data_as_text(exif, name); + text = metadata_read_string(fd, name, METADATA_FORMATTED); if (text) { gchar *label = g_strdup_printf("%s:", name); - gchar *utf8_text = utf8_validate_or_convert(text); - - g_free(text); - pan_text_alignment_add(ta, label, utf8_text); + pan_text_alignment_add(ta, label, text); g_free(label); - g_free(utf8_text); + g_free(text); } } - - exif_free_fd(fd, exif); } static void pan_info_update(PanWindow *pw, PanItem *pi) diff --git a/src/search.c b/src/search.c index e42f15b1..db7ed896 100644 --- a/src/search.c +++ b/src/search.c @@ -1804,7 +1804,7 @@ static gint search_file_next(SearchData *sd) tested = TRUE; match = FALSE; - list = metadata_read_list(fd, KEYWORD_KEY); + list = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN); if (list) { @@ -1884,7 +1884,7 @@ static gint search_file_next(SearchData *sd) tested = TRUE; match = FALSE; - comment = metadata_read_string(fd, COMMENT_KEY); + comment = metadata_read_string(fd, COMMENT_KEY, METADATA_PLAIN); if (comment) { diff --git a/src/thumb.c b/src/thumb.c index 3e7143e0..9bedcaed 100644 --- a/src/thumb.c +++ b/src/thumb.c @@ -21,6 +21,7 @@ #include "thumb_standard.h" #include "ui_fileops.h" #include "exif.h" +#include "metadata.h" #include @@ -141,14 +142,7 @@ static void thumb_loader_done_cb(ImageLoader *il, gpointer data) { if (!tl->fd->exif_orientation) { - ExifData *exif = exif_read_fd(tl->fd); - gint orientation; - - if (exif && exif_get_integer(exif, "Exif.Image.Orientation", &orientation)) - tl->fd->exif_orientation = orientation; - else - tl->fd->exif_orientation = EXIF_ORIENTATION_TOP_LEFT; - exif_free_fd(tl->fd, exif); + tl->fd->exif_orientation = metadata_read_int(tl->fd, "Exif.Image.Orientation", EXIF_ORIENTATION_TOP_LEFT); } if (tl->fd->exif_orientation != EXIF_ORIENTATION_TOP_LEFT) diff --git a/src/thumb_standard.c b/src/thumb_standard.c index 6780389c..095c22a9 100644 --- a/src/thumb_standard.c +++ b/src/thumb_standard.c @@ -20,6 +20,7 @@ #include "ui_fileops.h" #include "filedata.h" #include "exif.h" +#include "metadata.h" /* @@ -394,14 +395,7 @@ static GdkPixbuf *thumb_loader_std_finish(ThumbLoaderStd *tl, GdkPixbuf *pixbuf, { if (!tl->fd->exif_orientation) { - ExifData *exif = exif_read_fd(tl->fd); - gint orientation; - - if (exif && exif_get_integer(exif, "Exif.Image.Orientation", &orientation)) - tl->fd->exif_orientation = orientation; - else - tl->fd->exif_orientation = EXIF_ORIENTATION_TOP_LEFT; - exif_free_fd(tl->fd, exif); + tl->fd->exif_orientation = metadata_read_int(tl->fd, "Exif.Image.Orientation", EXIF_ORIENTATION_TOP_LEFT); } if (tl->fd->exif_orientation != EXIF_ORIENTATION_TOP_LEFT) diff --git a/src/typedefs.h b/src/typedefs.h index 76f3e129..f7cba7d9 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -164,6 +164,12 @@ typedef enum { CHANGE_GENERIC_ERROR = 1 << 16 } ChangeError; +typedef enum { + METADATA_PLAIN = 0, /* format that can be edited and written back */ + METADATA_FORMATTED = 1 /* for display only */ +} MetadataFormat; + + #define MAX_SPLIT_IMAGES 4 typedef struct _ImageLoader ImageLoader;