# HG changeset patch # User nadvornik # Date 1205663572 0 # Node ID 0584cb78aa14e69278771bfe21e11c056a509bb0 # Parent 9eafc4957f1ad46c0c756d25a09973aad3425fd9 write comment and keywords to xmp, sidecars are used if exist diff -r 9eafc4957f1a -r 0584cb78aa14 src/bar_exif.c --- a/src/bar_exif.c Sat Mar 15 19:53:33 2008 +0000 +++ b/src/bar_exif.c Sun Mar 16 10:32:52 2008 +0000 @@ -172,7 +172,7 @@ ExifData *exif; gint len, i; - exif = exif_read(eb->fd->path, FALSE); + exif = exif_read_fd(eb->fd, FALSE); if (!exif) { diff -r 9eafc4957f1a -r 0584cb78aa14 src/bar_info.c --- a/src/bar_info.c Sat Mar 15 19:53:33 2008 +0000 +++ b/src/bar_info.c Sun Mar 16 10:32:52 2008 +0000 @@ -11,6 +11,8 @@ #include "gqview.h" +#include "exif.h" + #include "bar_info.h" #include "cache.h" @@ -47,7 +49,7 @@ *------------------------------------------------------------------- */ -gint comment_write(gchar *path, GList *keywords, const gchar *comment) +static gint comment_file_write(gchar *path, GList *keywords, const gchar *comment) { FILE *f; @@ -76,7 +78,7 @@ return TRUE; } -gint comment_cache_write(FileData *fd, GList *keywords, const gchar *comment) +static gint comment_legacy_write(FileData *fd, GList *keywords, const gchar *comment) { gchar *comment_path; gint success = FALSE; @@ -113,7 +115,7 @@ comment_pathl = path_from_utf8(comment_path); - success = comment_write(comment_pathl, keywords, comment); + success = comment_file_write(comment_pathl, keywords, comment); g_free(comment_pathl); g_free(comment_path); @@ -122,7 +124,7 @@ return success; } -gint comment_read(gchar *path, GList **keywords, gchar **comment) +static gint comment_file_read(gchar *path, GList **keywords, gchar **comment) { FILE *f; gchar s_buf[1024]; @@ -184,7 +186,7 @@ return TRUE; } -gint comment_cache_read(FileData *fd, GList **keywords, gchar **comment) +static gint comment_legacy_read(FileData *fd, GList **keywords, gchar **comment) { gchar *comment_path; gchar *comment_pathl; @@ -196,7 +198,7 @@ comment_pathl = path_from_utf8(comment_path); - success = comment_read(comment_pathl, keywords, comment); + success = comment_file_read(comment_pathl, keywords, comment); g_free(comment_pathl); g_free(comment_path); @@ -204,6 +206,100 @@ return success; } +gchar *comment_key = "Xmp.dc.description"; +gchar *keyword_key = "Xmp.dc.subject"; + +static gint comment_xmp_read(FileData *fd, GList **keywords, gchar **comment) +{ + ExifData *exif = exif_read_fd(fd, FALSE); + if (!exif) return FALSE; + + if (comment) + { + ExifItem *item = exif_get_item(exif, comment_key); + *comment = exif_item_get_string(item, 0); + } + + if (keywords) + { + ExifItem *item = exif_get_item(exif, keyword_key); + int count = exif_item_get_elements(item); + int i = 0; + GList *work = NULL; + char *kw = NULL; + + while (i < count && (kw = exif_item_get_string(item, i++))) + { + work = g_list_append(work, (gpointer) kw); + } + + *keywords = work; + } + + exif_free(exif); + return TRUE; +} + +static gint comment_xmp_write(FileData *fd, GList *keywords, const gchar *comment) +{ + gint success = FALSE; + GList *work = keywords; + ExifData *exif = exif_read_fd(fd, FALSE); + if (!exif) return FALSE; + + ExifItem *item = exif_get_item(exif, comment_key); + + if (item && !(comment && comment[0])) + { + exif_item_delete(exif, item); + item = NULL; + } + + if (!item && comment && comment[0]) item = exif_add_item(exif, comment_key); + if (item) exif_item_set_string(item, comment); + + + + while ((item = exif_get_item(exif, keyword_key))) + { + exif_item_delete(exif, item); + } + + if (work) + { + item = exif_add_item(exif, keyword_key); + + while (work) + { + gchar *kw = (gchar *) work->data; + work = work->next; + + exif_item_set_string(item, kw); + } + } + + success = exif_write(exif); + + exif_free(exif); + + return success; +} + +gint comment_write(FileData *fd, GList *keywords, const gchar *comment) +{ + if (comment_xmp_write(fd, keywords, comment)) return TRUE; + + return comment_legacy_write(fd, keywords, comment); +} + +gint comment_read(FileData *fd, GList **keywords, gchar **comment) +{ + if (comment_xmp_read(fd, keywords, comment)) return TRUE; + + return comment_legacy_read(fd, keywords, comment); +} + + static gchar *comment_pull(GtkWidget *textview) { GtkTextBuffer *buffer; @@ -290,7 +386,7 @@ GList *keywords = NULL; GList *save_list = NULL; - comment_cache_read(fd, &keywords, &comment); + comment_read(fd, &keywords, &comment); if (add) { @@ -323,7 +419,7 @@ save_list = list; } - comment_cache_write(fd, save_list, comment); + comment_write(fd, save_list, comment); string_list_free(keywords); g_free(comment); @@ -625,7 +721,7 @@ list = keyword_list_pull(bd->keyword_view); comment = comment_pull(bd->comment_view); - comment_cache_write(bd->fd, list, comment); + comment_write(bd->fd, list, comment); string_list_free(list); g_free(comment); @@ -744,7 +840,7 @@ gtk_label_set_text(GTK_LABEL(bd->label_file_time), (bd->fd) ? text_from_time(bd->fd->date) : ""); } - if (comment_cache_read(bd->fd, &keywords, &comment)) + if (comment_read(bd->fd, &keywords, &comment)) { keyword_list_push(bd->keyword_view, keywords); gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->comment_view)), diff -r 9eafc4957f1a -r 0584cb78aa14 src/bar_info.h --- a/src/bar_info.h Sat Mar 15 19:53:33 2008 +0000 +++ b/src/bar_info.h Sun Mar 16 10:32:52 2008 +0000 @@ -27,11 +27,9 @@ void bar_info_maint_renamed(GtkWidget *bar, FileData *fd); -gint comment_write(gchar *path, GList *keywords, const gchar *comment); -gint comment_cache_write(FileData *fd, GList *keywords, const gchar *comment); +gint comment_write(FileData *fd, GList *keywords, const gchar *comment); -gint comment_read(gchar *path, GList **keywords, gchar **comment); -gint comment_cache_read(FileData *fd, GList **keywords, gchar **comment); +gint comment_read(FileData *fd, GList **keywords, gchar **comment); GList *keyword_list_pull(GtkWidget *text_widget); void keyword_list_push(GtkWidget *textview, GList *list); diff -r 9eafc4957f1a -r 0584cb78aa14 src/cache-loader.c --- a/src/cache-loader.c Sat Mar 15 19:53:33 2008 +0000 +++ b/src/cache-loader.c Sun Mar 16 10:32:52 2008 +0000 @@ -125,7 +125,7 @@ time_t date = -1; ExifData *exif; - exif = exif_read(cl->fd->path, FALSE); + exif = exif_read_fd(cl->fd, FALSE); if (exif) { gchar *text; diff -r 9eafc4957f1a -r 0584cb78aa14 src/exif-common.c --- a/src/exif-common.c Sat Mar 15 19:53:33 2008 +0000 +++ b/src/exif-common.c Sun Mar 16 10:32:52 2008 +0000 @@ -326,3 +326,25 @@ return NULL; } + +ExifData *exif_read_fd(FileData *fd, gint parse_color_profile) +{ + GList *work = fd->sidecar_files; + gchar *sidecar_path = NULL; + + while(work) + { + FileData *sfd = work->data; + work = work->next; + printf("sfd %s\n", sfd->path); + if (strcasecmp(sfd->extension, ".xmp") == 0) + { + sidecar_path = sfd->path; + break; + } + } + + + // FIXME: some caching would be nice + return exif_read(fd->path, sidecar_path, parse_color_profile); +} diff -r 9eafc4957f1a -r 0584cb78aa14 src/exif.c --- a/src/exif.c Sat Mar 15 19:53:33 2008 +0000 +++ b/src/exif.c Sun Mar 16 10:32:52 2008 +0000 @@ -1220,7 +1220,7 @@ g_free(exif); } -ExifData *exif_read(gchar *path, gint parse_color_profile) +ExifData *exif_read(gchar *path, gchar *sidecar_path, gint parse_color_profile) { ExifData *exif; void *f; diff -r 9eafc4957f1a -r 0584cb78aa14 src/exif.h --- a/src/exif.h Sat Mar 15 19:53:33 2008 +0000 +++ b/src/exif.h Sun Mar 16 10:32:52 2008 +0000 @@ -105,7 +105,11 @@ *----------------------------------------------------------------------------- */ -ExifData *exif_read(gchar *path, gint parse_color_profile); +ExifData *exif_read(gchar *path, gchar *sidecar_path, gint parse_color_profile); + +ExifData *exif_read_fd(FileData *fd, gint parse_color_profile); + + int exif_write(ExifData *exif); void exif_free(ExifData *exif); @@ -132,6 +136,8 @@ gint exif_item_get_integer(ExifItem *item, gint *value); ExifRational *exif_item_get_rational(ExifItem *item, gint *sign); +gchar *exif_item_get_string(ExifItem *item, int idx); + const gchar *exif_get_description_by_key(const gchar *key); const gchar *exif_get_tag_description_by_key(const gchar *key); diff -r 9eafc4957f1a -r 0584cb78aa14 src/exiv2.cc --- a/src/exiv2.cc Sat Mar 15 19:53:33 2008 +0000 +++ b/src/exiv2.cc Sun Mar 16 10:32:52 2008 +0000 @@ -28,6 +28,7 @@ extern "C" { #include +#include "gqview.h" #include "exif.h" } @@ -35,36 +36,66 @@ struct _ExifData { Exiv2::Image::AutoPtr image; + Exiv2::Image::AutoPtr sidecar; Exiv2::ExifData::const_iterator exifIter; /* for exif_get_next_item */ Exiv2::IptcData::const_iterator iptcIter; /* for exif_get_next_item */ Exiv2::XmpData::const_iterator xmpIter; /* for exif_get_next_item */ + bool have_sidecar; - _ExifData(gchar *path, gint parse_color_profile) + + _ExifData(gchar *path, gchar *sidecar_path, gint parse_color_profile) { + have_sidecar = false; image = Exiv2::ImageFactory::open(path); // g_assert (image.get() != 0); image->readMetadata(); + + printf("xmp count %d\n", image->xmpData().count()); + if (sidecar_path && image->xmpData().empty()) + { + sidecar = Exiv2::ImageFactory::open(sidecar_path); + sidecar->readMetadata(); + have_sidecar = sidecar->good(); + printf("sidecar xmp count %d\n", sidecar->xmpData().count()); + } + } void writeMetadata() { + if (have_sidecar) sidecar->writeMetadata(); image->writeMetadata(); } + Exiv2::ExifData &exifData () + { + return image->exifData(); + } + + Exiv2::IptcData &iptcData () + { + return image->iptcData(); + } + + Exiv2::XmpData &xmpData () + { + return have_sidecar ? sidecar->xmpData() : image->xmpData(); + } + }; extern "C" { -ExifData *exif_read(gchar *path, gint parse_color_profile) +ExifData *exif_read(gchar *path, gchar *sidecar_path, gint parse_color_profile) { - printf("exif %s\n", path); + printf("exif %s %s\n", path, sidecar_path ? sidecar_path : "-"); try { - return new ExifData(path, parse_color_profile); + return new ExifData(path, sidecar_path, parse_color_profile); } catch (Exiv2::AnyError& e) { std::cout << "Caught Exiv2 exception '" << e << "'\n"; - return 0; + return NULL; } } @@ -95,21 +126,21 @@ Exiv2::Metadatum *item; try { Exiv2::ExifKey ekey(key); - Exiv2::ExifData::iterator pos = exif->image->exifData().findKey(ekey); - if (pos == exif->image->exifData().end()) return NULL; + Exiv2::ExifData::iterator pos = exif->exifData().findKey(ekey); + if (pos == exif->exifData().end()) return NULL; item = &*pos; } catch (Exiv2::AnyError& e) { try { Exiv2::IptcKey ekey(key); - Exiv2::IptcData::iterator pos = exif->image->iptcData().findKey(ekey); - if (pos == exif->image->iptcData().end()) return NULL; + Exiv2::IptcData::iterator pos = exif->iptcData().findKey(ekey); + if (pos == exif->iptcData().end()) return NULL; item = &*pos; } catch (Exiv2::AnyError& e) { Exiv2::XmpKey ekey(key); - Exiv2::XmpData::iterator pos = exif->image->xmpData().findKey(ekey); - if (pos == exif->image->xmpData().end()) return NULL; + Exiv2::XmpData::iterator pos = exif->xmpData().findKey(ekey); + if (pos == exif->xmpData().end()) return NULL; item = &*pos; } } @@ -127,23 +158,23 @@ Exiv2::Metadatum *item; try { Exiv2::ExifKey ekey(key); - exif->image->exifData().add(ekey, NULL); - Exiv2::ExifData::iterator pos = exif->image->exifData().end(); // a hack, there should be a better way to get the currently added item + exif->exifData().add(ekey, NULL); + Exiv2::ExifData::iterator pos = exif->exifData().end(); // a hack, there should be a better way to get the currently added item pos--; item = &*pos; } catch (Exiv2::AnyError& e) { try { Exiv2::IptcKey ekey(key); - exif->image->iptcData().add(ekey, NULL); - Exiv2::IptcData::iterator pos = exif->image->iptcData().end(); + exif->iptcData().add(ekey, NULL); + Exiv2::IptcData::iterator pos = exif->iptcData().end(); pos--; item = &*pos; } catch (Exiv2::AnyError& e) { Exiv2::XmpKey ekey(key); - exif->image->xmpData().add(ekey, NULL); - Exiv2::XmpData::iterator pos = exif->image->xmpData().end(); + exif->xmpData().add(ekey, NULL); + Exiv2::XmpData::iterator pos = exif->xmpData().end(); pos--; item = &*pos; } @@ -160,22 +191,22 @@ ExifItem *exif_get_first_item(ExifData *exif) { try { - exif->exifIter = exif->image->exifData().begin(); - exif->iptcIter = exif->image->iptcData().begin(); - exif->xmpIter = exif->image->xmpData().begin(); - if (exif->exifIter != exif->image->exifData().end()) + exif->exifIter = exif->exifData().begin(); + exif->iptcIter = exif->iptcData().begin(); + exif->xmpIter = exif->xmpData().begin(); + if (exif->exifIter != exif->exifData().end()) { const Exiv2::Metadatum *item = &*exif->exifIter; exif->exifIter++; return (ExifItem *)item; } - if (exif->iptcIter != exif->image->iptcData().end()) + if (exif->iptcIter != exif->iptcData().end()) { const Exiv2::Metadatum *item = &*exif->iptcIter; exif->iptcIter++; return (ExifItem *)item; } - if (exif->xmpIter != exif->image->xmpData().end()) + if (exif->xmpIter != exif->xmpData().end()) { const Exiv2::Metadatum *item = &*exif->xmpIter; exif->xmpIter++; @@ -193,19 +224,19 @@ ExifItem *exif_get_next_item(ExifData *exif) { try { - if (exif->exifIter != exif->image->exifData().end()) + if (exif->exifIter != exif->exifData().end()) { const Exiv2::Metadatum *item = &*exif->exifIter; exif->exifIter++; return (ExifItem *)item; } - if (exif->iptcIter != exif->image->iptcData().end()) + if (exif->iptcIter != exif->iptcData().end()) { const Exiv2::Metadatum *item = &*exif->iptcIter; exif->iptcIter++; return (ExifItem *)item; } - if (exif->xmpIter != exif->image->xmpData().end()) + if (exif->xmpIter != exif->xmpData().end()) { const Exiv2::Metadatum *item = &*exif->xmpIter; exif->xmpIter++; @@ -345,6 +376,26 @@ } } +gchar *exif_item_get_string(ExifItem *item, int idx) +{ + try { + if (!item) return NULL; + Exiv2::Metadatum *em = (Exiv2::Metadatum *)item; + std::string str = em->toString(idx); + if (idx == 0 && str == "") str = em->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); + } + + return g_strdup(str.c_str()); + } + catch (Exiv2::AnyError& e) { + return NULL; + } +} + gint exif_item_get_integer(ExifItem *item, gint *value) { @@ -403,21 +454,21 @@ { try { if (!item) return 0; - for (Exiv2::ExifData::iterator i = exif->image->exifData().begin(); i != exif->image->exifData().end(); ++i) { + for (Exiv2::ExifData::iterator i = exif->exifData().begin(); i != exif->exifData().end(); ++i) { if (((Exiv2::Metadatum *)item) == &*i) { - i = exif->image->exifData().erase(i); + i = exif->exifData().erase(i); return 1; } } - for (Exiv2::IptcData::iterator i = exif->image->iptcData().begin(); i != exif->image->iptcData().end(); ++i) { + for (Exiv2::IptcData::iterator i = exif->iptcData().begin(); i != exif->iptcData().end(); ++i) { if (((Exiv2::Metadatum *)item) == &*i) { - i = exif->image->iptcData().erase(i); + i = exif->iptcData().erase(i); return 1; } } - for (Exiv2::XmpData::iterator i = exif->image->xmpData().begin(); i != exif->image->xmpData().end(); ++i) { + for (Exiv2::XmpData::iterator i = exif->xmpData().begin(); i != exif->xmpData().end(); ++i) { if (((Exiv2::Metadatum *)item) == &*i) { - i = exif->image->xmpData().erase(i); + i = exif->xmpData().erase(i); return 1; } } diff -r 9eafc4957f1a -r 0584cb78aa14 src/filelist.c --- a/src/filelist.c Sat Mar 15 19:53:33 2008 +0000 +++ b/src/filelist.c Sun Mar 16 10:32:52 2008 +0000 @@ -209,6 +209,7 @@ filter_add_if_missing("ico", "Icon file", ".ico;.cur", FALSE); filter_add_if_missing("ras", "Raster", ".ras", FALSE); filter_add_if_missing("svg", "Scalable Vector Graphics", ".svg", FALSE); + filter_add_if_missing("xmp", "XMP sidecar", ".xmp", FALSE); /* These are the raw camera formats with embedded jpeg/exif. * (see format_raw.c) @@ -467,7 +468,7 @@ void sidecar_ext_add_defaults() { - sidecar_ext_parse(".jpg;.cr2;.nef;.crw", FALSE); + sidecar_ext_parse(".jpg;.cr2;.nef;.crw;.xmp", FALSE); } /* diff -r 9eafc4957f1a -r 0584cb78aa14 src/image.c --- a/src/image.c Sat Mar 15 19:53:33 2008 +0000 +++ b/src/image.c Sun Mar 16 10:32:52 2008 +0000 @@ -425,7 +425,7 @@ if (exif_rotate_enable || (imd->color_profile_enable && imd->color_profile_use_image) ) { - exif = exif_read(imd->image_fd->path, (imd->color_profile_enable && imd->color_profile_use_image)); + exif = exif_read_fd(imd->image_fd, (imd->color_profile_enable && imd->color_profile_use_image)); } if (exif_rotate_enable && exif) @@ -624,7 +624,7 @@ { ExifData *exif = NULL; - if (imd->color_profile_use_image) exif = exif_read(imd->image_fd->path, TRUE); + if (imd->color_profile_use_image) exif = exif_read_fd(imd->image_fd, TRUE); image_post_process_color(imd, imd->prev_color_row, exif); exif_free(exif); } diff -r 9eafc4957f1a -r 0584cb78aa14 src/pan-view.c --- a/src/pan-view.c Sat Mar 15 19:53:33 2008 +0000 +++ b/src/pan-view.c Sun Mar 16 10:32:52 2008 +0000 @@ -1434,7 +1434,7 @@ gint i; if (!fd) return; - exif = exif_read(fd->path, FALSE); + exif = exif_read_fd(fd, FALSE); if (!exif) return; pan_text_alignment_add(ta, NULL, NULL); diff -r 9eafc4957f1a -r 0584cb78aa14 src/search.c --- a/src/search.c Sat Mar 15 19:53:33 2008 +0000 +++ b/src/search.c Sun Mar 16 10:32:52 2008 +0000 @@ -1772,7 +1772,7 @@ tested = TRUE; match = FALSE; - if (comment_cache_read(fd, &list, NULL)) + if (comment_read(fd, &list, NULL)) { GList *needle; GList *haystack;