write comment and keywords to xmp, sidecars are used if exist
authorVladimir Nadvornik <nadvornik@suse.cz>
Sun, 16 Mar 2008 10:32:52 +0000 (10:32 +0000)
committerVladimir Nadvornik <nadvornik@suse.cz>
Sun, 16 Mar 2008 10:32:52 +0000 (10:32 +0000)
12 files changed:
src/bar_exif.c
src/bar_info.c
src/bar_info.h
src/cache-loader.c
src/exif-common.c
src/exif.c
src/exif.h
src/exiv2.cc
src/filelist.c
src/image.c
src/pan-view.c
src/search.c

index e02579a..b63d9ee 100644 (file)
@@ -172,7 +172,7 @@ static void bar_exif_update(ExifBar *eb)
        ExifData *exif;
        gint len, i;
 
-       exif = exif_read(eb->fd->path, FALSE);
+       exif = exif_read_fd(eb->fd, FALSE);
 
        if (!exif)
                {
index bc7d0eb..d2a76e2 100644 (file)
@@ -11,6 +11,8 @@
 
 
 #include "gqview.h"
+#include "exif.h"
+
 #include "bar_info.h"
 
 #include "cache.h"
@@ -47,7 +49,7 @@ static void bar_info_keyword_update_all(void);
  *-------------------------------------------------------------------
  */
 
-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 @@ gint comment_write(gchar *path, GList *keywords, const gchar *comment)
        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 @@ gint comment_cache_write(FileData *fd, GList *keywords, const gchar *comment)
 
                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 @@ gint comment_cache_write(FileData *fd, GList *keywords, const gchar *comment)
        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 @@ gint comment_read(gchar *path, GList **keywords, gchar **comment)
        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 @@ gint comment_cache_read(FileData *fd, GList **keywords, gchar **comment)
 
        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 @@ gint comment_cache_read(FileData *fd, GList **keywords, gchar **comment)
        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 @@ static void metadata_set_keywords(FileData *fd, GList *list, gint add)
        GList *keywords = NULL;
        GList *save_list = NULL;
 
-       comment_cache_read(fd, &keywords, &comment);
+       comment_read(fd, &keywords, &comment);
 
        if (add)
                {
@@ -323,7 +419,7 @@ static void metadata_set_keywords(FileData *fd, GList *list, gint add)
                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 @@ static void bar_info_write(BarInfoData *bd)
        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 @@ 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) : "");
                }
 
-       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)),
index 21ddb1f..03721ab 100644 (file)
@@ -27,11 +27,9 @@ void bar_info_size_request(GtkWidget *bar, gint width);
 
 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);
index d0487c3..21290c0 100644 (file)
@@ -125,7 +125,7 @@ static gboolean cache_loader_process(CacheLoader *cl)
                time_t date = -1;
                ExifData *exif;
 
-               exif = exif_read(cl->fd->path, FALSE);
+               exif = exif_read_fd(cl->fd, FALSE);
                if (exif)
                        {
                        gchar *text;
index dcc61f9..15cd2ab 100644 (file)
@@ -326,3 +326,25 @@ gchar *exif_get_data_as_text(ExifData *exif, const gchar *key)
 
        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);
+}
index 957466b..fe151af 100644 (file)
@@ -1220,7 +1220,7 @@ void exif_free(ExifData *exif)
        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;
index 34685c3..b770c8d 100644 (file)
@@ -105,7 +105,11 @@ typedef enum {
  *-----------------------------------------------------------------------------
  */
 
-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 @@ gchar *exif_item_get_data_as_text(ExifItem *item);
 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);
 
index 406e6f3..4fbafb9 100644 (file)
@@ -28,6 +28,7 @@
 
 extern "C" {
 #include <glib.h> 
+#include "gqview.h"
 #include "exif.h"
 
 }
@@ -35,36 +36,66 @@ extern "C" {
 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 @@ ExifItem *exif_get_item(ExifData *exif, const gchar *key)
                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 @@ ExifItem *exif_add_item(ExifData *exif, const gchar *key)
                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_add_item(ExifData *exif, const gchar *key)
 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_first_item(ExifData *exif)
 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_data_as_text(ExifItem *item)
        }
 }
 
+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 @@ int exif_item_delete(ExifData *exif, ExifItem *item)
 {
        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;
                        }
                }
index c6dbb56..563a979 100644 (file)
@@ -209,6 +209,7 @@ void filter_add_defaults(void)
        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 @@ char *sidecar_ext_to_string()
 
 void sidecar_ext_add_defaults()
 {
-       sidecar_ext_parse(".jpg;.cr2;.nef;.crw", FALSE);
+       sidecar_ext_parse(".jpg;.cr2;.nef;.crw;.xmp", FALSE);
 }
 
 /*
index 7b0c3e6..b851d80 100644 (file)
@@ -425,7 +425,7 @@ static void image_post_process(ImageWindow *imd, gint clamp)
        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 @@ static gint image_post_buffer_get(ImageWindow *imd)
                        {
                        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);
                        }
index 85f54d5..a6d2f89 100644 (file)
@@ -1434,7 +1434,7 @@ static void pan_info_add_exif(PanTextAlignment *ta, FileData *fd)
        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);
index a7a049a..25ba5be 100644 (file)
@@ -1772,7 +1772,7 @@ static gint search_file_next(SearchData *sd)
                tested = TRUE;
                match = FALSE;
 
-               if (comment_cache_read(fd, &list, NULL))
+               if (comment_read(fd, &list, NULL))
                        {
                        GList *needle;
                        GList *haystack;