[gimp] Revert "New GimpMetadata as subclass of GExiv2Metadata"



commit 66bc98d29909a3c63ada76e92fa6c6b7de487f16
Author: Hartmut Kuhse <hk_priv gmx de>
Date:   Tue Jan 3 19:36:22 2017 +0100

    Revert "New GimpMetadata as subclass of GExiv2Metadata"
    
    This reverts commit 3ab08c8bfddb03ec4fc9a994084198228fb4f951.

 app/core/core-enums.c                              |    6 +-
 app/core/core-enums.h                              |    3 +-
 app/core/core-types.h                              |    1 -
 app/core/gimp.c                                    |    2 -
 app/core/gimpimage-merge.c                         |   23 +-
 app/core/gimpimage-undo-push.c                     |   16 -
 app/core/gimpimage-undo-push.h                     |    4 +-
 app/core/gimpitem.c                                |   40 -
 app/core/gimpitem.h                                |    4 -
 app/core/gimpitemundo.c                            |   74 +-
 app/core/gimpitemundo.h                            |    2 -
 app/core/gimplayer.c                               |   12 +-
 app/pdb/internal-procs.c                           |    2 +-
 app/pdb/item-cmds.c                                |  121 -
 app/xcf/xcf-load.c                                 |  142 +-
 app/xcf/xcf-save.c                                 |   72 +-
 configure.ac                                       |    2 +-
 icons/Color/16/gimp-image-metadata.png             |  Bin 569 -> 0 bytes
 icons/Color/24/gimp-image-metadata.png             |  Bin 850 -> 0 bytes
 icons/Color/24/gimp-image-metadata.svg             |  275 --
 icons/Color/48/gimp-image-metadata.png             |  Bin 1903 -> 0 bytes
 icons/Color/scalable/gimp-image-metadata.svg       |  268 --
 icons/Legacy/16/gimp-image-metadata.png            |  Bin 569 -> 0 bytes
 icons/Legacy/24/gimp-image-metadata.png            |  Bin 850 -> 0 bytes
 icons/Legacy/48/gimp-image-metadata.png            |  Bin 1903 -> 0 bytes
 icons/Symbolic-Inverted/24/gimp-image-metadata.svg |  189 --
 icons/Symbolic/16/gimp-image-metadata.png          |  Bin 461 -> 0 bytes
 icons/Symbolic/24/gimp-image-metadata.png          |  Bin 739 -> 0 bytes
 icons/Symbolic/24/gimp-image-metadata.svg          |  189 --
 icons/Symbolic/48/gimp-image-metadata.png          |  Bin 1367 -> 0 bytes
 icons/Symbolic/64/gimp-image-metadata.png          |  Bin 1853 -> 0 bytes
 icons/Symbolic/scalable/gimp-image-metadata.svg    |  189 --
 icons/icon-list.mk                                 |    5 -
 libgimp/Makefile.am                                |    3 -
 libgimp/gimp.def                                   |    2 -
 libgimp/gimp.h                                     |    1 -
 libgimp/gimpimagemetadata.c                        |  420 ++--
 libgimp/gimpimagemetadata.h                        |    1 -
 libgimp/gimpitem.c                                 |   86 -
 libgimp/gimpitem.h                                 |   40 -
 libgimp/gimpitem_pdb.c                             |   62 -
 libgimp/gimpitem_pdb.h                             |   89 +-
 libgimpbase/Makefile.am                            |    6 -
 libgimpbase/gimpattribute.c                        | 2002 ------------
 libgimpbase/gimpattribute.h                        |   97 -
 libgimpbase/gimpbase.def                           |   42 +-
 libgimpbase/gimpbase.h                             |    1 -
 libgimpbase/gimpbasetypes.h                        |    3 +-
 libgimpbase/gimpmetadata.c                         | 3330 ++++----------------
 libgimpbase/gimpmetadata.h                         |  144 +-
 libgimpbase/gimprational.c                         |  301 --
 libgimpbase/gimprational.h                         |   68 -
 libgimpwidgets/gimpicons.c                         |    1 -
 libgimpwidgets/gimpicons.h                         |    1 -
 plug-ins/common/Makefile.am                        |   59 +-
 plug-ins/common/file-jp2-load.c                    |    8 +-
 plug-ins/common/file-png.c                         |   23 +-
 plug-ins/common/gimprc.common                      |    3 +-
 plug-ins/common/plugin-defs.pl                     |    3 +-
 plug-ins/file-jpeg/jpeg-load.c                     |   13 +-
 plug-ins/file-jpeg/jpeg-load.h                     |    1 -
 plug-ins/file-jpeg/jpeg-save.c                     |    3 +-
 plug-ins/file-jpeg/jpeg.c                          |    8 +-
 plug-ins/file-psd/psd.c                            |    6 +-
 plug-ins/file-tiff/file-tiff-load.c                |    3 -
 plug-ins/file-tiff/file-tiff-load.h                |    1 -
 plug-ins/file-tiff/file-tiff.c                     |   18 +-
 plug-ins/ui/Makefile.am                            |    4 +-
 plug-ins/ui/plug-in-metadata.ui                    |  908 ++++++
 po-plug-ins/POTFILES.in                            |   10 +-
 tools/pdbgen/pdb/item.pdb                          |   78 +-
 71 files changed, 1924 insertions(+), 7566 deletions(-)
---
diff --git a/app/core/core-enums.c b/app/core/core-enums.c
index ac60a05..cbdcf44 100644
--- a/app/core/core-enums.c
+++ b/app/core/core-enums.c
@@ -853,15 +853,14 @@ gimp_undo_type_get_type (void)
     { GIMP_UNDO_IMAGE_SIZE, "GIMP_UNDO_IMAGE_SIZE", "image-size" },
     { GIMP_UNDO_IMAGE_RESOLUTION, "GIMP_UNDO_IMAGE_RESOLUTION", "image-resolution" },
     { GIMP_UNDO_IMAGE_GRID, "GIMP_UNDO_IMAGE_GRID", "image-grid" },
+    { GIMP_UNDO_IMAGE_METADATA, "GIMP_UNDO_IMAGE_METADATA", "image-metadata" },
     { GIMP_UNDO_IMAGE_COLORMAP, "GIMP_UNDO_IMAGE_COLORMAP", "image-colormap" },
     { GIMP_UNDO_IMAGE_COLOR_MANAGED, "GIMP_UNDO_IMAGE_COLOR_MANAGED", "image-color-managed" },
-    { GIMP_UNDO_IMAGE_METADATA, "GIMP_UNDO_IMAGE_METADATA", "image-metadata" },
     { GIMP_UNDO_GUIDE, "GIMP_UNDO_GUIDE", "guide" },
     { GIMP_UNDO_SAMPLE_POINT, "GIMP_UNDO_SAMPLE_POINT", "sample-point" },
     { GIMP_UNDO_DRAWABLE, "GIMP_UNDO_DRAWABLE", "drawable" },
     { GIMP_UNDO_DRAWABLE_MOD, "GIMP_UNDO_DRAWABLE_MOD", "drawable-mod" },
     { GIMP_UNDO_MASK, "GIMP_UNDO_MASK", "mask" },
-    { GIMP_UNDO_ITEM_METADATA, "GIMP_UNDO_ITEM_METADATA", "item-metadata" },
     { GIMP_UNDO_ITEM_REORDER, "GIMP_UNDO_ITEM_REORDER", "item-reorder" },
     { GIMP_UNDO_ITEM_RENAME, "GIMP_UNDO_ITEM_RENAME", "item-rename" },
     { GIMP_UNDO_ITEM_DISPLACE, "GIMP_UNDO_ITEM_DISPLACE", "item-displace" },
@@ -947,15 +946,14 @@ gimp_undo_type_get_type (void)
     { GIMP_UNDO_IMAGE_SIZE, NC_("undo-type", "Image size"), NULL },
     { GIMP_UNDO_IMAGE_RESOLUTION, NC_("undo-type", "Image resolution change"), NULL },
     { GIMP_UNDO_IMAGE_GRID, NC_("undo-type", "Grid"), NULL },
+    { GIMP_UNDO_IMAGE_METADATA, NC_("undo-type", "Change metadata"), NULL },
     { GIMP_UNDO_IMAGE_COLORMAP, NC_("undo-type", "Change indexed palette"), NULL },
     { GIMP_UNDO_IMAGE_COLOR_MANAGED, NC_("undo-type", "Change color managed state"), NULL },
-    { GIMP_UNDO_IMAGE_METADATA, "GIMP_UNDO_IMAGE_METADATA", NULL },
     { GIMP_UNDO_GUIDE, NC_("undo-type", "Guide"), NULL },
     { GIMP_UNDO_SAMPLE_POINT, NC_("undo-type", "Sample Point"), NULL },
     { GIMP_UNDO_DRAWABLE, NC_("undo-type", "Layer/Channel"), NULL },
     { GIMP_UNDO_DRAWABLE_MOD, NC_("undo-type", "Layer/Channel modification"), NULL },
     { GIMP_UNDO_MASK, NC_("undo-type", "Selection mask"), NULL },
-    { GIMP_UNDO_ITEM_METADATA, "GIMP_UNDO_ITEM_METADATA", NULL },
     { GIMP_UNDO_ITEM_REORDER, NC_("undo-type", "Reorder item"), NULL },
     { GIMP_UNDO_ITEM_RENAME, NC_("undo-type", "Rename item"), NULL },
     { GIMP_UNDO_ITEM_DISPLACE, NC_("undo-type", "Move item"), NULL },
diff --git a/app/core/core-enums.h b/app/core/core-enums.h
index 5b7e922..95616e6 100644
--- a/app/core/core-enums.h
+++ b/app/core/core-enums.h
@@ -425,15 +425,14 @@ typedef enum /*< pdb-skip >*/
   GIMP_UNDO_IMAGE_SIZE,               /*< desc="Image size"                  >*/
   GIMP_UNDO_IMAGE_RESOLUTION,         /*< desc="Image resolution change"     >*/
   GIMP_UNDO_IMAGE_GRID,               /*< desc="Grid"                        >*/
+  GIMP_UNDO_IMAGE_METADATA,           /*< desc="Change metadata"             >*/
   GIMP_UNDO_IMAGE_COLORMAP,           /*< desc="Change indexed palette"      >*/
   GIMP_UNDO_IMAGE_COLOR_MANAGED,      /*< desc="Change color managed state"  >*/
-  GIMP_UNDO_IMAGE_METADATA,           /*< desc="Change metadata              >*/
   GIMP_UNDO_GUIDE,                    /*< desc="Guide"                       >*/
   GIMP_UNDO_SAMPLE_POINT,             /*< desc="Sample Point"                >*/
   GIMP_UNDO_DRAWABLE,                 /*< desc="Layer/Channel"               >*/
   GIMP_UNDO_DRAWABLE_MOD,             /*< desc="Layer/Channel modification"  >*/
   GIMP_UNDO_MASK,                     /*< desc="Selection mask"              >*/
-  GIMP_UNDO_ITEM_METADATA,            /*< desc="Change metadata              >*/
   GIMP_UNDO_ITEM_REORDER,             /*< desc="Reorder item"                >*/
   GIMP_UNDO_ITEM_RENAME,              /*< desc="Rename item"                 >*/
   GIMP_UNDO_ITEM_DISPLACE,            /*< desc="Move item"                   >*/
diff --git a/app/core/core-types.h b/app/core/core-types.h
index 57921bb..11eaa62 100644
--- a/app/core/core-types.h
+++ b/app/core/core-types.h
@@ -157,7 +157,6 @@ typedef struct _GimpGroupLayer      GimpGroupLayer;
 typedef struct _GimpUndo            GimpUndo;
 typedef struct _GimpUndoStack       GimpUndoStack;
 typedef struct _GimpUndoAccumulator GimpUndoAccumulator;
-typedef struct _GimpViewableUndo      GimpViewableUndo;
 
 
 /* Symmetry transformations */
diff --git a/app/core/gimp.c b/app/core/gimp.c
index ff02bbd..25ee206 100644
--- a/app/core/gimp.c
+++ b/app/core/gimp.c
@@ -38,8 +38,6 @@
 #include "plug-in/gimppluginmanager.h"
 #include "plug-in/gimppluginmanager-restore.h"
 
-#include "gui/gimpdbusservice-generated.h"
-
 #include "paint/gimp-paint.h"
 
 #include "text/gimp-fonts.h"
diff --git a/app/core/gimpimage-merge.c b/app/core/gimpimage-merge.c
index 5e1e362..3d97d13 100644
--- a/app/core/gimpimage-merge.c
+++ b/app/core/gimpimage-merge.c
@@ -40,9 +40,7 @@
 #include "gimpgrouplayer.h"
 #include "gimpimage.h"
 #include "gimpimage-merge.h"
-#include "gimpimage-metadata.h"
 #include "gimpimage-undo.h"
-#include "gimpitem.h"
 #include "gimpitemstack.h"
 #include "gimplayer-floating-selection.h"
 #include "gimplayer-new.h"
@@ -430,7 +428,6 @@ gimp_image_merge_layers (GimpImage     *image,
   GimpLayer        *layer;
   GimpLayer        *bottom_layer;
   GimpParasiteList *parasites;
-  GimpMetadata     *metadata;
   gint              count;
   gint              x1, y1, x2, y2;
   gint              off_x, off_y;
@@ -525,8 +522,8 @@ gimp_image_merge_layers (GimpImage     *image,
       (gimp_drawable_is_indexed (GIMP_DRAWABLE (layer)) &&
        ! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer))))
     {
-      GeglColor      *color;
-      GimpRGB         bg;
+      GeglColor *color;
+      GimpRGB    bg;
 
       merge_layer = gimp_layer_new (image, (x2 - x1), (y2 - y1),
                                     gimp_image_get_layer_format (image, FALSE),
@@ -588,22 +585,6 @@ gimp_image_merge_layers (GimpImage     *image,
 
   bottom_layer = layer;
 
-  /* Copy the metadata of the bottom layer to the new layer */
-
-  metadata = gimp_item_get_metadata (GIMP_ITEM (bottom_layer));
-
-  if (!metadata)
-    metadata = gimp_image_get_metadata (image);
-
-  if (metadata)
-    {
-      GimpMetadata *new_metadata;
-
-      new_metadata = gimp_metadata_duplicate (metadata);
-      gimp_item_set_metadata (GIMP_ITEM (merge_layer), new_metadata, TRUE);
-      g_object_unref (new_metadata);
-    }
-
   /* Copy the tattoo and parasites of the bottom layer to the new layer */
   gimp_item_set_tattoo (GIMP_ITEM (merge_layer),
                         gimp_item_get_tattoo (GIMP_ITEM (bottom_layer)));
diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c
index c3b05e2..670cc42 100644
--- a/app/core/gimpimage-undo-push.c
+++ b/app/core/gimpimage-undo-push.c
@@ -49,7 +49,6 @@
 #include "gimpsamplepoint.h"
 #include "gimpsamplepointundo.h"
 #include "gimpselection.h"
-#include "gimpviewable.h"
 
 #include "text/gimptextlayer.h"
 #include "text/gimptextundo.h"
@@ -173,21 +172,6 @@ gimp_image_undo_push_image_metadata (GimpImage   *image,
                                NULL);
 }
 
-
-GimpUndo *
-gimp_image_undo_push_item_metadata (GimpImage    *image,
-                                      const gchar  *undo_desc,
-                                      GimpItem     *item)
-{
-  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
-
-  return gimp_image_undo_push (image, GIMP_TYPE_ITEM_UNDO,
-                               GIMP_UNDO_ITEM_METADATA, undo_desc,
-                               GIMP_DIRTY_IMAGE_META,
-                               "item", item,
-                               NULL);
-}
-
 GimpUndo *
 gimp_image_undo_push_image_parasite (GimpImage          *image,
                                      const gchar        *undo_desc,
diff --git a/app/core/gimpimage-undo-push.h b/app/core/gimpimage-undo-push.h
index 592954b..57bc970 100644
--- a/app/core/gimpimage-undo-push.h
+++ b/app/core/gimpimage-undo-push.h
@@ -118,9 +118,6 @@ GimpUndo * gimp_image_undo_push_item_parasite_remove(GimpImage     *image,
                                                      const gchar   *undo_desc,
                                                      GimpItem      *item,
                                                      const gchar   *name);
-GimpUndo * gimp_image_undo_push_item_metadata       (GimpImage     *image,
-                                                     const gchar   *undo_desc,
-                                                     GimpItem      *item);
 
 
 /*  layer undos  */
@@ -237,4 +234,5 @@ GimpUndo * gimp_image_undo_push_fs_to_layer         (GimpImage     *image,
 GimpUndo * gimp_image_undo_push_cantundo            (GimpImage     *image,
                                                      const gchar   *undo_desc);
 
+
 #endif  /* __GIMP_IMAGE_UNDO_PUSH_H__ */
diff --git a/app/core/gimpitem.c b/app/core/gimpitem.c
index 9167319..ab36f52 100644
--- a/app/core/gimpitem.c
+++ b/app/core/gimpitem.c
@@ -99,7 +99,6 @@ struct _GimpItemPrivate
   GimpColorTag      color_tag;          /*  color tag                */
 
   GList            *offset_nodes;       /*  offset nodes to manage   */
-  GimpMetadata     *metadata            /*  items metadata           */
 };
 
 #define GET_PRIVATE(item) G_TYPE_INSTANCE_GET_PRIVATE (item, \
@@ -332,7 +331,6 @@ gimp_item_init (GimpItem *item)
   g_object_force_floating (G_OBJECT (item));
 
   private->parasites = gimp_parasite_list_new ();
-  private->metadata = NULL;
 }
 
 static void
@@ -2422,41 +2420,3 @@ gimp_item_is_in_set (GimpItem    *item,
 
   return FALSE;
 }
-
-void
-gimp_item_set_metadata (GimpItem     *item,
-                        GimpMetadata *metadata,
-                        gboolean      push_undo)
-{
-  GimpItemPrivate *private;
-
-  g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
-
-  private = GET_PRIVATE (item);
-
-  if (metadata != private->metadata)
-    {
-      if (push_undo)
-        gimp_image_undo_push_item_metadata (gimp_item_get_image (item),
-                                            NULL,
-                                            item);
-
-      if (private->metadata)
-        g_object_unref (private->metadata);
-
-      private->metadata = metadata;
-      g_object_ref (private->metadata);
-    }
-}
-
-GimpMetadata *
-gimp_item_get_metadata (GimpItem *item)
-{
-  GimpItemPrivate *private;
-
-  g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
-
-  private = GET_PRIVATE (item);
-
-  return private->metadata;
-}
diff --git a/app/core/gimpitem.h b/app/core/gimpitem.h
index 2be3b75..da431e1 100644
--- a/app/core/gimpitem.h
+++ b/app/core/gimpitem.h
@@ -364,9 +364,5 @@ gboolean        gimp_item_mask_intersect     (GimpItem           *item,
 gboolean        gimp_item_is_in_set          (GimpItem           *item,
                                               GimpItemSet         set);
 
-void            gimp_item_set_metadata       (GimpItem           *item,
-                                              GimpMetadata       *metadata,
-                                              gboolean            push_undo);
-GimpMetadata  * gimp_item_get_metadata       (GimpItem           *item);
 
 #endif /* __GIMP_ITEM_H__ */
diff --git a/app/core/gimpitemundo.c b/app/core/gimpitemundo.c
index 529f310..34c9539 100644
--- a/app/core/gimpitemundo.c
+++ b/app/core/gimpitemundo.c
@@ -22,8 +22,6 @@
 
 #include "core-types.h"
 
-#include "libgimpbase/gimpbase.h"
-
 #include "gimpimage.h"
 #include "gimpitem.h"
 #include "gimpitemundo.h"
@@ -36,21 +34,18 @@ enum
 };
 
 
-static void   gimp_item_undo_constructed  (GObject             *object);
-static void   gimp_item_undo_set_property (GObject             *object,
-                                           guint                property_id,
-                                           const GValue        *value,
-                                           GParamSpec          *pspec);
-static void   gimp_item_undo_get_property (GObject             *object,
-                                           guint                property_id,
-                                           GValue              *value,
-                                           GParamSpec          *pspec);
+static void   gimp_item_undo_constructed  (GObject      *object);
+static void   gimp_item_undo_set_property (GObject      *object,
+                                           guint         property_id,
+                                           const GValue *value,
+                                           GParamSpec   *pspec);
+static void   gimp_item_undo_get_property (GObject      *object,
+                                           guint         property_id,
+                                           GValue       *value,
+                                           GParamSpec   *pspec);
 
-static void   gimp_item_undo_free         (GimpUndo            *undo,
-                                           GimpUndoMode         undo_mode);
-static void   gimp_item_undo_pop          (GimpUndo            *undo,
-                                           GimpUndoMode         undo_mode,
-                                           GimpUndoAccumulator *accum);
+static void   gimp_item_undo_free         (GimpUndo     *undo,
+                                           GimpUndoMode  undo_mode);
 
 
 G_DEFINE_TYPE (GimpItemUndo, gimp_item_undo, GIMP_TYPE_UNDO)
@@ -68,7 +63,6 @@ gimp_item_undo_class_init (GimpItemUndoClass *klass)
   object_class->set_property = gimp_item_undo_set_property;
   object_class->get_property = gimp_item_undo_get_property;
 
-  undo_class->pop            = gimp_item_undo_pop;
   undo_class->free           = gimp_item_undo_free;
 
   g_object_class_install_property (object_class, PROP_ITEM,
@@ -90,14 +84,7 @@ gimp_item_undo_constructed (GObject *object)
 
   G_OBJECT_CLASS (parent_class)->constructed (object);
 
-  switch (GIMP_UNDO (object)->undo_type)
-  {
-    case GIMP_UNDO_ITEM_METADATA:
-      item_undo->metadata =
-          gimp_metadata_duplicate (gimp_item_get_metadata (item_undo->item));
-      break;
-  }
-
+  g_assert (GIMP_IS_ITEM (item_undo->item));
 }
 
 static void
@@ -152,42 +139,5 @@ gimp_item_undo_free (GimpUndo     *undo,
       item_undo->item = NULL;
     }
 
-  if (item_undo->metadata)
-    {
-      g_object_unref (item_undo->metadata);
-      item_undo->metadata = NULL;
-    }
-
   GIMP_UNDO_CLASS (parent_class)->free (undo, undo_mode);
 }
-
-static void
-gimp_item_undo_pop     (GimpUndo            *undo,
-                        GimpUndoMode         undo_mode,
-                        GimpUndoAccumulator *accum)
-{
-  GimpItemUndo   *item_undo  = GIMP_ITEM_UNDO (undo);
-  GimpItem       *item       = GIMP_ITEM_UNDO (undo)->item;
-
-  switch (undo->undo_type)
-    {
-    case GIMP_UNDO_ITEM_METADATA:
-      {
-        GimpMetadata *metadata;
-
-        metadata = gimp_metadata_duplicate (gimp_item_get_metadata (item));
-
-        gimp_item_set_metadata (item, item_undo->metadata, FALSE);
-
-        if (item_undo->metadata)
-          g_object_unref (item_undo->metadata);
-        item_undo->metadata = metadata;
-      }
-      break;
-
-    default:
-//      g_assert_not_reached ();
-      break;
-
-    }
-}
diff --git a/app/core/gimpitemundo.h b/app/core/gimpitemundo.h
index 31e504a..1b95592 100644
--- a/app/core/gimpitemundo.h
+++ b/app/core/gimpitemundo.h
@@ -38,8 +38,6 @@ struct _GimpItemUndo
   GimpUndo  parent_instance;
 
   GimpItem *item;  /* the item this undo is for */
-  GimpMetadata    *metadata;
-
 };
 
 struct _GimpItemUndoClass
diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c
index d8a3eb5..d8284b8 100644
--- a/app/core/gimplayer.c
+++ b/app/core/gimplayer.c
@@ -743,9 +743,7 @@ static GimpItem *
 gimp_layer_duplicate (GimpItem *item,
                       GType     new_type)
 {
-  GimpItem       *new_item;
-  GimpMetadata   *metadata;
-  GimpMetadata   *new_metadata;
+  GimpItem *new_item;
 
   g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_DRAWABLE), NULL);
 
@@ -776,14 +774,6 @@ gimp_layer_duplicate (GimpItem *item,
           new_layer->edit_mask  = layer->edit_mask;
           new_layer->show_mask  = layer->show_mask;
         }
-
-      metadata = gimp_item_get_metadata (item);
-      if (metadata)
-        {
-          new_metadata = gimp_metadata_duplicate (metadata);
-          gimp_item_set_metadata (new_item, new_metadata, FALSE);
-          g_object_unref (new_metadata);
-        }
     }
 
   return new_item;
diff --git a/app/pdb/internal-procs.c b/app/pdb/internal-procs.c
index ff75522..5379699 100644
--- a/app/pdb/internal-procs.c
+++ b/app/pdb/internal-procs.c
@@ -28,7 +28,7 @@
 #include "internal-procs.h"
 
 
-/* 804 procedures registered total */
+/* 802 procedures registered total */
 
 void
 internal_procs_init (GimpPDB *pdb)
diff --git a/app/pdb/item-cmds.c b/app/pdb/item-cmds.c
index 0ba96b8..2a19e25 100644
--- a/app/pdb/item-cmds.c
+++ b/app/pdb/item-cmds.c
@@ -822,67 +822,6 @@ item_set_tattoo_invoker (GimpProcedure         *procedure,
 }
 
 static GimpValueArray *
-item_get_metadata_invoker (GimpProcedure         *procedure,
-                             Gimp                  *gimp,
-                             GimpContext           *context,
-                             GimpProgress          *progress,
-                             const GimpValueArray  *args,
-                             GError               **error)
-{
-  gboolean success = TRUE;
-  GimpValueArray *return_vals;
-  GimpItem *item;
-  gchar *metadata_string = NULL;
-
-  item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
-
-  if (success)
-    {
-      GimpMetadata *metadata = gimp_item_get_metadata (item);
-
-      if (metadata)
-        metadata_string = gimp_metadata_serialize (metadata);
-    }
-
-  return_vals = gimp_procedure_get_return_values (procedure, success,
-                                                  error ? *error : NULL);
-
-  if (success)
-    g_value_take_string (gimp_value_array_index (return_vals, 1), metadata_string);
-
-  return return_vals;
-}
-
-static GimpValueArray *
-item_set_metadata_invoker (GimpProcedure         *procedure,
-                             Gimp                  *gimp,
-                             GimpContext           *context,
-                             GimpProgress          *progress,
-                             const GimpValueArray  *args,
-                             GError               **error)
-{
-  gboolean success = TRUE;
-  GimpItem *item;
-  const gchar *metadata_string;
-
-  item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
-  metadata_string = g_value_get_string (gimp_value_array_index (args, 1));
-
-  if (success)
-    {
-      GimpMetadata *metadata = gimp_metadata_deserialize (metadata_string);
-
-      gimp_item_set_metadata (item, metadata, TRUE);
-
-      if (metadata)
-        g_object_unref (metadata);
-    }
-
-  return gimp_procedure_get_return_values (procedure, success,
-                                           error ? *error : NULL);
-}
-
-static GimpValueArray *
 item_attach_parasite_invoker (GimpProcedure         *procedure,
                               Gimp                  *gimp,
                               GimpContext           *context,
@@ -1792,66 +1731,6 @@ register_item_procs (GimpPDB *pdb)
   g_object_unref (procedure);
 
   /*
-   * gimp-item-get-metadata
-   */
-  procedure = gimp_procedure_new (item_get_metadata_invoker);
-  gimp_object_set_static_name (GIMP_OBJECT (procedure),
-                               "gimp-item-get-metadata");
-  gimp_procedure_set_static_strings (procedure,
-                                     "gimp-item-get-metadata",
-                                     "Returns the item's metadata.",
-                                     "Returns metadata from the item.",
-                                     "Spencer Kimball & Peter Mattis",
-                                     "Spencer Kimball & Peter Mattis",
-                                     "1995-1996",
-                                     NULL);
-  gimp_procedure_add_argument (procedure,
-                               gimp_param_spec_item_id ("item",
-                                                        "item",
-                                                        "The item",
-                                                        pdb->gimp, FALSE,
-                                                        GIMP_PARAM_READWRITE));
-  gimp_procedure_add_return_value (procedure,
-                                   gimp_param_spec_string ("metadata-string",
-                                                           "metadata string",
-                                                           "The metadata as a xml string",
-                                                           FALSE, FALSE, FALSE,
-                                                           NULL,
-                                                           GIMP_PARAM_READWRITE));
-  gimp_pdb_register_procedure (pdb, procedure);
-  g_object_unref (procedure);
-
-  /*
-   * gimp-item-set-metadata
-   */
-  procedure = gimp_procedure_new (item_set_metadata_invoker);
-  gimp_object_set_static_name (GIMP_OBJECT (procedure),
-                               "gimp-item-set-metadata");
-  gimp_procedure_set_static_strings (procedure,
-                                     "gimp-item-set-metadata",
-                                     "Set the item's metadata.",
-                                     "Sets metadata on the item.",
-                                     "Spencer Kimball & Peter Mattis",
-                                     "Spencer Kimball & Peter Mattis",
-                                     "1995-1996",
-                                     NULL);
-  gimp_procedure_add_argument (procedure,
-                               gimp_param_spec_item_id ("item",
-                                                        "item",
-                                                        "The item",
-                                                        pdb->gimp, FALSE,
-                                                        GIMP_PARAM_READWRITE));
-  gimp_procedure_add_argument (procedure,
-                               gimp_param_spec_string ("metadata-string",
-                                                       "metadata string",
-                                                       "The metadata as a xml string",
-                                                       FALSE, FALSE, FALSE,
-                                                       NULL,
-                                                       GIMP_PARAM_READWRITE));
-  gimp_pdb_register_procedure (pdb, procedure);
-  g_object_unref (procedure);
-
-  /*
    * gimp-item-attach-parasite
    */
   procedure = gimp_procedure_new (item_attach_parasite_invoker);
diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c
index cf8128f..5be2a71 100644
--- a/app/xcf/xcf-load.c
+++ b/app/xcf/xcf-load.c
@@ -48,7 +48,6 @@
 #include "core/gimpimage-undo.h"
 #include "core/gimpitemstack.h"
 #include "core/gimplayer-floating-selection.h"
-#include "core/gimpitem.h"
 #include "core/gimplayer-new.h"
 #include "core/gimplayermask.h"
 #include "core/gimpparasitelist.h"
@@ -269,31 +268,6 @@ xcf_load_image (Gimp     *gimp,
       gimp_parasite_list_remove (private->parasites,
                                  gimp_parasite_name (parasite));
     }
-  else
-    {
-
-      /* check for an attributes parasite */
-      parasite = gimp_image_parasite_find (GIMP_IMAGE (image),
-                                           "gimp-image-attributes");
-      if (parasite)
-        {
-          GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
-          GimpMetadata     *metadata;
-          const gchar      *attributes_string;
-
-          attributes_string = (gchar *) gimp_parasite_data (parasite);
-          metadata = gimp_metadata_deserialize (attributes_string);
-
-          if (metadata)
-            {
-              gimp_image_set_metadata (image, metadata, FALSE);
-              g_object_unref (metadata);
-            }
-
-          gimp_parasite_list_remove (private->parasites,
-                                     gimp_parasite_name (parasite));
-        }
-    }
 
   /* migrate the old "exif-data" parasite */
   parasite = gimp_image_parasite_find (GIMP_IMAGE (image),
@@ -310,10 +284,13 @@ xcf_load_image (Gimp     *gimp,
         }
       else
         {
-          GimpMetadata   *metadata = NULL;
-          GError         *my_error = NULL;
+          GimpMetadata *metadata = gimp_image_get_metadata (image);
+          GError       *my_error = NULL;
 
-          metadata = gimp_metadata_new ();
+          if (metadata)
+            g_object_ref (metadata);
+          else
+            metadata = gimp_metadata_new ();
 
           if (! gimp_metadata_set_from_exif (metadata,
                                              gimp_parasite_data (parasite),
@@ -364,10 +341,13 @@ xcf_load_image (Gimp     *gimp,
         }
       else
         {
-          GimpMetadata   *metadata = NULL;
-          GError         *my_error = NULL;
+          GimpMetadata *metadata = gimp_image_get_metadata (image);
+          GError       *my_error = NULL;
 
-          metadata = gimp_metadata_new ();
+          if (metadata)
+            g_object_ref (metadata);
+          else
+            metadata = gimp_metadata_new ();
 
           if (! gimp_metadata_set_from_xmp (metadata,
                                             (const guint8 *) xmp_data + 10,
@@ -1463,26 +1443,25 @@ xcf_load_layer (XcfInfo    *info,
                 GimpImage  *image,
                 GList     **item_path)
 {
-  GimpLayer          *layer;
-  GimpLayerMask      *layer_mask;
-  const GimpParasite *parasite;
-  guint32             hierarchy_offset;
-  guint32             layer_mask_offset;
-  gboolean            apply_mask = TRUE;
-  gboolean            edit_mask  = FALSE;
-  gboolean            show_mask  = FALSE;
-  gboolean            active;
-  gboolean            floating;
-  guint32             group_layer_flags = 0;
-  guint32             text_layer_flags = 0;
-  gint                width;
-  gint                height;
-  gint                type;
-  GimpImageBaseType   base_type;
-  gboolean            has_alpha;
-  const Babl         *format;
-  gboolean            is_fs_drawable;
-  gchar              *name;
+  GimpLayer         *layer;
+  GimpLayerMask     *layer_mask;
+  guint32            hierarchy_offset;
+  guint32            layer_mask_offset;
+  gboolean           apply_mask = TRUE;
+  gboolean           edit_mask  = FALSE;
+  gboolean           show_mask  = FALSE;
+  gboolean           active;
+  gboolean           floating;
+  guint32            group_layer_flags = 0;
+  guint32            text_layer_flags = 0;
+  gint               width;
+  gint               height;
+  gint               type;
+  GimpImageBaseType  base_type;
+  gboolean           has_alpha;
+  const Babl        *format;
+  gboolean           is_fs_drawable;
+  gchar             *name;
 
   /* check and see if this is the drawable the floating selection
    *  is attached to. if it is then we'll do the attachment in our caller.
@@ -1559,29 +1538,6 @@ xcf_load_layer (XcfInfo    *info,
 
   GIMP_LOG (XCF, "layer props loaded");
 
-  parasite = gimp_item_parasite_find (GIMP_ITEM (layer),
-                                       "gimp-item-metadata");
-  if (parasite)
-    {
-      GimpMetadata   *metadata;
-      const gchar    *metadata_string;
-
-      metadata_string = (gchar *) gimp_parasite_data (parasite);
-      metadata = gimp_metadata_deserialize (metadata_string);
-
-      if (metadata)
-        {
-          gimp_item_set_metadata (GIMP_ITEM (layer), metadata, FALSE);
-          g_object_unref (metadata);
-        }
-
-      gimp_item_parasite_detach (GIMP_ITEM (layer),
-                                 "gimp-item-metadata",
-                                 FALSE);
-    }
-
-  GIMP_LOG (XCF, "layer metadata loaded");
-
   xcf_progress_update (info);
 
   /* call the evil text layer hack that might change our layer pointer */
@@ -1671,14 +1627,13 @@ static GimpChannel *
 xcf_load_channel (XcfInfo   *info,
                   GimpImage *image)
 {
-  GimpChannel        *channel;
-  const GimpParasite *parasite;
-  guint32             hierarchy_offset;
-  gint                width;
-  gint                height;
-  gboolean            is_fs_drawable;
-  gchar              *name;
-  GimpRGB             color = { 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE };
+  GimpChannel *channel;
+  guint32      hierarchy_offset;
+  gint         width;
+  gint         height;
+  gboolean     is_fs_drawable;
+  gchar       *name;
+  GimpRGB      color = { 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE };
 
   /* check and see if this is the drawable the floating selection
    *  is attached to. if it is then we'll do the attachment in our caller.
@@ -1703,27 +1658,6 @@ xcf_load_channel (XcfInfo   *info,
   if (!xcf_load_channel_props (info, image, &channel))
     goto error;
 
-  parasite = gimp_item_parasite_find (GIMP_ITEM (channel),
-                                       "gimp-item-metadata");
-  if (parasite)
-    {
-      GimpMetadata   *metadata;
-      const gchar    *metadata_string;
-
-      metadata_string = (gchar *) gimp_parasite_data (parasite);
-      metadata = gimp_metadata_deserialize (metadata_string);
-
-      if (metadata)
-        {
-          gimp_item_set_metadata (GIMP_ITEM (channel), metadata, FALSE);
-          g_object_unref (metadata);
-        }
-
-      gimp_item_parasite_detach (GIMP_ITEM (channel),
-                                 "gimp-item-metadata",
-                                 FALSE);
-    }
-
   xcf_progress_update (info);
 
   /* read the hierarchy and layer mask offsets */
diff --git a/app/xcf/xcf-save.c b/app/xcf/xcf-save.c
index 3d9cf4a..7930b0f 100644
--- a/app/xcf/xcf-save.c
+++ b/app/xcf/xcf-save.c
@@ -45,7 +45,6 @@
 #include "core/gimpimage-metadata.h"
 #include "core/gimpimage-private.h"
 #include "core/gimpimage-sample-points.h"
-#include "core/gimpitem.h"
 #include "core/gimplayer.h"
 #include "core/gimplayermask.h"
 #include "core/gimpparasitelist.h"
@@ -338,11 +337,11 @@ xcf_save_image_props (XcfInfo    *info,
                       GimpImage  *image,
                       GError    **error)
 {
-  GimpImagePrivate *private             = GIMP_IMAGE_GET_PRIVATE (image);
-  GimpParasite     *grid_parasite       = NULL;
-  GimpParasite     *meta_parasite       = NULL;
-  GimpParasite     *compat_parasite     = NULL;
-  GimpUnit          unit                = gimp_image_get_unit (image);
+  GimpImagePrivate *private         = GIMP_IMAGE_GET_PRIVATE (image);
+  GimpParasite     *grid_parasite   = NULL;
+  GimpParasite     *meta_parasite   = NULL;
+  GimpParasite     *compat_parasite = NULL;
+  GimpUnit          unit            = gimp_image_get_unit (image);
   gdouble           xres;
   gdouble           yres;
 
@@ -394,27 +393,6 @@ xcf_save_image_props (XcfInfo    *info,
       gimp_parasite_list_add (private->parasites, grid_parasite);
     }
 
-#if 0
-  if (gimp_image_get_attributes (image))
-    {
-      GimpParasite   *attributes_parasite = NULL;
-      GimpAttributes *attributes = gimp_image_get_attributes (image);
-      gchar          *attributes_string;
-
-      attributes_string = gimp_attributes_serialize (attributes);
-
-      if (attributes_string)
-        {
-          attributes_parasite = gimp_parasite_new ("gimp-image-attributes",
-                                                   GIMP_PARASITE_PERSISTENT,
-                                                   strlen (attributes_string) + 1,
-                                                   attributes_string);
-          gimp_parasite_list_add (private->parasites, attributes_parasite);
-          g_free (attributes_string);
-        }
-    }
-#endif
-
   if (gimp_image_get_metadata (image))
     {
       GimpMetadata *metadata = gimp_image_get_metadata (image);
@@ -490,25 +468,6 @@ xcf_save_layer_props (XcfInfo    *info,
   GimpParasiteList *parasites;
   gint              offset_x;
   gint              offset_y;
-  GimpParasite     *metadata_parasite = NULL;
-
-  if (gimp_item_get_metadata (GIMP_ITEM (layer)))
-    {
-      GimpMetadata *metadata = gimp_item_get_metadata (GIMP_ITEM (layer));
-      gchar        *metadata_string;
-
-      metadata_string = gimp_metadata_serialize (metadata);
-
-      if (metadata_string)
-        {
-          metadata_parasite = gimp_parasite_new ("gimp-item-metadata",
-                                                 GIMP_PARASITE_PERSISTENT,
-                                                 strlen (metadata_string) + 1,
-                                                 metadata_string);
-          gimp_item_parasite_attach (GIMP_ITEM (layer), metadata_parasite, FALSE);
-          g_free (metadata_string);
-        }
-    }
 
   if (gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
     xcf_check_error (xcf_save_prop (info, image, PROP_GROUP_ITEM, error));
@@ -624,27 +583,6 @@ xcf_save_channel_props (XcfInfo      *info,
 {
   GimpParasiteList *parasites;
   guchar            col[3];
-#if 0
-  GimpParasite     *attributes_parasite = NULL;
-
-  if (gimp_item_get_attributes (GIMP_ITEM (channel)))
-    {
-      GimpAttributes *attributes = gimp_item_get_attributes (GIMP_ITEM (channel));
-      gchar          *attributes_string;
-
-      attributes_string = gimp_attributes_serialize (attributes);
-
-      if (attributes_string)
-        {
-          attributes_parasite = gimp_parasite_new ("gimp-item-attributes",
-                                                   GIMP_PARASITE_PERSISTENT,
-                                                   strlen (attributes_string) + 1,
-                                                   attributes_string);
-          gimp_item_parasite_attach (GIMP_ITEM (channel), attributes_parasite, FALSE);
-          g_free (attributes_string);
-        }
-    }
-#endif
 
   if (channel == gimp_image_get_active_channel (image))
     xcf_check_error (xcf_save_prop (info, image, PROP_ACTIVE_CHANNEL, error));
diff --git a/configure.ac b/configure.ac
index 918b78b..e9bf40a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,7 +66,7 @@ m4_define([pycairo_required_version], [1.0.2])
 m4_define([poppler_required_version], [0.44.0])
 m4_define([poppler_data_required_version], [0.4.7])
 m4_define([libgudev_required_version], [167])
-m4_define([gexiv2_required_version], [0.10.3])
+m4_define([gexiv2_required_version], [0.6.1])
 m4_define([libmypaint_required_version], [1.3.0])
 m4_define([lcms_required_version], [2.7])
 m4_define([libpng_required_version], [1.6.25])
diff --git a/icons/icon-list.mk b/icons/icon-list.mk
index db71840..5ed962b 100644
--- a/icons/icon-list.mk
+++ b/icons/icon-list.mk
@@ -142,7 +142,6 @@ scalable_images = \
        scalable/gimp-histogram.svg                     \
        scalable/gimp-images.svg                        \
        scalable/gimp-image.svg                         \
-       scalable/gimp-image-metadata.svg                \
        scalable/gimp-image-open.svg                    \
        scalable/gimp-image-reload.svg                  \
        scalable/gimp-info.svg                          \
@@ -354,7 +353,6 @@ vector24_images = \
        24/gimp-grid.svg                                \
        24/gimp-histogram.svg                           \
        24/gimp-image.svg                               \
-       24/gimp-image-metadata.svg                              \
        24/gimp-images.svg                              \
        24/gimp-info.svg                                \
        24/gimp-landscape.svg                           \
@@ -607,7 +605,6 @@ icons16_images = \
        16/gimp-histogram-logarithmic.png                       \
        16/gimp-histogram.png                                           \
        16/gimp-image.png                                                       \
-       16/gimp-image-metadata.png                                      \
        16/gimp-images.png                                                      \
        16/gimp-image-open.png                                          \
        16/gimp-image-reload.png                                        \
@@ -864,7 +861,6 @@ icons24_images = \
        24/gimp-hchain.png                      \
        24/gimp-hfill.png                       \
        24/gimp-image.png                       \
-       24/gimp-image-metadata.png              \
        24/gimp-images.png                      \
        24/gimp-info.png                        \
        24/gimp-layer-mask.png                  \
@@ -974,7 +970,6 @@ icons48_images = \
        48/gimp-channel.png                     \
        48/gimp-floating-selection.png          \
        48/gimp-image.png                       \
-       48/gimp-image-metadata.png                      \
        48/gimp-layer-mask.png                  \
        48/gimp-layer.png                       \
        48/gimp-prefs-color-management.png      \
diff --git a/libgimp/Makefile.am b/libgimp/Makefile.am
index dfb0169..72ce2b7 100644
--- a/libgimp/Makefile.am
+++ b/libgimp/Makefile.am
@@ -222,8 +222,6 @@ libgimp_sources = \
        gimpimage.h             \
        gimpimagecolorprofile.c \
        gimpimagecolorprofile.h \
-       gimpitem.c              \
-       gimpitem.h              \
        gimplayer.c             \
        gimplayer.h             \
        gimppalette.c           \
@@ -347,7 +345,6 @@ gimpinclude_HEADERS = \
        gimpgradientselect.h            \
        gimpimage.h                     \
        gimpimagecolorprofile.h         \
-       gimpitem.h                      \
        gimplayer.h                     \
        gimppalette.h                   \
        gimppalettes.h                  \
diff --git a/libgimp/gimp.def b/libgimp/gimp.def
index 066c234..ac54622 100644
--- a/libgimp/gimp.def
+++ b/libgimp/gimp.def
@@ -557,7 +557,6 @@ EXPORTS
        gimp_item_get_linked
        gimp_item_get_lock_content
        gimp_item_get_lock_position
-       gimp_item_get_metadata
        gimp_item_get_name
        gimp_item_get_parasite
        gimp_item_get_parasite_list
@@ -577,7 +576,6 @@ EXPORTS
        gimp_item_set_linked
        gimp_item_set_lock_content
        gimp_item_set_lock_position
-       gimp_item_set_metadata
        gimp_item_set_name
        gimp_item_set_tattoo
        gimp_item_set_visible
diff --git a/libgimp/gimp.h b/libgimp/gimp.h
index bf23188..0b89b20 100644
--- a/libgimp/gimp.h
+++ b/libgimp/gimp.h
@@ -46,7 +46,6 @@
 #include <libgimp/gimpgradientselect.h>
 #include <libgimp/gimpimage.h>
 #include <libgimp/gimpimagecolorprofile.h>
-#include <libgimp/gimpitem.h>
 #include <libgimp/gimplayer.h>
 #include <libgimp/gimppalette.h>
 #include <libgimp/gimppalettes.h>
diff --git a/libgimp/gimpimagemetadata.c b/libgimp/gimpimagemetadata.c
index 7115437..5591403 100644
--- a/libgimp/gimpimagemetadata.c
+++ b/libgimp/gimpimagemetadata.c
@@ -28,7 +28,6 @@
 #include "gimp.h"
 #include "gimpui.h"
 #include "gimpimagemetadata.h"
-#include "libgimpbase/gimpbase.h"
 
 #include "libgimp-intl.h"
 
@@ -45,6 +44,7 @@ static gboolean    gimp_image_metadata_rotate_dialog (gint32             image_I
                                                       GExiv2Orientation  orientation,
                                                       const gchar       *parasite_name);
 
+
 /*  public functions  */
 
 /**
@@ -67,7 +67,7 @@ gimp_image_metadata_load_prepare (gint32        image_ID,
                                   GFile        *file,
                                   GError      **error)
 {
-  GimpMetadata   *metadata;
+  GimpMetadata *metadata;
 
   g_return_val_if_fail (image_ID > 0, NULL);
   g_return_val_if_fail (mime_type != NULL, NULL);
@@ -81,24 +81,18 @@ gimp_image_metadata_load_prepare (gint32        image_ID,
 #if 0
       {
         gchar *xml = gimp_metadata_serialize (metadata);
+        GimpMetadata *new = gimp_metadata_deserialize (xml);
+        gchar *xml2 = gimp_metadata_serialize (new);
 
-//        FILE *f = fopen ("/tmp/gimp-test-xml1", "w");
-        FILE *f = fopen ("e:\\gimp-test-xml1", "w");
+        FILE *f = fopen ("/tmp/gimp-test-xml1", "w");
         fprintf (f, "%s", xml);
         fclose (f);
 
-        GimpMetadata *new = gimp_metadata_deserialize (xml);
-
-        gimp_metadata_print (new);
-
-        gchar *xml2 = gimp_metadata_serialize (new);
-
-//        f = fopen ("/tmp/gimp-test-xml2", "w");
-        f = fopen ("e:\\gimp-test-xml2", "w");
+        f = fopen ("/tmp/gimp-test-xml2", "w");
         fprintf (f, "%s", xml2);
         fclose (f);
 
-//        system ("diff -u /tmp/gimp-test-xml1 /tmp/gimp-test-xml2");
+        system ("diff -u /tmp/gimp-test-xml1 /tmp/gimp-test-xml2");
 
         g_free (xml);
         g_free (xml2);
@@ -106,7 +100,7 @@ gimp_image_metadata_load_prepare (gint32        image_ID,
       }
 #endif
 
-      gexiv2_metadata_erase_exif_thumbnail (GEXIV2_METADATA (metadata));
+      gexiv2_metadata_erase_exif_thumbnail (metadata);
     }
 
   return metadata;
@@ -128,7 +122,6 @@ gimp_image_metadata_load_prepare (gint32        image_ID,
  */
 void
 gimp_image_metadata_load_finish (gint32                 image_ID,
-                                 gint32                 layer_ID,
                                  const gchar           *mime_type,
                                  GimpMetadata          *metadata,
                                  GimpMetadataLoadFlags  flags,
@@ -136,28 +129,17 @@ gimp_image_metadata_load_finish (gint32                 image_ID,
 {
   g_return_if_fail (image_ID > 0);
   g_return_if_fail (mime_type != NULL);
-  g_return_if_fail (IS_GIMP_METADATA(metadata));
-
-  if (flags & GIMP_METADATA_LOAD_ORIENTATION)
-    {
-      gimp_image_metadata_rotate_query (image_ID, mime_type,
-                                        metadata, interactive);
-    }
+  g_return_if_fail (GEXIV2_IS_METADATA (metadata));
 
   if (flags & GIMP_METADATA_LOAD_COMMENT)
     {
-      GimpAttribute *attribute = NULL;
-      gchar         *comment   = NULL;
+      gchar *comment;
 
-      attribute = gimp_metadata_get_attribute (metadata, "Exif.Photo.UserComment");
-      if (attribute)
-        comment = gimp_attribute_get_string (attribute);
-      else
-        {
-          attribute = gimp_metadata_get_attribute (metadata, "Exif.Image.ImageDescription");
-          if (attribute)
-            comment = gimp_attribute_get_string (attribute);
-        }
+      comment = gexiv2_metadata_get_tag_interpreted_string (metadata,
+                                                            "Exif.Photo.UserComment");
+      if (! comment)
+        comment = gexiv2_metadata_get_tag_interpreted_string (metadata,
+                                                              "Exif.Image.ImageDescription");
 
       if (comment)
         {
@@ -173,6 +155,7 @@ gimp_image_metadata_load_finish (gint32                 image_ID,
           gimp_parasite_free (parasite);
         }
     }
+
   if (flags & GIMP_METADATA_LOAD_RESOLUTION)
     {
       gdouble   xres;
@@ -186,10 +169,19 @@ gimp_image_metadata_load_finish (gint32                 image_ID,
         }
     }
 
+  if (flags & GIMP_METADATA_LOAD_ORIENTATION)
+    {
+      gimp_image_metadata_rotate_query (image_ID, mime_type,
+                                        metadata, interactive);
+    }
+
   if (flags & GIMP_METADATA_LOAD_COLORSPACE)
     {
       GimpColorProfile *profile = gimp_image_get_color_profile (image_ID);
 
+      /* only look for colorspace information from metadata if the
+       * image didn't contain an embedded color profile
+       */
       if (! profile)
         {
           GimpMetadataColorspace colorspace;
@@ -217,11 +209,7 @@ gimp_image_metadata_load_finish (gint32                 image_ID,
         g_object_unref (profile);
     }
 
-    gimp_image_set_metadata (image_ID, metadata);
-    if (layer_ID > 0)
-      {
-        gimp_item_set_metadata (layer_ID, metadata);
-      }
+  gimp_image_set_metadata (image_ID, metadata);
 }
 
 /**
@@ -231,7 +219,7 @@ gimp_image_metadata_load_finish (gint32                 image_ID,
  * @suggested_flags: Suggested default values for the @flags passed to
  *                   gimp_image_metadata_save_finish()
  *
- * Gets the image attributes for saving using
+ * Gets the image metadata for saving it using
  * gimp_image_metadata_save_finish().
  *
  * The @suggested_flags are determined from what kind of metadata
@@ -239,7 +227,7 @@ gimp_image_metadata_load_finish (gint32                 image_ID,
  * value for GIMP_METADATA_SAVE_THUMBNAIL is determined by whether
  * there was a thumbnail in the previously imported image.
  *
- * Returns: The image's attributes, prepared for saving.
+ * Returns: The image's metadata, prepared for saving.
  *
  * Since: 2.10
  */
@@ -248,7 +236,7 @@ gimp_image_metadata_save_prepare (gint32                 image_ID,
                                   const gchar           *mime_type,
                                   GimpMetadataSaveFlags *suggested_flags)
 {
-  GimpMetadata   *metadata   = NULL;
+  GimpMetadata *metadata;
 
   g_return_val_if_fail (image_ID > 0, NULL);
   g_return_val_if_fail (mime_type != NULL, NULL);
@@ -256,36 +244,133 @@ gimp_image_metadata_save_prepare (gint32                 image_ID,
 
   *suggested_flags = GIMP_METADATA_SAVE_ALL;
 
-  /* this is a GimpMetadata XML-Packet
-   * it is deserialized to a GimpMetadata object.
-   * Deserialization fills the GExiv2Metadata object of the GimpMetadata*/
   metadata = gimp_image_get_metadata (image_ID);
 
   if (metadata)
     {
+      GDateTime          *datetime;
+      const GimpParasite *comment_parasite;
+      const gchar        *comment = NULL;
+      gint                image_width;
+      gint                image_height;
+      gdouble             xres;
+      gdouble             yres;
+      gchar               buffer[32];
+
+      image_width  = gimp_image_width  (image_ID);
+      image_height = gimp_image_height (image_ID);
+
+      datetime = g_date_time_new_now_local ();
+
+      comment_parasite = gimp_image_get_parasite (image_ID, "gimp-comment");
+      if (comment_parasite)
+        comment = gimp_parasite_data (comment_parasite);
+
       /* Exif */
 
-      if (! gimp_metadata_has_tag_type (metadata, TAG_EXIF))
+      if (! gexiv2_metadata_has_exif (metadata))
         *suggested_flags &= ~GIMP_METADATA_SAVE_EXIF;
 
+      if (comment)
+        {
+          gexiv2_metadata_set_tag_string (metadata,
+                                          "Exif.Photo.UserComment",
+                                          comment);
+          gexiv2_metadata_set_tag_string (metadata,
+                                          "Exif.Image.ImageDescription",
+                                          comment);
+        }
+
+      g_snprintf (buffer, sizeof (buffer),
+                  "%d:%02d:%02d %02d:%02d:%02d",
+                  g_date_time_get_year (datetime),
+                  g_date_time_get_month (datetime),
+                  g_date_time_get_day_of_month (datetime),
+                  g_date_time_get_hour (datetime),
+                  g_date_time_get_minute (datetime),
+                  g_date_time_get_second (datetime));
+      gexiv2_metadata_set_tag_string (metadata,
+                                      "Exif.Image.DateTime",
+                                      buffer);
+
+      gexiv2_metadata_set_tag_string (metadata,
+                                      "Exif.Image.Software",
+                                      PACKAGE_STRING);
+
+      gimp_metadata_set_pixel_size (metadata,
+                                    image_width, image_height);
+
+      gimp_image_get_resolution (image_ID, &xres, &yres);
+      gimp_metadata_set_resolution (metadata, xres, yres,
+                                    gimp_image_get_unit (image_ID));
 
       /* XMP */
 
-      if (! gimp_metadata_has_tag_type (metadata, TAG_XMP))
+      if (! gexiv2_metadata_has_xmp (metadata))
         *suggested_flags &= ~GIMP_METADATA_SAVE_XMP;
 
+      gexiv2_metadata_set_tag_string (metadata,
+                                      "Xmp.dc.Format",
+                                      mime_type);
+
+      if (! g_strcmp0 (mime_type, "image/tiff"))
+        {
+          /* TIFF specific XMP data */
+
+          g_snprintf (buffer, sizeof (buffer), "%d", image_width);
+          gexiv2_metadata_set_tag_string (metadata,
+                                          "Xmp.tiff.ImageWidth",
+                                          buffer);
+
+          g_snprintf (buffer, sizeof (buffer), "%d", image_height);
+          gexiv2_metadata_set_tag_string (metadata,
+                                          "Xmp.tiff.ImageLength",
+                                          buffer);
+
+          g_snprintf (buffer, sizeof (buffer),
+                      "%d:%02d:%02d %02d:%02d:%02d",
+                      g_date_time_get_year (datetime),
+                      g_date_time_get_month (datetime),
+                      g_date_time_get_day_of_month (datetime),
+                      g_date_time_get_hour (datetime),
+                      g_date_time_get_minute (datetime),
+                      g_date_time_get_second (datetime));
+          gexiv2_metadata_set_tag_string (metadata,
+                                          "Xmp.tiff.DateTime",
+                                          buffer);
+        }
 
       /* IPTC */
 
-      if (! gimp_metadata_has_tag_type (metadata, TAG_IPTC))
+      if (! gexiv2_metadata_has_iptc (metadata))
         *suggested_flags &= ~GIMP_METADATA_SAVE_IPTC;
 
+      g_snprintf (buffer, sizeof (buffer),
+                  "%d-%d-%d",
+                  g_date_time_get_year (datetime),
+                  g_date_time_get_month (datetime),
+                  g_date_time_get_day_of_month (datetime));
+      gexiv2_metadata_set_tag_string (metadata,
+                                      "Iptc.Application2.DateCreated",
+                                      buffer);
+
+      g_snprintf (buffer, sizeof (buffer),
+                  "%02d:%02d:%02d-%02d:%02d",
+                  g_date_time_get_hour (datetime),
+                  g_date_time_get_minute (datetime),
+                  g_date_time_get_second (datetime),
+                  g_date_time_get_hour (datetime),
+                  g_date_time_get_minute (datetime));
+      gexiv2_metadata_set_tag_string (metadata,
+                                      "Iptc.Application2.TimeCreated",
+                                      buffer);
+
+      g_date_time_unref (datetime);
 
       /* Thumbnail */
 
       if (FALSE /* FIXME if (original image had a thumbnail) */)
         *suggested_flags &= ~GIMP_METADATA_SAVE_THUMBNAIL;
-        
     }
 
   return metadata;
@@ -316,26 +401,17 @@ gimp_image_metadata_save_finish (gint32                  image_ID,
                                  GFile                  *file,
                                  GError                **error)
 {
-  GExiv2Metadata     *gimpmetadata;
-  GExiv2Metadata     *filemetadata;
-  GimpMetadata       *gexivdata;
-  gboolean            success = FALSE;
-  gchar               buffer[32];
-  GDateTime          *datetime;
-  const GimpParasite *comment_parasite;
-  const gchar        *comment = NULL;
-  gint                image_width;
-  gint                image_height;
-  gdouble             xres;
-  gdouble             yres;
-  gchar              *value;
-
+  GExiv2Metadata *new_metadata;
   gboolean        support_exif;
   gboolean        support_xmp;
   gboolean        support_iptc;
+  gchar          *value;
+  gboolean        success = FALSE;
+  gint            i;
 
   g_return_val_if_fail (image_ID > 0, FALSE);
   g_return_val_if_fail (mime_type != NULL, FALSE);
+  g_return_val_if_fail (GEXIV2_IS_METADATA (metadata), FALSE);
   g_return_val_if_fail (G_IS_FILE (file), FALSE);
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
@@ -345,199 +421,74 @@ gimp_image_metadata_save_finish (gint32                  image_ID,
                   GIMP_METADATA_SAVE_THUMBNAIL)))
     return TRUE;
 
-  image_width  = gimp_image_width  (image_ID);
-  image_height = gimp_image_height (image_ID);
-
-  datetime = g_date_time_new_now_local ();
-
-  comment_parasite = gimp_image_get_parasite (image_ID, "gimp-comment");
-  if (comment_parasite)
-    comment = gimp_parasite_data (comment_parasite);
-
   /* read metadata from saved file */
-  gexivdata = gimp_metadata_load_from_file (file, error);
+  new_metadata = gimp_metadata_load_from_file (file, error);
 
-  if (! gexivdata)
+  if (! new_metadata)
     return FALSE;
 
-  filemetadata = GEXIV2_METADATA (gexivdata);
-  gimpmetadata = GEXIV2_METADATA (metadata);
-
-  support_exif = gexiv2_metadata_get_supports_exif (filemetadata);
-  support_xmp  = gexiv2_metadata_get_supports_xmp  (filemetadata);
-  support_iptc = gexiv2_metadata_get_supports_iptc (filemetadata);
+  support_exif = gexiv2_metadata_get_supports_exif (new_metadata);
+  support_xmp  = gexiv2_metadata_get_supports_xmp  (new_metadata);
+  support_iptc = gexiv2_metadata_get_supports_iptc (new_metadata);
 
-  /* Exif */
-
-  if (flags & GIMP_METADATA_SAVE_EXIF && support_exif)
+  if ((flags & GIMP_METADATA_SAVE_EXIF) && support_exif)
     {
-      gint i;
-
-      gchar **exif_data = gexiv2_metadata_get_exif_tags (gimpmetadata);
+      gchar **exif_data = gexiv2_metadata_get_exif_tags (metadata);
 
       for (i = 0; exif_data[i] != NULL; i++)
         {
-          if (! gexiv2_metadata_has_tag (filemetadata, exif_data[i]) &&
+          if (! gexiv2_metadata_has_tag (new_metadata, exif_data[i]) &&
               gimp_metadata_is_tag_supported (exif_data[i], mime_type))
             {
-              value = gexiv2_metadata_get_tag_string (gimpmetadata, exif_data[i]);
-              gexiv2_metadata_set_tag_string (filemetadata, exif_data[i],
+              value = gexiv2_metadata_get_tag_string (metadata, exif_data[i]);
+              gexiv2_metadata_set_tag_string (new_metadata, exif_data[i],
                                               value);
               g_free (value);
             }
         }
 
       g_strfreev (exif_data);
-
-      if (comment)
-        {
-          gimp_metadata_new_attribute (gexivdata,
-                                         "Exif.Photo.UserComment",
-                                         (gchar *) comment,
-                                         TYPE_UNICODE);
-          gimp_metadata_new_attribute (gexivdata,
-                                         "Exif.Image.ImageDescription",
-                                         (gchar *) comment,
-                                         TYPE_ASCII);
-        }
-
-      g_snprintf (buffer, sizeof (buffer),
-                  "%d:%02d:%02d %02d:%02d:%02d",
-                  g_date_time_get_year (datetime),
-                  g_date_time_get_month (datetime),
-                  g_date_time_get_day_of_month (datetime),
-                  g_date_time_get_hour (datetime),
-                  g_date_time_get_minute (datetime),
-                  g_date_time_get_second (datetime));
-      gimp_metadata_new_attribute (gexivdata,
-                                     "Exif.Image.DateTime",
-                                     buffer,
-                                     TYPE_ASCII);
-
-      gimp_metadata_new_attribute (gexivdata,
-                                     "Exif.Image.Software",
-                                     PACKAGE_STRING,
-                                     TYPE_ASCII);
-
-      gimp_metadata_set_pixel_size (gexivdata,
-                                      image_width, image_height);
-
-      gimp_image_get_resolution (image_ID, &xres, &yres);
-      gimp_metadata_set_resolution (gexivdata, xres, yres,
-                                      gimp_image_get_unit (image_ID));
     }
 
-  /* XMP */
-
-  if (flags & GIMP_METADATA_SAVE_XMP && support_xmp)
+  if ((flags & GIMP_METADATA_SAVE_XMP) && support_xmp)
     {
-      gint i;
-
-      gchar **xmp_data = gexiv2_metadata_get_xmp_tags (gimpmetadata);
+      gchar **xmp_data = gexiv2_metadata_get_xmp_tags (metadata);
 
       for (i = 0; xmp_data[i] != NULL; i++)
         {
-          GimpAttribute *attribute;
-
-          if (! gexiv2_metadata_has_tag (filemetadata, xmp_data[i]) &&
+          if (! gexiv2_metadata_has_tag (new_metadata, xmp_data[i]) &&
               gimp_metadata_is_tag_supported (xmp_data[i], mime_type))
             {
-              /* we need the attribute-value here, because some xmp-tags cannot be read out and stored like 
exif tags:
-               * xmp-tags allow structures like lists. These structures need this special handling. */
-              attribute = gimp_metadata_get_attribute (metadata, xmp_data[i]);
-              gimp_metadata_add_attribute (gexivdata, attribute);
+              value = gexiv2_metadata_get_tag_string (metadata, xmp_data[i]);
+              gexiv2_metadata_set_tag_string (new_metadata, xmp_data[i],
+                                              value);
+              g_free (value);
             }
         }
 
       g_strfreev (xmp_data);
-
-      gimp_metadata_new_attribute (gexivdata,
-                                     "Xmp.dc.Format",
-                                     (gchar *) mime_type,
-                                     TYPE_ASCII);
-
-      if (! g_strcmp0 (mime_type, "image/tiff"))
-        {
-          /* TIFF specific XMP data */
-
-          g_snprintf (buffer, sizeof (buffer), "%d", image_width);
-          gimp_metadata_new_attribute (gexivdata,
-                                         "Xmp.tiff.ImageWidth",
-                                         buffer,
-                                         TYPE_ASCII);
-
-          g_snprintf (buffer, sizeof (buffer), "%d", image_height);
-          gimp_metadata_new_attribute (gexivdata,
-                                         "Xmp.tiff.ImageLength",
-                                         buffer,
-                                         TYPE_ASCII);
-
-          g_snprintf (buffer, sizeof (buffer),
-                      "%d:%02d:%02d %02d:%02d:%02d",
-                      g_date_time_get_year (datetime),
-                      g_date_time_get_month (datetime),
-                      g_date_time_get_day_of_month (datetime),
-                      g_date_time_get_hour (datetime),
-                      g_date_time_get_minute (datetime),
-                      g_date_time_get_second (datetime));
-          gimp_metadata_new_attribute (gexivdata,
-                                         "Xmp.tiff.DateTime",
-                                         buffer,
-                                         TYPE_ASCII);
-        }
     }
 
-  /* IPTC */
-
-  if (flags & GIMP_METADATA_SAVE_IPTC && support_iptc)
+  if ((flags & GIMP_METADATA_SAVE_IPTC) && support_iptc)
     {
-      gint i;
-
-      gchar **iptc_data = gexiv2_metadata_get_iptc_tags (gimpmetadata);
+      gchar **iptc_data = gexiv2_metadata_get_iptc_tags (metadata);
 
       for (i = 0; iptc_data[i] != NULL; i++)
         {
-          GimpAttribute *attribute;
-
-          if (! gexiv2_metadata_has_tag (filemetadata, iptc_data[i]) &&
+          if (! gexiv2_metadata_has_tag (new_metadata, iptc_data[i]) &&
               gimp_metadata_is_tag_supported (iptc_data[i], mime_type))
             {
-              /* we need the attribute-value here, because iptc-tags of TYPE_MULTIPLE cannot be read out and 
stored like exif tags:
-               * These tags need this special handling. */
-              attribute = gimp_metadata_get_attribute (metadata, iptc_data[i]);
-              gimp_metadata_add_attribute (gexivdata, attribute);
+              value = gexiv2_metadata_get_tag_string (metadata, iptc_data[i]);
+              gexiv2_metadata_set_tag_string (new_metadata, iptc_data[i],
+                                              value);
+              g_free (value);
             }
         }
 
       g_strfreev (iptc_data);
-
-      g_snprintf (buffer, sizeof (buffer),
-                  "%d-%d-%d",
-                  g_date_time_get_year (datetime),
-                  g_date_time_get_month (datetime),
-                  g_date_time_get_day_of_month (datetime));
-      gimp_metadata_new_attribute (gexivdata,
-                                     "Iptc.Application2.DateCreated",
-                                     buffer,
-                                     TYPE_ASCII);
-
-      g_snprintf (buffer, sizeof (buffer),
-                  "%02d:%02d:%02d",
-                  g_date_time_get_hour (datetime),
-                  g_date_time_get_minute (datetime),
-                  g_date_time_get_second (datetime));
-      gimp_metadata_new_attribute (gexivdata,
-                                     "Iptc.Application2.TimeCreated",
-                                     buffer,
-                                     TYPE_ASCII);
-
-      g_date_time_unref (datetime);
-
     }
 
-  /* Thumbnail */
-
-  if ((flags & GIMP_METADATA_SAVE_THUMBNAIL) && g_strcmp0 (mime_type, "image/tiff"))
+  if (flags & GIMP_METADATA_SAVE_THUMBNAIL)
     {
       GdkPixbuf *thumb_pixbuf;
       gchar     *thumb_buffer;
@@ -573,27 +524,27 @@ gimp_image_metadata_save_finish (gint32                  image_ID,
         {
           gchar buffer[32];
 
-          gexiv2_metadata_set_exif_thumbnail_from_buffer (filemetadata,
+          gexiv2_metadata_set_exif_thumbnail_from_buffer (new_metadata,
                                                           (guchar *) thumb_buffer,
                                                           count);
 
           g_snprintf (buffer, sizeof (buffer), "%d", thumbw);
-          gexiv2_metadata_set_tag_string (filemetadata,
+          gexiv2_metadata_set_tag_string (new_metadata,
                                           "Exif.Thumbnail.ImageWidth",
                                           buffer);
 
           g_snprintf (buffer, sizeof (buffer), "%d", thumbh);
-          gexiv2_metadata_set_tag_string (filemetadata,
+          gexiv2_metadata_set_tag_string (new_metadata,
                                           "Exif.Thumbnail.ImageLength",
                                           buffer);
 
-          gexiv2_metadata_set_tag_string (filemetadata,
+          gexiv2_metadata_set_tag_string (new_metadata,
                                           "Exif.Thumbnail.BitsPerSample",
                                           "8 8 8");
-          gexiv2_metadata_set_tag_string (filemetadata,
+          gexiv2_metadata_set_tag_string (new_metadata,
                                           "Exif.Thumbnail.SamplesPerPixel",
                                           "3");
-          gexiv2_metadata_set_tag_string (filemetadata,
+          gexiv2_metadata_set_tag_string (new_metadata,
                                           "Exif.Thumbnail.PhotometricInterpretation",
                                           "6");
 
@@ -603,9 +554,9 @@ gimp_image_metadata_save_finish (gint32                  image_ID,
       g_object_unref (thumb_pixbuf);
     }
 
-  success = gimp_metadata_save_to_file (gexivdata, file, error);
+  success = gimp_metadata_save_to_file (new_metadata, file, error);
 
-  g_object_unref (filemetadata);
+  g_object_unref (new_metadata);
 
   return success;
 }
@@ -614,25 +565,21 @@ gint32
 gimp_image_metadata_load_thumbnail (GFile   *file,
                                     GError **error)
 {
-  GimpMetadata   *metadata;
-  GExiv2Metadata *gexiv2metadata;
-  GInputStream   *input_stream;
-  GdkPixbuf      *pixbuf;
-  guint8         *thumbnail_buffer;
-  gint            thumbnail_size;
-  gint32          image_ID = -1;
+  GimpMetadata *metadata;
+  GInputStream *input_stream;
+  GdkPixbuf    *pixbuf;
+  guint8       *thumbnail_buffer;
+  gint          thumbnail_size;
+  gint32        image_ID = -1;
 
   g_return_val_if_fail (G_IS_FILE (file), -1);
   g_return_val_if_fail (error == NULL || *error == NULL, -1);
 
   metadata = gimp_metadata_load_from_file (file, error);
-
-  gexiv2metadata = GEXIV2_METADATA (metadata);
-
   if (! metadata)
     return -1;
 
-  if (! gexiv2_metadata_get_exif_thumbnail (gexiv2metadata,
+  if (! gexiv2_metadata_get_exif_thumbnail (metadata,
                                             &thumbnail_buffer,
                                             &thumbnail_size))
     {
@@ -664,7 +611,7 @@ gimp_image_metadata_load_thumbnail (GFile   *file,
       gimp_image_insert_layer (image_ID, layer_ID, -1, 0);
 
       gimp_image_metadata_rotate (image_ID,
-                                  gexiv2_metadata_get_orientation (gexiv2metadata));
+                                  gexiv2_metadata_get_orientation (metadata));
     }
 
   g_object_unref (metadata);
@@ -779,15 +726,12 @@ gimp_image_metadata_rotate_query (gint32        image_ID,
                                   GimpMetadata *metadata,
                                   gboolean      interactive)
 {
-  GExiv2Metadata    *gexiv2metadata;
   GimpParasite      *parasite;
   gchar             *parasite_name;
   GExiv2Orientation  orientation;
   gboolean           query = interactive;
 
-  gexiv2metadata = GEXIV2_METADATA (metadata);
-
-  orientation = gexiv2_metadata_get_orientation (gexiv2metadata);
+  orientation = gexiv2_metadata_get_orientation (metadata);
 
   if (orientation <= GEXIV2_ORIENTATION_NORMAL ||
       orientation >  GEXIV2_ORIENTATION_MAX)
@@ -827,9 +771,9 @@ gimp_image_metadata_rotate_query (gint32        image_ID,
 
   gimp_image_metadata_rotate (image_ID, orientation);
 
-  gexiv2_metadata_set_tag_string (gexiv2metadata,
+  gexiv2_metadata_set_tag_string (metadata,
                                   "Exif.Image.Orientation", "1");
-  gexiv2_metadata_set_tag_string (gexiv2metadata,
+  gexiv2_metadata_set_tag_string (metadata,
                                   "Xmp.tiff.Orientation", "1");
 }
 
diff --git a/libgimp/gimpimagemetadata.h b/libgimp/gimpimagemetadata.h
index 1771ec2..26d0b71 100644
--- a/libgimp/gimpimagemetadata.h
+++ b/libgimp/gimpimagemetadata.h
@@ -35,7 +35,6 @@ GimpMetadata * gimp_image_metadata_load_prepare (gint32                 image_ID
                                                  GFile                 *file,
                                                  GError               **error);
 void           gimp_image_metadata_load_finish  (gint32                 image_ID,
-                                                 gint32                 layer_ID,
                                                  const gchar           *mime_type,
                                                  GimpMetadata          *metadata,
                                                  GimpMetadataLoadFlags  flags,
diff --git a/libgimp/gimpitem_pdb.c b/libgimp/gimpitem_pdb.c
index 2f68038..c1a004f 100644
--- a/libgimp/gimpitem_pdb.c
+++ b/libgimp/gimpitem_pdb.c
@@ -935,68 +935,6 @@ gimp_item_set_tattoo (gint32 item_ID,
 }
 
 /**
- * _gimp_item_get_metadata:
- * @item_ID: The item.
- *
- * Returns the item's metadata.
- *
- * Returns metadata from the item.
- *
- * Returns: The metadata as a xml string.
- **/
-gchar *
-_gimp_item_get_metadata (gint32 item_ID)
-{
-  GimpParam *return_vals;
-  gint nreturn_vals;
-  gchar *metadata_string = NULL;
-
-  return_vals = gimp_run_procedure ("gimp-item-get-metadata",
-                                    &nreturn_vals,
-                                    GIMP_PDB_ITEM, item_ID,
-                                    GIMP_PDB_END);
-
-  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
-    metadata_string = g_strdup (return_vals[1].data.d_string);
-
-  gimp_destroy_params (return_vals, nreturn_vals);
-
-  return metadata_string;
-}
-
-/**
- * _gimp_item_set_metadata:
- * @item_ID: The item.
- * @metadata_string: The metadata as a xml string.
- *
- * Set the item's metadata.
- *
- * Sets metadata on the item.
- *
- * Returns: TRUE on success.
- **/
-gboolean
-_gimp_item_set_metadata (gint32       item_ID,
-                         const gchar *metadata_string)
-{
-  GimpParam *return_vals;
-  gint nreturn_vals;
-  gboolean success = TRUE;
-
-  return_vals = gimp_run_procedure ("gimp-item-set-metadata",
-                                    &nreturn_vals,
-                                    GIMP_PDB_ITEM, item_ID,
-                                    GIMP_PDB_STRING, metadata_string,
-                                    GIMP_PDB_END);
-
-  success = return_vals[0].data.d_status == GIMP_PDB_SUCCESS;
-
-  gimp_destroy_params (return_vals, nreturn_vals);
-
-  return success;
-}
-
-/**
  * gimp_item_attach_parasite:
  * @item_ID: The item.
  * @parasite: The parasite to attach to the item.
diff --git a/libgimp/gimpitem_pdb.h b/libgimp/gimpitem_pdb.h
index a16d0e4..6b81f04 100644
--- a/libgimp/gimpitem_pdb.h
+++ b/libgimp/gimpitem_pdb.h
@@ -32,52 +32,49 @@ G_BEGIN_DECLS
 /* For information look into the C source or the html documentation */
 
 
-gboolean                 gimp_item_is_valid          (gint32              item_ID);
-gint32                   gimp_item_get_image         (gint32              item_ID);
-gboolean                 gimp_item_delete            (gint32              item_ID);
-gboolean                 gimp_item_is_drawable       (gint32              item_ID);
-gboolean                 gimp_item_is_layer          (gint32              item_ID);
-gboolean                 gimp_item_is_text_layer     (gint32              item_ID);
-gboolean                 gimp_item_is_channel        (gint32              item_ID);
-gboolean                 gimp_item_is_layer_mask     (gint32              item_ID);
-gboolean                 gimp_item_is_selection      (gint32              item_ID);
-gboolean                 gimp_item_is_vectors        (gint32              item_ID);
-gboolean                 gimp_item_is_group          (gint32              item_ID);
-gint32                   gimp_item_get_parent        (gint32              item_ID);
-gint*                    gimp_item_get_children      (gint32              item_ID,
-                                                      gint               *num_children);
-gchar*                   gimp_item_get_name          (gint32              item_ID);
-gboolean                 gimp_item_set_name          (gint32              item_ID,
-                                                      const gchar        *name);
-gboolean                 gimp_item_get_visible       (gint32              item_ID);
-gboolean                 gimp_item_set_visible       (gint32              item_ID,
-                                                      gboolean            visible);
-gboolean                 gimp_item_get_linked        (gint32              item_ID);
-gboolean                 gimp_item_set_linked        (gint32              item_ID,
-                                                      gboolean            linked);
-gboolean                 gimp_item_get_lock_content  (gint32              item_ID);
-gboolean                 gimp_item_set_lock_content  (gint32              item_ID,
-                                                      gboolean            lock_content);
-gboolean                 gimp_item_get_lock_position (gint32              item_ID);
-gboolean                 gimp_item_set_lock_position (gint32              item_ID,
-                                                      gboolean            lock_position);
-GimpColorTag             gimp_item_get_color_tag     (gint32              item_ID);
-gboolean                 gimp_item_set_color_tag     (gint32              item_ID,
-                                                      GimpColorTag        color_tag);
-gint                     gimp_item_get_tattoo        (gint32              item_ID);
-gboolean                 gimp_item_set_tattoo        (gint32              item_ID,
-                                                      gint                tattoo);
-G_GNUC_INTERNAL gchar*   _gimp_item_get_metadata     (gint32              item_ID);
-G_GNUC_INTERNAL gboolean _gimp_item_set_metadata     (gint32              item_ID,
-                                                      const gchar        *metadata_string);
-gboolean                 gimp_item_attach_parasite   (gint32              item_ID,
-                                                      const GimpParasite *parasite);
-gboolean                 gimp_item_detach_parasite   (gint32              item_ID,
-                                                      const gchar        *name);
-GimpParasite*            gimp_item_get_parasite      (gint32              item_ID,
-                                                      const gchar        *name);
-gchar**                  gimp_item_get_parasite_list (gint32              item_ID,
-                                                      gint               *num_parasites);
+gboolean      gimp_item_is_valid          (gint32              item_ID);
+gint32        gimp_item_get_image         (gint32              item_ID);
+gboolean      gimp_item_delete            (gint32              item_ID);
+gboolean      gimp_item_is_drawable       (gint32              item_ID);
+gboolean      gimp_item_is_layer          (gint32              item_ID);
+gboolean      gimp_item_is_text_layer     (gint32              item_ID);
+gboolean      gimp_item_is_channel        (gint32              item_ID);
+gboolean      gimp_item_is_layer_mask     (gint32              item_ID);
+gboolean      gimp_item_is_selection      (gint32              item_ID);
+gboolean      gimp_item_is_vectors        (gint32              item_ID);
+gboolean      gimp_item_is_group          (gint32              item_ID);
+gint32        gimp_item_get_parent        (gint32              item_ID);
+gint*         gimp_item_get_children      (gint32              item_ID,
+                                           gint               *num_children);
+gchar*        gimp_item_get_name          (gint32              item_ID);
+gboolean      gimp_item_set_name          (gint32              item_ID,
+                                           const gchar        *name);
+gboolean      gimp_item_get_visible       (gint32              item_ID);
+gboolean      gimp_item_set_visible       (gint32              item_ID,
+                                           gboolean            visible);
+gboolean      gimp_item_get_linked        (gint32              item_ID);
+gboolean      gimp_item_set_linked        (gint32              item_ID,
+                                           gboolean            linked);
+gboolean      gimp_item_get_lock_content  (gint32              item_ID);
+gboolean      gimp_item_set_lock_content  (gint32              item_ID,
+                                           gboolean            lock_content);
+gboolean      gimp_item_get_lock_position (gint32              item_ID);
+gboolean      gimp_item_set_lock_position (gint32              item_ID,
+                                           gboolean            lock_position);
+GimpColorTag  gimp_item_get_color_tag     (gint32              item_ID);
+gboolean      gimp_item_set_color_tag     (gint32              item_ID,
+                                           GimpColorTag        color_tag);
+gint          gimp_item_get_tattoo        (gint32              item_ID);
+gboolean      gimp_item_set_tattoo        (gint32              item_ID,
+                                           gint                tattoo);
+gboolean      gimp_item_attach_parasite   (gint32              item_ID,
+                                           const GimpParasite *parasite);
+gboolean      gimp_item_detach_parasite   (gint32              item_ID,
+                                           const gchar        *name);
+GimpParasite* gimp_item_get_parasite      (gint32              item_ID,
+                                           const gchar        *name);
+gchar**       gimp_item_get_parasite_list (gint32              item_ID,
+                                           gint               *num_parasites);
 
 
 G_END_DECLS
diff --git a/libgimpbase/Makefile.am b/libgimpbase/Makefile.am
index d35c9c0..c97e68f 100644
--- a/libgimpbase/Makefile.am
+++ b/libgimpbase/Makefile.am
@@ -90,8 +90,6 @@ libgimpbase_sources = \
        gimpparam.h             \
        gimpversion.h           \
        \
-       gimpattribute.c \
-       gimpattribute.h \
        gimpbase-private.c      \
        gimpbase-private.h      \
        gimpchecks.c            \
@@ -112,8 +110,6 @@ libgimpbase_sources = \
        gimpparasiteio.h        \
        gimpprotocol.c          \
        gimpprotocol.h          \
-       gimprational.c          \
-       gimprational.h          \
        gimprectangle.c         \
        gimprectangle.h         \
        gimpreloc.c             \
@@ -147,7 +143,6 @@ libgimpbaseinclude_HEADERS = \
        gimpparam.h             \
        gimpversion.h           \
        \
-       gimpattribute.h         \
        gimpchecks.h            \
        gimpdatafiles.h         \
        gimpenv.h               \
@@ -155,7 +150,6 @@ libgimpbaseinclude_HEADERS = \
        gimpmetadata.h          \
        gimpparasite.h          \
        gimpparasiteio.h        \
-       gimprational.h          \
        gimprectangle.h         \
        gimpsignal.h            \
        gimpunit.h              \
diff --git a/libgimpbase/gimpbase.def b/libgimpbase/gimpbase.def
index f3395f9..5897ed8 100644
--- a/libgimpbase/gimpbase.def
+++ b/libgimpbase/gimpbase.def
@@ -1,29 +1,6 @@
 EXPORTS
        gimp_add_mask_type_get_type
        gimp_any_to_utf8
-       gimp_attribute_copy
-       gimp_attribute_get_attribute_type
-       gimp_attribute_get_attribute_ifd
-       gimp_attribute_get_attribute_structure
-       gimp_attribute_get_attribute_tag
-       gimp_attribute_get_interpreted_string
-       gimp_attribute_get_name
-       gimp_attribute_get_sortable_name
-       gimp_attribute_get_string
-       gimp_attribute_get_structure_type
-       gimp_attribute_get_tag_type
-       gimp_attribute_get_value
-       gimp_attribute_get_value_type
-       gimp_attribute_get_value_type_from_string
-       gimp_attribute_get_gps_degree
-       gimp_attribute_get_xml
-       gimp_attribute_has_structure
-       gimp_attribute_is_valid
-       gimp_attribute_new_string
-       gimp_attribute_print
-       gimp_attribute_set_interpreted_string
-       gimp_attribute_set_structure_type
-       gimp_attribute_set_value_type
        gimp_base_init
        gimp_blend_mode_get_type
        gimp_brush_generated_shape_get_type
@@ -93,36 +70,21 @@ EXPORTS
        gimp_memsize_to_string
        gimp_merge_type_get_type
        gimp_message_handler_type_get_type
-       gimp_metadata_add_attribute
        gimp_metadata_deserialize
        gimp_metadata_duplicate
-       gimp_metadata_get_attribute
        gimp_metadata_get_colorspace
        gimp_metadata_get_resolution
-       gimp_metadata_get_table
-       gimp_metadata_get_type
-       gimp_metadata_has_attribute
-       gimp_metadata_has_tag_type
        gimp_metadata_is_tag_supported
-       gimp_metadata_iter_init
-       gimp_metadata_iter_next
        gimp_metadata_load_from_file
        gimp_metadata_new
-       gimp_metadata_new_attribute
-       gimp_metadata_new_gexiv2metadata
-       gimp_metadata_print
-       gimp_metadata_remove_attribute
-       gimp_metadata_has_attribute
+       gimp_metadata_save_to_file
        gimp_metadata_serialize
        gimp_metadata_set_bits_per_sample
        gimp_metadata_set_colorspace
-       gimp_metadata_save_to_file
        gimp_metadata_set_from_exif
        gimp_metadata_set_from_xmp
        gimp_metadata_set_pixel_size
        gimp_metadata_set_resolution
-       gimp_metadata_size
-       gimp_metadata_to_xmp_packet
        gimp_micro_version
        gimp_minor_version
        gimp_offset_type_get_type
@@ -248,5 +210,3 @@ EXPORTS
        gp_tile_ack_write
        gp_tile_data_write
        gp_tile_req_write
-       rational_free
-       srational_free
diff --git a/libgimpbase/gimpbase.h b/libgimpbase/gimpbase.h
index f60bef7..a5682e7 100644
--- a/libgimpbase/gimpbase.h
+++ b/libgimpbase/gimpbase.h
@@ -23,7 +23,6 @@
 
 #include <libgimpbase/gimpbasetypes.h>
 
-#include <libgimpbase/gimpattribute.h>
 #include <libgimpbase/gimpchecks.h>
 #include <libgimpbase/gimpcpuaccel.h>
 #include <libgimpbase/gimpdatafiles.h>
diff --git a/libgimpbase/gimpbasetypes.h b/libgimpbase/gimpbasetypes.h
index d05d80c..bef9904 100644
--- a/libgimpbase/gimpbasetypes.h
+++ b/libgimpbase/gimpbasetypes.h
@@ -45,8 +45,6 @@ G_BEGIN_DECLS
 #endif
 
 
-typedef struct _GimpAttribute    GimpAttribute;
-typedef struct _GimpMetadata     GimpMetadata;
 typedef struct _GimpParasite     GimpParasite;
 typedef struct _GimpDatafileData GimpDatafileData;
 typedef struct _GimpEnumDesc     GimpEnumDesc;
@@ -57,6 +55,7 @@ typedef struct _GimpValueArray   GimpValueArray;
 typedef void (* GimpDatafileLoaderFunc) (const GimpDatafileData *file_data,
                                          gpointer                user_data);
 
+typedef struct _GExiv2Metadata GimpMetadata;
 
 
 /**
diff --git a/libgimpbase/gimpmetadata.c b/libgimpbase/gimpmetadata.c
index d1f360f..8da75a7 100644
--- a/libgimpbase/gimpmetadata.c
+++ b/libgimpbase/gimpmetadata.c
@@ -22,10 +22,6 @@
 
 #include "config.h"
 
-#include <stdio.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
 #include <stdlib.h>
 #include <string.h>
 
@@ -34,8 +30,6 @@
 
 #include "libgimpmath/gimpmath.h"
 
-#include "gimprational.h"
-#include "gimpattribute.h"
 #include "gimpbasetypes.h"
 
 #include "gimplimits.h"
@@ -44,78 +38,24 @@
 
 #include "libgimp/libgimp-intl.h"
 
-typedef struct _GimpMetadataClass GimpMetadataClass;
-typedef struct _GimpMetadataPrivate GimpMetadataPrivate;
-
-struct _GimpMetadataPrivate {
-  GHashTable      *attribute_table;
-  GHashTable      *sorted_to_attribute;
-  GList           *sorted_key_list;
-  GSList          *xmp_structure_list;
 
-};
+/**
+ * SECTION: gimpmetadata
+ * @title: gimpmetadata
+ * @short_description: Basic functions for handling #GimpMetadata objects.
+ * @see_also: gimp_image_metadata_load_prepare(),
+ *            gimp_image_metadata_load_finish(),
+ *            gimp_image_metadata_load_prepare(),
+ *            gimp_image_metadata_load_finish().
+ *
+ * Basic functions for handling #GimpMetadata objects.
+ **/
 
-struct _GimpMetadata {
-  GExiv2Metadata       parent_instance;
-  GimpMetadataPrivate *priv;
-};
 
-struct _GimpMetadataClass {
-  GExiv2MetadataClass parent_class;
-};
+static GQuark   gimp_metadata_error_quark (void);
+static void     gimp_metadata_add         (GimpMetadata *src,
+                                           GimpMetadata *dest);
 
-static gpointer              gimpmetadata_parent_class    = NULL;
-static GimpAttribute        *current_attribute            = NULL;
-static gboolean              iter_initialized             = FALSE;
-
-static void                  gimp_metadata_finalize                    (GObject              *obj);
-static void                  gimp_metadata_get_property                (GObject              *object,
-                                                                        guint                 property_id,
-                                                                        GValue               *value,
-                                                                        GParamSpec           *pspec);
-static void                  gimp_metadata_set_property                (GObject              *object,
-                                                                        guint                 property_id,
-                                                                        const GValue         *value,
-                                                                        GParamSpec           *pspec);
-static GimpAttribute *       gimp_metadata_get_attribute_sorted        (GimpMetadata         *metadata,
-                                                                        const gchar          *sorted_name);
-static void                  gimp_metadata_deserialize_error           (GMarkupParseContext  *context,
-                                                                        GError               *error,
-                                                                        gpointer              user_data);
-static GQuark                gimp_metadata_error_quark                 (void);
-static void                  gimp_metadata_deserialize_start_element   (GMarkupParseContext  *context,
-                                                                        const gchar          *element_name,
-                                                                        const gchar         
**attribute_names,
-                                                                        const gchar         
**attribute_values,
-                                                                        gpointer              user_data,
-                                                                        GError              **error);
-static void                  gimp_metadata_deserialize_text            (GMarkupParseContext  *context,
-                                                                        const gchar          *text,
-                                                                        gsize                 text_len,
-                                                                        gpointer              user_data,
-                                                                        GError              **error);
-static void                  gimp_metadata_deserialize_end_element     (GMarkupParseContext  *context,
-                                                                        const gchar          *element_name,
-                                                                        gpointer              user_data,
-                                                                        GError              **error);
-static const gchar*          gimp_metadata_name_to_value               (const gchar         
**attribute_names,
-                                                                        const gchar         
**attribute_values,
-                                                                        const gchar          *name);
-static gboolean              has_xmp_structure                         (GSList               *xmp_list,
-                                                                        const gchar          *entry);
-GExiv2Metadata *             gimp_metadata_new_gexiv2metadata          (void);
-GimpAttribute *              gimp_metadata_from_parent                 (GimpMetadata         *metadata,
-                                                                        const gchar          *name);
-void                         gimp_metadata_to_parent                   (GimpMetadata         *metadata,
-                                                                        GimpAttribute        *attribute);
-void                         gimp_metadata_add_attribute_to_list       (GimpMetadata         *metadata,
-                                                                        GimpAttribute        *attribute);
-void                         gimp_metadata_from_gexiv2                 (GimpMetadata         *metadata);
-void                         gimp_metadata_to_gexiv2                   (GimpMetadata         *metadata);
-
-G_DEFINE_TYPE (GimpMetadata, gimp_metadata, GEXIV2_TYPE_METADATA)
-
-#define parent_class gimp_metadata_parent_class
 
 static const gchar *tiff_tags[] =
 {
@@ -152,6 +92,7 @@ static const gchar *unsupported_tags[] =
   "Exif.Image.ClipPath",
   "Exif.Image.XClipPathUnits",
   "Exif.Image.YClipPathUnits",
+  "Xmp.xmpMM.History",
   "Exif.Image.XPTitle",
   "Exif.Image.XPComment",
   "Exif.Image.XPAuthor",
@@ -159,7 +100,8 @@ static const gchar *unsupported_tags[] =
   "Exif.Image.XPSubject",
   "Exif.Image.DNGVersion",
   "Exif.Image.DNGBackwardVersion",
-  "Exif.Iop"};
+  "Exif.Iop"
+};
 
 static const guint8 minimal_exif[] =
 {
@@ -200,170 +142,53 @@ static const guint8 wilber_jpg[] =
 
 static const guint wilber_jpg_len = G_N_ELEMENTS (wilber_jpg);
 
-typedef struct
-{
-  gchar                     name[1024];
-  gboolean                  base64;
-  GimpAttributeValueType    type;
-  GimpMetadata             *metadata;
-} GimpMetadataParseData;
-
-struct Namespaces{
-  const gchar              *namespace_name;
-  const gchar              *namespace_URI;
-};
-
-struct Namespaces namespaces_table[] = {
-  {"gimp",     "http://www.gimp.org/ns/2.10/";                        },
-  {"dwc",      "http://rs.tdwg.org/dwc/terms/";                       },
-  {"lr",       "http://ns.adobe.com/lr/1.0/";                         },
-  {"gpano",    "http://ns.google.com/photos/1.0/panorama/";           },
-  {"panorama", "http://ns.adobe.com/photoshop/1.0/panorama-profile/"; }
-
-};
-
-
-static void gimp_metadata_class_init (GimpMetadataClass * klass)
-{
-  gimpmetadata_parent_class = g_type_class_peek_parent (klass);
-  g_type_class_add_private (klass, sizeof(GimpMetadataPrivate));
-
-  G_OBJECT_CLASS (klass)->get_property = gimp_metadata_get_property;
-  G_OBJECT_CLASS (klass)->set_property = gimp_metadata_set_property;
-  G_OBJECT_CLASS (klass)->finalize = gimp_metadata_finalize;
-}
-
-static void gimp_metadata_init (GimpMetadata * self)
-{
-  self->priv = GIMP_METADATA_GET_PRIVATE (self);
-  self->priv->attribute_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
-  self->priv->sorted_to_attribute = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-  self->priv->sorted_key_list = NULL;
-  self->priv->xmp_structure_list = NULL;
-}
-
-/**
- * gimp_metadata_finalize:
- *
- * instance finalizer
- */
-static void
-gimp_metadata_finalize (GObject* obj)
-{
-  GimpMetadata * metadata;
-
-  metadata = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_GIMP_METADATA, GimpMetadata);
-
-  g_hash_table_unref (metadata->priv->attribute_table);
-  g_hash_table_unref (metadata->priv->sorted_to_attribute);
-  g_list_free_full   (metadata->priv->sorted_key_list, (GDestroyNotify) g_free);
-  g_slist_free (metadata->priv->xmp_structure_list);
-
-  G_OBJECT_CLASS (gimpmetadata_parent_class)->finalize (obj);
-}
-
-/**
- * gimp_metadata_get_property
- *
- * instance get property
- */
-static void
-gimp_metadata_get_property (GObject * object,
-                            guint property_id,
-                            GValue * value,
-                            GParamSpec * pspec)
-{
-}
-
-/**
- * gimp_metadata_set_property
- *
- * instance set property
- */
-static void
-gimp_metadata_set_property (GObject * object,
-                            guint property_id,
-                            const GValue * value,
-                            GParamSpec * pspec)
-{
-}
 
 /**
  * gimp_metadata_new:
  *
- * returns a new #GimpMetadata object
+ * Creates a new #GimpMetadata instance.
  *
- * Return value:  a new @GimpMetadata object
+ * Return value: The new #GimpMetadata.
  *
- * Since : 2.10
+ * Since: 2.10
  */
 GimpMetadata *
 gimp_metadata_new (void)
 {
-  GimpMetadata *new_metadata = NULL;
-  gint          i;
+  GExiv2Metadata *metadata = NULL;
 
   if (gexiv2_initialize ())
     {
-      new_metadata = g_object_new (TYPE_GIMP_METADATA, NULL);
+      metadata = gexiv2_metadata_new ();
 
-      if (gexiv2_initialize ())
+      if (! gexiv2_metadata_open_buf (metadata, wilber_jpg, wilber_jpg_len,
+                                      NULL))
         {
-          if (gexiv2_metadata_open_buf (GEXIV2_METADATA (new_metadata), wilber_jpg, wilber_jpg_len,
-                                          NULL))
-            {
-              for (i = 0; i < G_N_ELEMENTS (namespaces_table); i++)
-                {
-                  struct Namespaces n_space = namespaces_table[i];
-                  gexiv2_metadata_register_xmp_namespace (n_space.namespace_URI, n_space.namespace_name);
-                }
-            }
+          g_object_unref (metadata);
 
+          return NULL;
         }
-
-      return new_metadata;
-
     }
-  else
-    {
-      return NULL;
-    }
-}
-
-/**
- * gimp_metadata_size: ToDo handle size
- *
- * @metadata: a #GimpMetadata
- *
- * Return value:  a #gint: amount of #GimpAttribute objects in
- * the #GimpMetadata container
- *
- * Since : 2.10
- */
-gint
-gimp_metadata_size (GimpMetadata *metadata)
-{
-  GimpMetadataPrivate *private = GIMP_METADATA_GET_PRIVATE (metadata);
 
-  return g_hash_table_size (private->attribute_table);
+  return metadata;
 }
 
 /**
  * gimp_metadata_duplicate:
+ * @metadata: The object to duplicate, or %NULL.
  *
- * @metadata: a #GimpMetadata
+ * Duplicates a #GimpMetadata instance.
  *
- * Duplicates the #GimpMetadata object with all the #GimpAttribute objects
- * Return value:  a copy of the @metadata object
+ * Return value: The new #GimpMetadata, or %NULL if @metadata is %NULL.
  *
- * Since : 2.10
+ * Since: 2.10
  */
 GimpMetadata *
 gimp_metadata_duplicate (GimpMetadata *metadata)
 {
-  GimpMetadata * new_metadata = NULL;
+  GimpMetadata *new_metadata = NULL;
 
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), NULL);
+  g_return_val_if_fail (metadata == NULL || GEXIV2_IS_METADATA (metadata), NULL);
 
   if (metadata)
     {
@@ -371,2296 +196,359 @@ gimp_metadata_duplicate (GimpMetadata *metadata)
 
       xml = gimp_metadata_serialize (metadata);
       new_metadata = gimp_metadata_deserialize (xml);
+      g_free (xml);
     }
 
   return new_metadata;
 }
 
-/**
- * gimp_metadata_get_table:
- *
- * @metadata: a #GimpMetadata
- *
- * Return value:  the #GHashTable
- *
- * Since : 2.10
- */
-GHashTable *
-gimp_metadata_get_table (GimpMetadata *metadata)
+typedef struct
 {
-  return metadata->priv->attribute_table;
-}
+  gchar         name[1024];
+  gboolean      base64;
+  GimpMetadata *metadata;
+} GimpMetadataParseData;
 
-/**
- * gimp_metadata_add_attribute:
- *
- * @metadata  : a #GimpMetadata
- * @attribute : a #GimpAttribute
- *
- * stores the @attribute in the @metadata container
- *
- * Since : 2.10
- */
-void
-gimp_metadata_add_attribute (GimpMetadata        *metadata,
-                             GimpAttribute       *attribute)
+static const gchar*
+gimp_metadata_attribute_name_to_value (const gchar **attribute_names,
+                                       const gchar **attribute_values,
+                                       const gchar  *name)
 {
-  const gchar *name;
-  gchar       *lowchar;
-
-  g_return_if_fail (IS_GIMP_METADATA (metadata));
-  g_return_if_fail (GIMP_IS_ATTRIBUTE (attribute));
-
-  name = gimp_attribute_get_name (attribute);
-
-  if (name)
+  while (*attribute_names)
     {
-        lowchar = g_ascii_strdown (name, -1);
-
-      /* FIXME: really simply add? That means, that an older value is overwritten */
-
-      if (g_hash_table_insert (metadata->priv->attribute_table, (gpointer) g_strdup (lowchar), (gpointer) 
attribute))
+      if (! strcmp (*attribute_names, name))
         {
-          gchar *sortable_tag;
-
-          sortable_tag = g_ascii_strdown (gimp_attribute_get_sortable_name (attribute), -1);
-
-          if (g_hash_table_insert (metadata->priv->sorted_to_attribute, (gpointer) g_strdup (sortable_tag), 
(gpointer) g_strdup (lowchar)))
-            {
-              metadata->priv->sorted_key_list = g_list_insert_sorted (metadata->priv->sorted_key_list,
-                                                                      (gpointer) g_strdup (sortable_tag),
-                                                                      (GCompareFunc) g_strcmp0);
-              gimp_metadata_to_parent (metadata, attribute);
-            }
-          else
-            {
-              g_hash_table_remove (metadata->priv->attribute_table, (gpointer) g_strdup (lowchar));
-            }
-
-          g_free (sortable_tag);
+          return *attribute_values;
         }
-      g_free (lowchar);
-    }
-}
 
-/**
- * gimp_metadata_get_attribute:
- *
- * @metadata : a #GimpMetadata
- * @name     : a #gchar array
- *
- * gets the #GimpAttribute object with @name
- *
- * Return value: the #GimpAttribute object if found, NULL otherwise.
- *
- * Since : 2.10
- */
-GimpAttribute *
-gimp_metadata_get_attribute (GimpMetadata      *metadata,
-                             const gchar       *name)
-{
-  GimpAttribute  *attribute_data = NULL;
-
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), NULL);
-
-  attribute_data = gimp_metadata_from_parent (metadata, name);
+      attribute_names++;
+      attribute_values++;
+    }
 
-  return attribute_data;
+  return NULL;
 }
 
-/**
- * gimp_metadata_get_attribute_sorted:
- *
- * @metadata: a #GimpMetadata
- * @name : a #gchar array
- *
- * gets the #GimpAttribute object with @sorted_name as
- * sortable_name
- * see GimpAttribute::get_sortable_name
- *
- * Return value: the #GimpAttribute object if found, NULL otherwise.
- *
- * Since : 2.10
- */
-static GimpAttribute *
-gimp_metadata_get_attribute_sorted (GimpMetadata      *metadata,
-                                    const gchar       *sorted_name)
+static void
+gimp_metadata_deserialize_start_element (GMarkupParseContext *context,
+                                         const gchar         *element_name,
+                                         const gchar        **attribute_names,
+                                         const gchar        **attribute_values,
+                                         gpointer             user_data,
+                                         GError             **error)
 {
-  gchar          *lowchar;
-  GimpAttribute  *attribute_data = NULL;
-  gpointer       *data;
-  gchar          *name_of_tag;
-
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), NULL);
-  g_return_val_if_fail (sorted_name != NULL, NULL);
-
-  lowchar = g_ascii_strdown (sorted_name, -1);
-
-  data = g_hash_table_lookup (metadata->priv->sorted_to_attribute, (gpointer) lowchar);
+  GimpMetadataParseData *parse_data = user_data;
 
-  if (data)
+  if (! strcmp (element_name, "tag"))
     {
-      name_of_tag = (gchar *) data;
+      const gchar *name;
+      const gchar *encoding;
+
+      name = gimp_metadata_attribute_name_to_value (attribute_names,
+                                                    attribute_values,
+                                                    "name");
+      encoding = gimp_metadata_attribute_name_to_value (attribute_names,
+                                                        attribute_values,
+                                                        "encoding");
 
-      data = g_hash_table_lookup (metadata->priv->attribute_table, (gpointer) name_of_tag);
-      if (data)
+      if (! name)
         {
-          attribute_data = (GimpAttribute *) data;
+          g_set_error (error, gimp_metadata_error_quark (), 1001,
+                       "Element 'tag' does not contain required attribute 'name'.");
+          return;
         }
-    }
 
-  g_free (lowchar);
+      strncpy (parse_data->name, name, sizeof (parse_data->name));
+      parse_data->name[sizeof (parse_data->name) - 1] = 0;
 
-  return attribute_data;
+      parse_data->base64 = (encoding && ! strcmp (encoding, "base64"));
+    }
 }
 
-/**
- * gimp_metadata_remove_attribute: ToDo remove from gexiv2 ToDo rewrite
- *
- * @metadata : a #GimpMetadata
- * @name     : a #gchar array
- *
- * removes the #GimpAttribute object with @name from the @metadata container
- *
- * Return value: TRUE, if removing was successful, FALSE otherwise.
- *
- * Since : 2.10
- */
-gboolean
-gimp_metadata_remove_attribute (GimpMetadata      *metadata,
-                                const gchar       *name)
+static void
+gimp_metadata_deserialize_end_element (GMarkupParseContext *context,
+                                       const gchar         *element_name,
+                                       gpointer             user_data,
+                                       GError             **error)
 {
-  gchar            *lowchar;
-  gboolean          success       = FALSE;
-  GHashTableIter    iter_remove;
-  gpointer          key, value;
-  gchar            *tag_to_remove = NULL;
-  gchar            *name_of_tag   = NULL;
+}
 
-  lowchar = g_ascii_strdown (name, -1);
+static void
+gimp_metadata_deserialize_text (GMarkupParseContext  *context,
+                                const gchar          *text,
+                                gsize                 text_len,
+                                gpointer              user_data,
+                                GError              **error)
+{
+  GimpMetadataParseData *parse_data = user_data;
+  const gchar           *current_element;
+
+  current_element = g_markup_parse_context_get_element (context);
 
-  if (g_hash_table_remove (metadata->priv->attribute_table, (gpointer) lowchar))
+  if (! g_strcmp0 (current_element, "tag"))
     {
-      gchar *tag_list_remove = NULL;
+      gchar *value = g_strndup (text, text_len);
 
-      g_hash_table_iter_init (&iter_remove, metadata->priv->sorted_to_attribute);
-      while (g_hash_table_iter_next (&iter_remove, &key, &value))
+      if (parse_data->base64)
         {
-          tag_to_remove  = (gchar *) key;
-          name_of_tag    = (gchar *) value;
-
-          if (! g_strcmp0 (lowchar, name_of_tag))
-            break;
-        }
+          guchar *decoded;
+          gsize   len;
 
-      tag_list_remove = g_strdup (tag_to_remove); /* because removing from hashtable frees tag_to_remove */
+          decoded = g_base64_decode (value, &len);
 
-      if (g_hash_table_remove (metadata->priv->sorted_to_attribute, (gpointer) tag_to_remove))
-        {
-          GList *list = NULL;
+          if (decoded[len - 1] == '\0')
+            gexiv2_metadata_set_tag_string (parse_data->metadata,
+                                            parse_data->name,
+                                            (const gchar *) decoded);
 
-          for (list = metadata->priv->sorted_key_list; list; list = list->next)
-            {
-              gchar *s_tag = (gchar *) list->data;
-
-              if (! g_strcmp0 (s_tag, tag_list_remove))
-                {
-                  metadata->priv->sorted_key_list = g_list_remove (metadata->priv->sorted_key_list,
-                                                                   (gconstpointer) s_tag);
-                  g_free (s_tag);
-                  break;
-                }
-            }
-          g_free (tag_list_remove);
-          success = TRUE;
+          g_free (decoded);
         }
       else
         {
-          if (name_of_tag)
-            g_free (name_of_tag);
-          if (tag_to_remove)
-            g_free (tag_to_remove);
-          success = FALSE;
+          gexiv2_metadata_set_tag_string (parse_data->metadata,
+                                          parse_data->name,
+                                          value);
         }
-    }
-  g_free (lowchar);
-
-  gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata), name);
-
-  return success;
-}
-
-/**
- * gimp_metadata_has_attribute:
- *
- * @metadata : a #GimpMetadata
- * @name     : a #gchar array
- *
- * tests, if a #GimpAttribute object with @name is in the @metadata container
- *
- * Return value: TRUE if yes, FALSE otherwise.
- *
- * Since : 2.10
- */
-gboolean
-gimp_metadata_has_attribute (GimpMetadata      *metadata,
-                             const gchar         *name)
-{
-  gchar *lowchar;
-  gboolean success;
-
-  lowchar = g_ascii_strdown (name, -1);
 
-  success = gexiv2_metadata_has_tag (GEXIV2_METADATA(metadata), name);
-
-  g_free (lowchar);
-
-  return success;
-}
-
-/**
- * gimp_metadata_new_attribute:
- *
- * @metadata: a #GimpMetadata
- * @name    : a #gchar array
- * @value   : a #gchar array
- * @type    : a #GimpAttributeValueType
- *
- * adds a #GimpAttribute object to @metadata container.
- * The #GimpAttribute object is created from the
- * @name,
- * @value and
- * @type parameters.
- *
- * Return value: TRUE if successful, FALSE otherwise.
- *
- * Since : 2.10
- */
-gboolean
-gimp_metadata_new_attribute (GimpMetadata *metadata,
-                             const gchar    *name,
-                             gchar          *value,
-                             GimpAttributeValueType type)
-{
-  GimpAttribute *attribute;
-
-  attribute = gimp_attribute_new_string (name, value, type);
-  if (attribute)
-    {
-      gimp_metadata_add_attribute (metadata, attribute);
-      return TRUE;
+      g_free (value);
     }
-
-  return FALSE;
 }
 
-/**
- * gimp_metadata_serialize: ToDo handle old metadata and get data from sorted list -> attributes.c
- *
- * @metadata: a #GimpMetadata
- *
- * creates a xml representation of all #GimpAttribute objects in the #GimpMetadata container.
- * see #GimpAttribute:gimp_attribute_get_xml
- *
- * Return value: a new #gchar array, the xml representation of the #GimpMetadata object.
- *
- * Since : 2.10
- */
-gchar *
-gimp_metadata_serialize (GimpMetadata *metadata)
+static  void
+gimp_metadata_deserialize_error (GMarkupParseContext *context,
+                                 GError              *error,
+                                 gpointer             user_data)
 {
-  GString        *string;
-  GList          *key_list;
-
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), NULL);
-
-  gimp_metadata_from_gexiv2 (metadata);
-
-  string = g_string_new (NULL);
-
-  g_string_append (string, "<?xml version='1.0' encoding='UTF-8'?>\n");
-  g_string_append (string, "<metadata>\n");
-
-  for (key_list = metadata->priv->sorted_key_list; key_list; key_list = key_list->next)
-    {
-      gchar          *xml       = NULL;
-      GimpAttribute  *attribute = NULL;
-      gchar          *p_key = (gchar *) key_list->data;
-
-      attribute      = gimp_metadata_get_attribute_sorted (metadata, p_key);
-
-      xml = gimp_attribute_get_xml (attribute);
-
-      g_string_append_printf (string, "%s\n", xml);
-
-      g_free (xml);
-    }
-
-  g_string_append (string, "</metadata>\n");
-
-  return g_string_free (string, FALSE);
+  g_printerr ("Metadata parse error: %s\n", error->message);
 }
 
 /**
  * gimp_metadata_deserialize:
+ * @metadata_xml: A string of serialized metadata XML.
  *
- * @xml: a #gchar array
+ * Deserializes a string of XML that has been created by
+ * gimp_metadata_serialize().
  *
- * parses a xml representation of a #GimpMetadata container.
- * see
- * #GimpMetadata:gimp_metadata_deserialize_start_element
- * #GimpMetadata:gimp_metadata_deserialize_end_element
- * #GimpMetadata:gimp_metadata_deserialize_text
- * #GimpMetadata:gimp_metadata_deserialize_error
+ * Return value: The new #GimpMetadata.
  *
- * Return value: a new #GimpMetadata object.
- *
- * Since : 2.10
+ * Since: 2.10
  */
 GimpMetadata *
-gimp_metadata_deserialize (const gchar *xml)
+gimp_metadata_deserialize (const gchar *metadata_xml)
 {
-  GMarkupParser            *markup_parser = g_slice_new (GMarkupParser);
-  GimpMetadataParseData    *parse_data = g_slice_new (GimpMetadataParseData);
-  GMarkupParseContext      *context;
-  GimpMetadata             *metadata;
+  GimpMetadata          *metadata;
+  GMarkupParser          markup_parser;
+  GimpMetadataParseData  parse_data;
+  GMarkupParseContext   *context;
 
-  g_return_val_if_fail (xml != NULL, NULL);
+  g_return_val_if_fail (metadata_xml != NULL, NULL);
 
   metadata = gimp_metadata_new ();
 
-  parse_data->metadata = metadata;
+  parse_data.metadata = metadata;
 
-  markup_parser->start_element = gimp_metadata_deserialize_start_element;
-  markup_parser->end_element   = gimp_metadata_deserialize_end_element;
-  markup_parser->text          = gimp_metadata_deserialize_text;
-  markup_parser->passthrough   = NULL;
-  markup_parser->error         = gimp_metadata_deserialize_error;
+  markup_parser.start_element = gimp_metadata_deserialize_start_element;
+  markup_parser.end_element   = gimp_metadata_deserialize_end_element;
+  markup_parser.text          = gimp_metadata_deserialize_text;
+  markup_parser.passthrough   = NULL;
+  markup_parser.error         = gimp_metadata_deserialize_error;
 
-  context = g_markup_parse_context_new (markup_parser, 0, parse_data, NULL);
+  context = g_markup_parse_context_new (&markup_parser, 0, &parse_data, NULL);
 
   g_markup_parse_context_parse (context,
-                                xml, strlen (xml),
+                                metadata_xml, strlen (metadata_xml),
                                 NULL);
 
   g_markup_parse_context_unref (context);
 
-  g_slice_free (GMarkupParser, markup_parser);
-  g_slice_free (GimpMetadataParseData, parse_data);
-
- return metadata;
+  return metadata;
 }
 
-/**
- * gimp_metadata_from_gexiv2metadata:
- * @metadata:  The metadata the gexiv2metadata will be added to, may be %NULL
- * @gexiv2metadata:  The metadata in gexiv2 format
- *
- * Converts the @gexiv2metadata retrieved from a file into
- * a #GimpMetadata object
- *
- * Return value: The #GimpMetadata object
- *
- * Since: GIMP 2.10
- */
-//GimpMetadata *
-//gimp_metadata_from_gexiv2metadata (GimpMetadata   *metadata,
-//                                   GimpMetadata   *gexivdata)
-//{
-//  const gchar               *tag_type;
-//  GimpAttribute             *attribute;
-//  GimpAttributeValueType     attrib_type;
-//  gint                       i;
-//  GimpMetadata              *new_metadata    = NULL;
-//  GExiv2Metadata            *gexiv2metadata  = NULL;
-//
-//  gexiv2metadata = GEXIV2_METADATA(gexivdata);
-//
-//  if (!metadata)
-//    {
-//      new_metadata = gimp_metadata_new ();
-//    }
-//  else
-//    {
-//      new_metadata = gimp_metadata_duplicate (metadata);
-//      g_object_unref (metadata);
-//    }
-//
-//  if (new_metadata)
-//    {
-//      gchar    **exif_data;
-//      gchar    **xmp_data;
-//      gchar    **iptc_data;
-//      gboolean   no_interpreted    = TRUE; /*FIXME: No interpreted String possible */
-//
-//      exif_data = gexiv2_metadata_get_exif_tags (gexiv2metadata);
-//
-//      for (i = 0; exif_data[i] != NULL; i++)
-//        {
-//          gchar    *interpreted_value = NULL;
-//          gchar    *value             = NULL;
-//          gboolean  interpreted       = FALSE;
-//
-//          value = gexiv2_metadata_get_tag_string (gexiv2metadata, exif_data[i]);
-//          interpreted_value = gexiv2_metadata_get_tag_interpreted_string (gexiv2metadata, exif_data[i]);
-//          tag_type = gexiv2_metadata_get_tag_type (exif_data[i]);
-//          attrib_type = gimp_attribute_get_value_type_from_string (tag_type);
-//
-//          interpreted = g_strcmp0 (value, interpreted_value);
-//
-//          if (!interpreted)
-//            {
-//              gint length;
-//
-//              length = strlen (interpreted_value);
-//              if (length > 2048)
-//                {
-//                  g_free (interpreted_value);
-//                  interpreted_value = g_strdup_printf ("(Size of value: %d)", length);
-//                  interpreted = TRUE;
-//                }
-//            }
-//
-//          attribute = gimp_attribute_new_string (exif_data[i], value, attrib_type);
-//          if (gimp_attribute_is_valid (attribute))
-//            {
-//              if (no_interpreted)
-//                {
-//                  if (interpreted)
-//                    {
-//                      gimp_attribute_set_interpreted_string (attribute, interpreted_value);
-//                    }
-//                }
-//              gimp_metadata_add_attribute (new_metadata, attribute);
-//            }
-//          else
-//            {
-//              g_object_unref (attribute);
-//            }
-//
-//          g_free (interpreted_value);
-//          g_free (value);
-//        }
-//
-//      g_strfreev (exif_data);
-//
-//      xmp_data = gexiv2_metadata_get_xmp_tags (gexiv2metadata);
-//
-//      for (i = 0; xmp_data[i] != NULL; i++)
-//        {
-//          gchar    *interpreted_value = NULL;
-//          gchar    *value             = NULL;
-//          gboolean  interpreted       = FALSE;
-//
-//          value = gexiv2_metadata_get_tag_string (gexiv2metadata, xmp_data[i]);
-//          interpreted_value = gexiv2_metadata_get_tag_interpreted_string (gexiv2metadata, xmp_data[i]);
-//          tag_type = gexiv2_metadata_get_tag_type (xmp_data[i]);
-//          attrib_type = gimp_attribute_get_value_type_from_string (tag_type);
-//
-//          interpreted = g_strcmp0 (value, interpreted_value);
-//
-//          attribute = gimp_attribute_new_string (xmp_data[i], value, attrib_type);
-//
-//          if (gimp_attribute_is_valid (attribute))
-//            {
-//              if (no_interpreted)
-//                {
-//                  if (interpreted)
-//                    gimp_attribute_set_interpreted_string (attribute, interpreted_value);
-//                }
-//              gimp_metadata_add_attribute (new_metadata, attribute);
-//            }
-//          else
-//            {
-//              g_object_unref (attribute);
-//            }
-//
-//          g_free (value);
-//        }
-//
-//      g_strfreev (xmp_data);
-//
-//      iptc_data = gexiv2_metadata_get_iptc_tags (gexiv2metadata);
-//
-//      for (i = 0; iptc_data[i] != NULL; i++)
-//        {
-//          gchar    *interpreted_value = NULL;
-//          gchar    *value             = NULL;
-//          gboolean  interpreted       = FALSE;
-//
-//          value = gexiv2_metadata_get_tag_string (gexiv2metadata, iptc_data[i]);
-//          interpreted_value = gexiv2_metadata_get_tag_interpreted_string (gexiv2metadata, iptc_data[i]);
-//          tag_type = gexiv2_metadata_get_tag_type (iptc_data[i]);
-//          attrib_type = gimp_attribute_get_value_type_from_string (tag_type);
-//
-//          interpreted = g_strcmp0 (value, interpreted_value);
-//
-//          attribute = gimp_attribute_new_string (iptc_data[i], value, attrib_type);
-//          if (gimp_attribute_is_valid (attribute))
-//            {
-//              if (no_interpreted)
-//                {
-//                  if (interpreted)
-//                    gimp_attribute_set_interpreted_string (attribute, interpreted_value);
-//                }
-//              gimp_metadata_add_attribute (new_metadata, attribute);
-//            }
-//          else
-//            {
-//              g_object_unref (attribute);
-//            }
-//
-//          g_free (value);
-//        }
-//
-//      g_strfreev (iptc_data);
-//    }
-//  return new_metadata;
-//}
-
-/**
- * gimp_metadata_from_gexiv2:
- * @metadata:  The metadata
- *
- * Constructs the @metadata retrieved from the gexiv2 package.
- *
- *
- * Since: GIMP 2.10
- */
-void
-gimp_metadata_from_gexiv2 (GimpMetadata   *metadata)
+static gchar *
+gimp_metadata_escape (const gchar *name,
+                      const gchar *value,
+                      gboolean    *base64)
 {
-  const gchar               *tag_type;
-  GimpAttribute             *attribute;
-  GimpAttributeValueType     attrib_type;
-  gint                       i;
-  GExiv2Metadata            *gexiv2metadata  = NULL;
-  GimpMetadataPrivate       *priv;
-
-  g_return_if_fail (IS_GIMP_METADATA (metadata));
-
-  priv = GIMP_METADATA_GET_PRIVATE (metadata);
-
-  if (priv->attribute_table)
-    g_hash_table_unref (priv->attribute_table);
-  if (priv->sorted_to_attribute)
-    g_hash_table_unref (priv->sorted_to_attribute);
-  if (priv->sorted_key_list)
-    g_list_free_full   (priv->sorted_key_list, (GDestroyNotify) g_free);
-  if (priv->xmp_structure_list)
-    g_slist_free (priv->xmp_structure_list);
-
-
-  priv->attribute_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
-  priv->sorted_to_attribute = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-  priv->sorted_key_list = NULL;
-  priv->xmp_structure_list = NULL;
-
-  gexiv2metadata = GEXIV2_METADATA(metadata);
-
+  if (! g_utf8_validate (value, -1, NULL))
     {
-      gchar    **exif_data;
-      gchar    **xmp_data;
-      gchar    **iptc_data;
-      gboolean   no_interpreted    = TRUE; /*FIXME: No interpreted String possible */
-
-      exif_data = gexiv2_metadata_get_exif_tags (gexiv2metadata);
-
-      for (i = 0; exif_data[i] != NULL; i++)
-        {
-          gchar    *interpreted_value = NULL;
-          gchar    *value             = NULL;
-          gboolean  interpreted       = FALSE;
+      gchar *encoded;
 
-          value = gexiv2_metadata_get_tag_string (gexiv2metadata, exif_data[i]);
-          interpreted_value = gexiv2_metadata_get_tag_interpreted_string (gexiv2metadata, exif_data[i]);
-          tag_type = gexiv2_metadata_get_tag_type (exif_data[i]);
-          attrib_type = gimp_attribute_get_value_type_from_string (tag_type);
-
-          interpreted = g_strcmp0 (value, interpreted_value);
-
-          if (!interpreted)
-            {
-              gint length;
-
-              length = strlen (interpreted_value);
-              if (length > 2048)
-                {
-                  g_free (interpreted_value);
-                  interpreted_value = g_strdup_printf ("(Size of value: %d)", length);
-                  interpreted = TRUE;
-                }
-            }
-
-          attribute = gimp_attribute_new_string (exif_data[i], value, attrib_type);
-          if (gimp_attribute_is_valid (attribute))
-            {
-              if (no_interpreted)
-                {
-                  if (interpreted)
-                    {
-                      gimp_attribute_set_interpreted_string (attribute, interpreted_value);
-                    }
-                }
-              gimp_metadata_add_attribute_to_list (metadata, attribute);
-            }
-          else
-            {
-              g_object_unref (attribute);
-            }
-
-          g_free (interpreted_value);
-          g_free (value);
-        }
-
-      g_strfreev (exif_data);
-
-      xmp_data = gexiv2_metadata_get_xmp_tags (gexiv2metadata);
-
-      for (i = 0; xmp_data[i] != NULL; i++)
-        {
-          gchar    *interpreted_value = NULL;
-          gchar    *value             = NULL;
-          gboolean  interpreted       = FALSE;
+      encoded = g_base64_encode ((const guchar *) value, strlen (value) + 1);
 
-          value = gexiv2_metadata_get_tag_string (gexiv2metadata, xmp_data[i]);
-          interpreted_value = gexiv2_metadata_get_tag_interpreted_string (gexiv2metadata, xmp_data[i]);
-          tag_type = gexiv2_metadata_get_tag_type (xmp_data[i]);
-          attrib_type = gimp_attribute_get_value_type_from_string (tag_type);
+      g_printerr ("Invalid UTF-8 in metadata value %s, encoding as base64: %s\n",
+                  name, encoded);
 
-          interpreted = g_strcmp0 (value, interpreted_value);
+      *base64 = TRUE;
 
-          attribute = gimp_attribute_new_string (xmp_data[i], value, attrib_type);
-
-          if (gimp_attribute_is_valid (attribute))
-            {
-              if (no_interpreted)
-                {
-                  if (interpreted)
-                    gimp_attribute_set_interpreted_string (attribute, interpreted_value);
-                }
-              gimp_metadata_add_attribute_to_list (metadata, attribute);
-            }
-          else
-            {
-              g_object_unref (attribute);
-            }
-
-          g_free (value);
-        }
-
-      g_strfreev (xmp_data);
-
-      iptc_data = gexiv2_metadata_get_iptc_tags (gexiv2metadata);
-
-      for (i = 0; iptc_data[i] != NULL; i++)
-        {
-          gchar    *interpreted_value = NULL;
-          gchar    *value             = NULL;
-          gboolean  interpreted       = FALSE;
-
-          value = gexiv2_metadata_get_tag_string (gexiv2metadata, iptc_data[i]);
-          interpreted_value = gexiv2_metadata_get_tag_interpreted_string (gexiv2metadata, iptc_data[i]);
-          tag_type = gexiv2_metadata_get_tag_type (iptc_data[i]);
-          attrib_type = gimp_attribute_get_value_type_from_string (tag_type);
-
-          interpreted = g_strcmp0 (value, interpreted_value);
-
-          attribute = gimp_attribute_new_string (iptc_data[i], value, attrib_type);
-          if (gimp_attribute_is_valid (attribute))
-            {
-              if (no_interpreted)
-                {
-                  if (interpreted)
-                    gimp_attribute_set_interpreted_string (attribute, interpreted_value);
-                }
-              gimp_metadata_add_attribute (metadata, attribute);
-            }
-          else
-            {
-              g_object_unref (attribute);
-            }
-
-          g_free (value);
-        }
-
-      g_strfreev (iptc_data);
+      return encoded;
     }
-}
-
-/**
- * gimp_metadata_add_list:
- *
- * @metadata  : a #GimpMetadata
- * @attribute : a #GimpAttribute
- *
- * stores the @attribute in the @metadata container
- *
- * Since : 2.10
- */
-void
-gimp_metadata_add_attribute_to_list (GimpMetadata    *metadata,
-                                     GimpAttribute   *attribute)
-{
-  const gchar         *name;
-  gchar               *lowchar;
-  GimpMetadataPrivate *priv;
-
-  g_return_if_fail (IS_GIMP_METADATA (metadata));
-  g_return_if_fail (GIMP_IS_ATTRIBUTE (attribute));
-
-  priv = GIMP_METADATA_GET_PRIVATE (metadata);
 
-  name = gimp_attribute_get_name (attribute);
+  *base64 = FALSE;
 
-  if (name)
-    {
-        lowchar = g_ascii_strdown (name, -1);
-
-      /* FIXME: really simply add? That means, that an older value is overwritten */
-
-      if (g_hash_table_insert (priv->attribute_table, (gpointer) g_strdup (lowchar), (gpointer) attribute))
-        {
-          gchar *sortable_tag;
-
-          sortable_tag = g_ascii_strdown (gimp_attribute_get_sortable_name (attribute), -1);
-
-          if (g_hash_table_insert (priv->sorted_to_attribute, (gpointer) g_strdup (sortable_tag), (gpointer) 
g_strdup (lowchar)))
-            {
-              priv->sorted_key_list = g_list_insert_sorted (priv->sorted_key_list,
-                                                            (gpointer) g_strdup (sortable_tag),
-                                                            (GCompareFunc) g_strcmp0);
-            }
-          else
-            {
-              g_hash_table_remove (priv->attribute_table, (gpointer) g_strdup (lowchar));
-            }
-
-          g_free (sortable_tag);
-        }
-      g_free (lowchar);
-    }
+  return g_markup_escape_text (value, -1);
 }
 
-/**
- * gimp_metadata_from_parent:
- * @metadata:  The metadata the gexiv2metadata will be added to, may be %NULL
- * @gexiv2metadata:  The metadata in gexiv2 format
- *
- * Converts the @gexiv2metadata retrieved from a file into
- * a #GimpMetadata object
- *
- * Return value: The #GimpMetadata object
- *
- * Since: GIMP 2.10
- */
-GimpAttribute *
-gimp_metadata_from_parent (GimpMetadata      *metadata,
-                           const gchar       *name)
+static void
+gimp_metadata_append_tag (GString     *string,
+                          const gchar *name,
+                          gchar       *value,
+                          gboolean     base64)
 {
-  const gchar               *tag_type;
-  gboolean                   no_interpreted    = TRUE; /*FIXME: No interpreted String possible */
-  gchar                     *interpreted_value = NULL;
-  gchar                     *value             = NULL;
-  gboolean                   interpreted       = FALSE;
-  GimpAttribute             *attribute         = NULL;
-  GimpAttributeValueType     attrib_type;
-  GExiv2Metadata            *gexiv2metadata;
-
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), NULL);
-
-  gexiv2metadata = GEXIV2_METADATA (metadata);
-
-  if (gexiv2_metadata_has_tag (gexiv2metadata, name))
+  if (value)
     {
-      value = gexiv2_metadata_get_tag_string (gexiv2metadata, name);
-      interpreted_value = gexiv2_metadata_get_tag_interpreted_string (gexiv2metadata, name);
-      tag_type = gexiv2_metadata_get_tag_type (name);
-      attrib_type = gimp_attribute_get_value_type_from_string (tag_type);
-
-      interpreted = g_strcmp0 (value, interpreted_value);
-
-      if (!interpreted)
-        {
-          gint length;
-
-          length = strlen (interpreted_value);
-          if (length > 2048)
-            {
-              g_free (interpreted_value);
-              interpreted_value = g_strdup_printf ("(Size of value: %d)", length);
-              interpreted = TRUE;
-            }
-        }
-
-      attribute = gimp_attribute_new_string (name, value, attrib_type);
-      if (gimp_attribute_is_valid (attribute))
+      if (base64)
         {
-          if (no_interpreted)
-            {
-              if (interpreted)
-                {
-                  gimp_attribute_set_interpreted_string (attribute, interpreted_value);
-                }
-            }
+          g_string_append_printf (string, "  <tag name=\"%s\" encoding=\"base64\">%s</tag>\n",
+                                  name, value);
         }
       else
         {
-          g_object_unref (attribute);
+          g_string_append_printf (string, "  <tag name=\"%s\">%s</tag>\n",
+                                  name, value);
         }
 
-      g_free (interpreted_value);
       g_free (value);
     }
-  return attribute;
-}
-
-/**
- * gimp_metadata_print:
- * @metadata:  The #GimpMetadata
- *
- * prints out information of metadata
- *
- * Since: GIMP 2.10
- */
-void
-gimp_metadata_print (GimpMetadata *metadata)
-{
-  gint            i;
-  GList          *key_list = NULL;
-
-  g_return_if_fail (IS_GIMP_METADATA (metadata));
-
-  gimp_metadata_from_gexiv2 (metadata);
-
-  i = 0;
-
-  for (key_list = metadata->priv->sorted_key_list; key_list; key_list = key_list->next)
-    {
-      const gchar    *tag;
-      const gchar    *interpreted;
-      gchar          *value;
-      GimpAttribute  *attribute;
-      gchar          *p_key = (gchar *) key_list->data;
-
-      attribute      = gimp_metadata_get_attribute_sorted (metadata, p_key);
-
-      if (! attribute)
-        continue;
-
-      i++;
-
-      tag = gimp_attribute_get_name (attribute);
-      value = gimp_attribute_get_string (attribute);
-      interpreted = gimp_attribute_get_interpreted_string (attribute);
-
-      g_print ("%p: %s\n%04d. Tag: %s\n\tValue:%s\n\tInterpreted value:%s\n", attribute, p_key, i, tag, 
value, interpreted);
-
-      if (value)
-        g_free (value);
-    }
 }
 
 /**
- * gimp_metadata_to_gexiv2metadata:
- * @metadata:  The #GimpMetadata
- * @gexiv2metadata:  The #GimpMetadata
- * @mime_type: the mime type of the image
+ * gimp_metadata_serialize:
+ * @metadata: A #GimpMetadata instance.
  *
- * Converts @metadata to @gexiv2metadata in gexiv2 format
+ * Serializes @metadata into an XML string that can later be deserialized
+ * using gimp_metadata_deserialize().
  *
- * Since: GIMP 2.10
- */
-//void
-//gimp_metadata_to_gexiv2metadata (GimpMetadata   *metadata,
-//                                 GimpMetadata   *gexivdata,
-//                                 const gchar    *mime_type)
-//{
-//  gchar          *o_packet            = NULL;
-//  gboolean        write_tag           = FALSE;
-//  gboolean        namespace           = FALSE;
-//  gboolean        check_mime          = TRUE;
-//  gboolean        support_exif;
-//  gboolean        support_xmp;
-//  gboolean        support_iptc;
-//  GSList         *xmp_structure_list  = NULL;
-//  GList          *key_list            = NULL;
-//  gint            i;
-//  GExiv2Metadata *gexiv2metadata;
-//
-//  g_return_if_fail (IS_GIMP_METADATA (metadata));
-//
-//  gexiv2metadata = GEXIV2_METADATA(gexivdata);
-//
-//  for (i = 0; i < G_N_ELEMENTS (namespaces_table); i++)
-//    {
-//      struct Namespaces n_space = namespaces_table[i];
-//      gexiv2_metadata_register_xmp_namespace (n_space.namespace_URI, n_space.namespace_name);
-//    }
-//
-//  support_exif = gexiv2_metadata_get_supports_exif (gexiv2metadata);
-//  support_xmp  = gexiv2_metadata_get_supports_xmp  (gexiv2metadata);
-//  support_iptc = gexiv2_metadata_get_supports_iptc (gexiv2metadata);
-//
-//  for (key_list = metadata->priv->sorted_key_list; key_list; key_list = key_list->next)
-//    {
-//      const gchar              *tag;
-//      const gchar              *ns_name;
-//      gchar                    *p_key = (gchar *) key_list->data;
-//      gchar                    *value         = NULL;
-//      gchar                    *category      = NULL;
-//      gboolean                  is_xmp        = FALSE;
-//      gboolean                  has_structure = FALSE;
-//      GimpAttribute            *attribute;
-//      GimpAttributeValueType    tag_value_type;
-//
-//      write_tag      = FALSE;
-//      namespace      = FALSE;
-//
-//      attribute      = gimp_metadata_get_attribute_sorted (metadata, p_key);
-//
-//      if (! attribute)
-//        continue;
-//
-//      tag            = gimp_attribute_get_name (attribute);
-//      has_structure  = gimp_attribute_has_structure (attribute);
-//
-//      if (mime_type)
-//        check_mime = gimp_metadata_is_tag_supported (tag, mime_type);
-//
-//      if (check_mime)
-//        {
-//          gchar *t_packet       = NULL;
-//
-//          tag_value_type = gimp_attribute_get_value_type (attribute);
-//          value = gimp_attribute_get_string (attribute);
-//          category = g_ascii_strdown (gimp_attribute_get_attribute_type (attribute), -1);
-//
-//          if (tag && value && category)
-//            {
-//              if(! g_strcmp0 (category, "exif") && support_exif)
-//                {
-//                  write_tag = TRUE;
-//                }
-//              else if(! g_strcmp0 (category, "xmp") && support_xmp)
-//                {
-//                  write_tag = TRUE;
-//                  is_xmp    = TRUE;
-//
-//                  namespace = gimp_attribute_is_new_namespace (attribute);
-//
-//                  if (namespace)
-//                    {
-//                      write_tag = FALSE;
-//
-//                      ns_name = gimp_attribute_get_attribute_ifd (attribute);
-//
-//                      for (i = 0; i < G_N_ELEMENTS (namespaces_table); i++)
-//                        {
-//                          struct Namespaces n_space = namespaces_table[i];
-//                          if(! g_strcmp0 (ns_name, n_space.namespace_name))
-//                            {
-//                              write_tag = TRUE;
-//                              break;
-//                            }
-//                        }
-//                    }
-//
-//                  if (write_tag && has_structure)
-//                    {
-//                      gboolean                    success = TRUE;
-//                      GSList                     *structure;
-//                      GSList                     *list;
-//                      GimpAttributeStructureType  structure_type;
-//
-//                      structure      = gimp_attribute_get_attribute_structure (attribute);
-//                      structure_type = gimp_attribute_get_structure_type (attribute);
-//
-//                      for (list = structure; list; list = list->next)
-//                        {
-//                          const gchar   *structure_element = (const gchar*) list->data;
-//                          gboolean       has_tag = gexiv2_metadata_has_tag (gexiv2metadata, 
structure_element);
-//
-//                          if (!has_tag && ! has_xmp_structure (xmp_structure_list, structure_element))
-//                            {
-//                              switch (structure_type)
-//                              {
-//                                case STRUCTURE_TYPE_ALT:
-//                                  success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, 
structure_element, GEXIV2_STRUCTURE_XA_ALT); /*start block*/
-//                                  break;
-//                                case STRUCTURE_TYPE_BAG:
-//                                  success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, 
structure_element, GEXIV2_STRUCTURE_XA_BAG); /*start block*/
-//                                  break;
-//                                case STRUCTURE_TYPE_SEQ:
-//                                  success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, 
structure_element, GEXIV2_STRUCTURE_XA_SEQ); /*start block*/
-//                                  break;
-//                                default:
-//                                  success = FALSE;
-//                                  break;
-//                              }
-//
-//                              if (success)
-//                                xmp_structure_list = g_slist_prepend (xmp_structure_list, 
(gpointer)structure_element);
-//                            }
-//                        }
-//                    }
-//                }
-//              else if(! g_strcmp0 (category, "iptc") && support_iptc)
-//                {
-//                  write_tag = TRUE;
-//                }
-//              else
-//                {
-//                  write_tag = FALSE;
-//                }
-//
-//              if (write_tag)
-//                {
-//                  switch (tag_value_type)
-//                  {
-//                    case TYPE_INVALID:
-//                      break;
-//                    case TYPE_LONG:
-//                    case TYPE_SLONG:
-//                    case TYPE_FLOAT:
-//                    case TYPE_DOUBLE:
-//                    case TYPE_SHORT:
-//                    case TYPE_SSHORT:
-//                    case TYPE_DATE:
-//                    case TYPE_TIME:
-//                    case TYPE_ASCII:
-//                    case TYPE_UNICODE:
-//                    case TYPE_BYTE:
-//                    case TYPE_RATIONAL:
-//                    case TYPE_SRATIONAL:
-//                      {
-//                        gexiv2_metadata_set_tag_string (gexiv2metadata, tag, value);
-//                      }
-//                      break;
-//                    case TYPE_MULTIPLE:
-//                      {
-//                        GValue h;
-//                        gchar **values;
-//
-//                        h = gimp_attribute_get_value (attribute);
-//                        values = (gchar **) g_value_get_boxed (&h);
-//                        gexiv2_metadata_set_tag_multiple (gexiv2metadata, tag, (const gchar **) values);
-//                        g_strfreev  (values);
-//                      }
-//                      break;
-//                    case TYPE_UNKNOWN:
-//                    default:
-//                      break;
-//
-//                  }
-//
-//                  if (is_xmp)
-//                    {
-//                      t_packet = gexiv2_metadata_generate_xmp_packet (gexiv2metadata, 
GEXIV2_USE_COMPACT_FORMAT | GEXIV2_OMIT_ALL_FORMATTING, 0);
-//
-//                      if (! g_strcmp0 (t_packet, o_packet))
-//                        {
-//                          gexiv2_metadata_clear_tag (gexiv2metadata, tag);
-//                          g_print ("cleared to gexiv2metadata:\n%s, %s\n", tag, value);
-//                        }
-//                      else
-//                        {
-//                          o_packet = g_strdup (t_packet);
-//                        }
-//                    }
-//                }
-//            }
-//
-//          if (t_packet)
-//            g_free (t_packet);
-//          if (value)
-//            g_free (value);
-//          if (category)
-//            g_free (category);
-//       }
-//    }
-//
-//  if (o_packet)
-//    g_free (o_packet);
-//  if (xmp_structure_list)
-//    g_slist_free (xmp_structure_list);
-//}
-
-/**
- * gimp_metadata_to_gexiv2:
- * @metadata:  The #GimpMetadata
- *
- * Converts @metadata to @gexiv2metadata packet
+ * Return value: The serialized XML string.
  *
- * Since: GIMP 2.10
- */
-void
-gimp_metadata_to_gexiv2 (GimpMetadata   *metadata)
-{
-  gchar          *o_packet            = NULL;
-  gboolean        write_tag           = FALSE;
-  gboolean        namespace           = FALSE;
-  gboolean        support_exif;
-  gboolean        support_xmp;
-  gboolean        support_iptc;
-  GSList         *xmp_structure_list  = NULL;
-  GList          *key_list            = NULL;
-  gint            i;
-  GExiv2Metadata *gexiv2metadata;
-
-  g_return_if_fail (IS_GIMP_METADATA (metadata));
-
-  gexiv2metadata = GEXIV2_METADATA(metadata);
-
-  for (i = 0; i < G_N_ELEMENTS (namespaces_table); i++)
-    {
-      struct Namespaces n_space = namespaces_table[i];
-      gexiv2_metadata_register_xmp_namespace (n_space.namespace_URI, n_space.namespace_name);
-    }
-
-  support_exif = gexiv2_metadata_get_supports_exif (gexiv2metadata);
-  support_xmp  = gexiv2_metadata_get_supports_xmp  (gexiv2metadata);
-  support_iptc = gexiv2_metadata_get_supports_iptc (gexiv2metadata);
-
-  for (key_list = metadata->priv->sorted_key_list; key_list; key_list = key_list->next)
-    {
-      const gchar              *tag;
-      const gchar              *ns_name;
-      gchar                    *p_key = (gchar *) key_list->data;
-      gchar                    *value         = NULL;
-      gchar                    *category      = NULL;
-      gboolean                  is_xmp        = FALSE;
-      gboolean                  has_structure = FALSE;
-      gchar                    *t_packet      = NULL;
-      GimpAttribute            *attribute;
-      GimpAttributeValueType    tag_value_type;
-
-      write_tag      = FALSE;
-      namespace      = FALSE;
-
-      attribute      = gimp_metadata_get_attribute_sorted (metadata, p_key);
-
-      if (! attribute)
-        continue;
-
-      tag            = gimp_attribute_get_name (attribute);
-      has_structure  = gimp_attribute_has_structure (attribute);
-
-      tag_value_type = gimp_attribute_get_value_type (attribute);
-      value = gimp_attribute_get_string (attribute);
-      category = g_ascii_strdown (gimp_attribute_get_attribute_type (attribute), -1);
-
-      if (tag && value && category)
-        {
-          if(! g_strcmp0 (category, "exif") && support_exif)
-            {
-              write_tag = TRUE;
-            }
-          else if(! g_strcmp0 (category, "xmp") && support_xmp)
-            {
-              write_tag = TRUE;
-              is_xmp    = TRUE;
-
-              namespace = gimp_attribute_is_new_namespace (attribute);
-
-              if (namespace)
-                {
-                  write_tag = FALSE;
-
-                  ns_name = gimp_attribute_get_attribute_ifd (attribute);
-
-                  for (i = 0; i < G_N_ELEMENTS (namespaces_table); i++)
-                    {
-                      struct Namespaces n_space = namespaces_table[i];
-                      if(! g_strcmp0 (ns_name, n_space.namespace_name))
-                        {
-                          write_tag = TRUE;
-                          break;
-                        }
-                    }
-                }
-
-              if (write_tag && has_structure)
-                {
-                  gboolean                    success = TRUE;
-                  GSList                     *structure;
-                  GSList                     *list;
-                  GimpAttributeStructureType  structure_type;
-
-                  structure      = gimp_attribute_get_attribute_structure (attribute);
-                  structure_type = gimp_attribute_get_structure_type (attribute);
-
-                  for (list = structure; list; list = list->next)
-                    {
-                      const gchar   *structure_element = (const gchar*) list->data;
-                      gboolean       has_tag = gexiv2_metadata_has_tag (gexiv2metadata, structure_element);
-
-                      if (!has_tag && ! has_xmp_structure (xmp_structure_list, structure_element))
-                        {
-                          switch (structure_type)
-                          {
-                            case STRUCTURE_TYPE_ALT:
-                              success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, 
structure_element, GEXIV2_STRUCTURE_XA_ALT); /*start block*/
-                              break;
-                            case STRUCTURE_TYPE_BAG:
-                              success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, 
structure_element, GEXIV2_STRUCTURE_XA_BAG); /*start block*/
-                              break;
-                            case STRUCTURE_TYPE_SEQ:
-                              success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, 
structure_element, GEXIV2_STRUCTURE_XA_SEQ); /*start block*/
-                              break;
-                            default:
-                              success = FALSE;
-                              break;
-                          }
-
-                          if (success)
-                            xmp_structure_list = g_slist_prepend (xmp_structure_list, 
(gpointer)structure_element);
-                        }
-                    }
-                }
-            }
-          else if(! g_strcmp0 (category, "iptc") && support_iptc)
-            {
-              write_tag = TRUE;
-            }
-          else
-            {
-              write_tag = FALSE;
-            }
-
-          if (write_tag)
-            {
-              switch (tag_value_type)
-              {
-                case TYPE_INVALID:
-                  break;
-                case TYPE_LONG:
-                case TYPE_SLONG:
-                case TYPE_FLOAT:
-                case TYPE_DOUBLE:
-                case TYPE_SHORT:
-                case TYPE_SSHORT:
-                case TYPE_DATE:
-                case TYPE_TIME:
-                case TYPE_ASCII:
-                case TYPE_UNICODE:
-                case TYPE_BYTE:
-                case TYPE_RATIONAL:
-                case TYPE_SRATIONAL:
-                  {
-                    gexiv2_metadata_set_tag_string (gexiv2metadata, tag, value);
-                  }
-                  break;
-                case TYPE_MULTIPLE:
-                  {
-                    GValue h;
-                    gchar **values;
-
-                    h = gimp_attribute_get_value (attribute);
-                    values = (gchar **) g_value_get_boxed (&h);
-                    gexiv2_metadata_set_tag_multiple (gexiv2metadata, tag, (const gchar **) values);
-                    g_strfreev  (values);
-                  }
-                  break;
-                case TYPE_UNKNOWN:
-                default:
-                  break;
-
-              }
-
-              if (is_xmp)
-                {
-                  /* XMP packet for testing
-                   * There is no way to check, if storing of tags were successful, because gexiv2 has no 
error handling
-                   * The only way is to compare a xpm packet before and after the storing process. If they 
are equal, the storing was not successful
-                   * so the stored tag must be deleted, otherwise the whole xmp data is corrupt. */
-                  t_packet = gexiv2_metadata_generate_xmp_packet (gexiv2metadata, GEXIV2_USE_COMPACT_FORMAT 
| GEXIV2_OMIT_ALL_FORMATTING, 0);
-
-                  if (! g_strcmp0 (t_packet, o_packet))
-                    {
-                      gexiv2_metadata_clear_tag (gexiv2metadata, tag);
-                      g_print ("cleared to gexiv2metadata:\n%s, %s\n", tag, value);
-                    }
-                  else
-                    {
-                      o_packet = g_strdup (t_packet);
-                    }
-                }
-            }
-        }
-
-      if (t_packet)
-        g_free (t_packet);
-      if (value)
-        g_free (value);
-      if (category)
-        g_free (category);
-    }
-
-  if (o_packet)
-    g_free (o_packet);
-  if (xmp_structure_list)
-    g_slist_free (xmp_structure_list);
-}
-
-/**
- * gimp_metadata_to_parent:
- * @metadata:  The #GimpMetadata
- * @gexiv2metadata:  The #GimpMetadata
- * @mime_type: the mime type of the image
- *
- * Converts @metadata to @gexiv2metadata in gexiv2 format
- *
- * Since: GIMP 2.10
+ * Since: 2.10
  */
-void
-gimp_metadata_to_parent (GimpMetadata    *metadata,
-                         GimpAttribute   *attribute)
+gchar *
+gimp_metadata_serialize (GimpMetadata *metadata)
 {
-  gchar                    *o_packet            = NULL;
-  gboolean                  write_tag           = FALSE;
-  gboolean                  namespace           = FALSE;
-  gint                      i;
-  GExiv2Metadata           *gexiv2metadata;
-  const gchar              *tag;
-  const gchar              *ns_name;
-  gchar                    *value               = NULL;
-  gchar                    *category            = NULL;
-  gboolean                  is_xmp              = FALSE;
-  gboolean                  has_structure       = FALSE;
-  GimpAttributeValueType    tag_value_type;
-  gchar                    *t_packet            = NULL;
-  GimpMetadataPrivate      *priv;
-
-  g_return_if_fail (IS_GIMP_METADATA (metadata));
-  g_return_if_fail (GIMP_IS_ATTRIBUTE (attribute));
-
-  gexiv2metadata = GEXIV2_METADATA (metadata);
-  priv = GIMP_METADATA_GET_PRIVATE (metadata);
-  write_tag      = FALSE;
-  namespace      = FALSE;
-
-  tag            = gimp_attribute_get_name (attribute);
-  has_structure  = gimp_attribute_has_structure (attribute);
-
-
-  tag_value_type = gimp_attribute_get_value_type (attribute);
-  value = gimp_attribute_get_string (attribute);
-  category = g_ascii_strdown (gimp_attribute_get_attribute_type (attribute), -1);
-
-//  if (g_str_has_prefix (tag, "Xmp"))
-//    {
-//      g_print ("found xmp: %s\n", tag);
-//    }
-//
-//  if (g_str_has_prefix (tag, "Xmp.xmpMM.History"))
-//    {
-//      g_print ("found struct: %s\n", tag);
-//    }
-
-
-  if (tag && value && category)
-    {
-      if(! g_strcmp0 (category, "exif"))
-        {
-          write_tag = TRUE;
-        }
-      else if(! g_strcmp0 (category, "xmp"))
-        {
-          write_tag = TRUE;
-          is_xmp    = TRUE;
-
-          /* XMP packet for testing before adding tag
-           * There is no way to check, if storing of tags were successful, because gexiv2 has no error 
handling
-           * The only way is to compare a xpm packet before and after the storing process. If they are 
equal, the storing was not successful
-           * so the stored tag must be deleted, otherwise the whole xmp data is corrupt. */
-          o_packet = gexiv2_metadata_generate_xmp_packet (gexiv2metadata, GEXIV2_USE_COMPACT_FORMAT | 
GEXIV2_OMIT_ALL_FORMATTING, 0);
-
-          namespace = gimp_attribute_is_new_namespace (attribute);
+  GString  *string;
+  gchar   **exif_data = NULL;
+  gchar   **iptc_data = NULL;
+  gchar   **xmp_data  = NULL;
+  gchar    *value;
+  gchar    *escaped;
+  gboolean  base64;
+  gint      i;
 
-          if (namespace)
-            {
-              write_tag = FALSE;
-
-              ns_name = gimp_attribute_get_attribute_ifd (attribute);
-
-              for (i = 0; i < G_N_ELEMENTS (namespaces_table); i++)
-                {
-                  struct Namespaces n_space = namespaces_table[i];
-                  if(! g_strcmp0 (ns_name, n_space.namespace_name))
-                    {
-                      write_tag = TRUE;
-                      break;
-                    }
-                }
-            }
+  g_return_val_if_fail (GEXIV2_IS_METADATA (metadata), NULL);
 
-          if (write_tag && has_structure)
-            {
-              gboolean                    success = TRUE;
-              GSList                     *structure;
-              GSList                     *list;
-              GimpAttributeStructureType  structure_type;
-
-              structure      = gimp_attribute_get_attribute_structure (attribute);
-              structure_type = gimp_attribute_get_structure_type (attribute);
-
-              for (list = structure; list; list = list->next)
-                {
-                  const gchar   *structure_element = (const gchar*) list->data;
-                  gboolean       has_tag = gexiv2_metadata_has_tag (gexiv2metadata, structure_element);
-
-                  if (!has_tag && ! has_xmp_structure (priv->xmp_structure_list, structure_element))
-                    {
-                      switch (structure_type)
-                      {
-                        case STRUCTURE_TYPE_ALT:
-                          success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, structure_element, 
GEXIV2_STRUCTURE_XA_ALT); /*start block*/
-                          break;
-                        case STRUCTURE_TYPE_BAG:
-                          success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, structure_element, 
GEXIV2_STRUCTURE_XA_BAG); /*start block*/
-                          break;
-                        case STRUCTURE_TYPE_SEQ:
-                          success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, structure_element, 
GEXIV2_STRUCTURE_XA_SEQ); /*start block*/
-                          break;
-                        default:
-                          success = FALSE;
-                          break;
-                      }
-
-                      if (success)
-                        priv->xmp_structure_list = g_slist_prepend (priv->xmp_structure_list, 
(gpointer)structure_element);
-                    }
-                }
-            }
-        }
-      else if(! g_strcmp0 (category, "iptc"))
-        {
-          write_tag = TRUE;
-        }
-      else
-        {
-          write_tag = FALSE;
-        }
-
-      if (write_tag)
-        {
-          switch (tag_value_type)
-          {
-            case TYPE_INVALID:
-              break;
-            case TYPE_LONG:
-            case TYPE_SLONG:
-            case TYPE_FLOAT:
-            case TYPE_DOUBLE:
-            case TYPE_SHORT:
-            case TYPE_SSHORT:
-            case TYPE_DATE:
-            case TYPE_TIME:
-            case TYPE_ASCII:
-            case TYPE_UNICODE:
-            case TYPE_BYTE:
-            case TYPE_RATIONAL:
-            case TYPE_SRATIONAL:
-              {
-                gexiv2_metadata_set_tag_string (gexiv2metadata, tag, value);
-              }
-              break;
-            case TYPE_MULTIPLE:
-              {
-                GValue h;
-                gchar **values;
-
-                h = gimp_attribute_get_value (attribute);
-                values = (gchar **) g_value_get_boxed (&h);
-                gexiv2_metadata_set_tag_multiple (gexiv2metadata, tag, (const gchar **) values);
-                g_strfreev  (values);
-              }
-              break;
-            case TYPE_UNKNOWN:
-            default:
-              break;
-
-          }
-
-          if (is_xmp)
-            {
-              /* XMP packet for testing after adding tag */
-              t_packet = gexiv2_metadata_generate_xmp_packet (gexiv2metadata, GEXIV2_USE_COMPACT_FORMAT | 
GEXIV2_OMIT_ALL_FORMATTING, 0);
-
-              if (! g_strcmp0 (t_packet, o_packet))
-                {
-                  gexiv2_metadata_clear_tag (gexiv2metadata, tag);
-                  g_print ("cleared to gexiv2metadata:\n%s, %s\n", tag, value);
-                }
-            }
-        }
-    }
-
-  if (t_packet)
-    g_free (t_packet);
-  if (value)
-    g_free (value);
-  if (category)
-    g_free (category);
-  if (o_packet)
-    g_free (o_packet);
-}
-
-/**
- * gimp_metadata_to_xmp_packet: ToDo handle xmp-packet
- * @metadata:  The #GimpMetadata
- * @mime_type :  a mime_type
- *
- * Converts @metadata to a xmp packet
- * It looks like an ugly hack, but let
- * gexiv2/exiv2 do all the hard work.
- *
- * Return value: a #gchar*, representing a xml packet.
- *
- * Since: GIMP 2.10
- */
-const gchar *
-gimp_metadata_to_xmp_packet (GimpMetadata *metadata,
-                             const gchar *mime_type)
+  string = g_string_new (NULL);
 
-{
-  gint            i;
-  const gchar    *packet_string;
-  gchar          *o_packet           = NULL;
-  gboolean        check_mime         = TRUE;
-  gboolean        write_tag          = FALSE;
-  gboolean        namespace          = FALSE;
-  gboolean        support_exif;
-  gboolean        support_xmp;
-  gboolean        support_iptc;
-  GExiv2Metadata *gexiv2metadata;
-  GSList         *xmp_structure_list = NULL;
-  GList          *key_list           = NULL;
-
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), NULL);
-
-  gimp_metadata_from_gexiv2 (metadata);
-
-  gexiv2metadata = gimp_metadata_new_gexiv2metadata ();
-
-  for (i = 0; i < G_N_ELEMENTS (namespaces_table); i++)
-    {
-      struct Namespaces n_space = namespaces_table[i];
-      gexiv2_metadata_register_xmp_namespace (n_space.namespace_URI, n_space.namespace_name);
-    }
+  g_string_append (string, "<?xml version='1.0' encoding='UTF-8'?>\n");
+  g_string_append (string, "<metadata>\n");
 
-  support_exif = gexiv2_metadata_get_supports_exif (gexiv2metadata);
-  support_xmp  = gexiv2_metadata_get_supports_xmp  (gexiv2metadata);
-  support_iptc = gexiv2_metadata_get_supports_iptc (gexiv2metadata);
+  exif_data = gexiv2_metadata_get_exif_tags (metadata);
 
-  for (key_list = metadata->priv->sorted_key_list; key_list; key_list = key_list->next)
+  if (exif_data)
     {
-      gchar          *p_key = (gchar *) key_list->data;
-
-      const gchar            *tag;
-      const gchar            *attribute_tag;
-      const gchar            *ns_name;
-      gchar                  *new_tag         = NULL;
-      gchar                  *value           = NULL;
-      gchar                  *category        = NULL;
-      gboolean                has_structure;
-      gboolean                temp_attribute  = FALSE;
-      GimpAttribute          *attribute;
-      GimpAttributeValueType  tag_value_type;
-
-      write_tag     = FALSE;
-      namespace = FALSE;
-
-      attribute = gimp_metadata_get_attribute_sorted (metadata, p_key);
-
-      if (! attribute)
-        continue;
-
-      tag            = gimp_attribute_get_name (attribute);
-      attribute_tag  = gimp_attribute_get_attribute_tag (attribute);
-      has_structure  = gimp_attribute_has_structure (attribute);
-
-      if (mime_type)
-        check_mime = gimp_metadata_is_tag_supported (tag, mime_type);
-
-      if (check_mime)
+      for (i = 0; exif_data[i] != NULL; i++)
         {
-          gchar *sec_tag        = NULL;
-          gchar *t_packet       = NULL;
-
-          tag_value_type = gimp_attribute_get_value_type (attribute);
-          value = gimp_attribute_get_string (attribute);
-          category = g_ascii_strdown (gimp_attribute_get_attribute_type (attribute), -1);
-
-          if (tag && value && category)
-            {
-              if(! g_strcmp0 (category, "exif") && support_exif)
-                {
-                  new_tag = g_strdup_printf ("Xmp.exif.%s", attribute_tag);
-
-                  write_tag = TRUE;
-
-//                  /* Now for some specialities */
-//                  if (! g_strcmp0 (new_tag, "Xmp.exif.ISOSpeedRatings"))
-//                    {
-//                      g_print ("ungültig\n");
-//                       attribute = gimp_attribute_new_string ("Xmp.exif.ISOSpeedRatings", value, 
TYPE_ASCII);
-//                      if (attribute)
-//                        {
-//                          temp_attribute = TRUE;
-//                          tag_value_type = TYPE_ASCII;
-//                        }
-//                      else
-//                        {
-//                          write_tag = FALSE;
-//                        }
-//                    }
-                }
-              else if(! g_strcmp0 (category, "xmp") && support_xmp)
-                {
-                  new_tag = g_strdup_printf ("%s", tag);
-
-                  write_tag = TRUE;
-
-                  namespace = gimp_attribute_is_new_namespace (attribute);
-
-                  if (namespace)
-                    {
-                      write_tag = FALSE;
-
-                      ns_name = gimp_attribute_get_attribute_ifd (attribute);
-
-                      for (i = 0; i < G_N_ELEMENTS (namespaces_table); i++)
-                        {
-                          struct Namespaces n_space = namespaces_table[i];
-                          if(! g_strcmp0 (ns_name, n_space.namespace_name))
-                            {
-                              write_tag = TRUE;
-                              break;
-                            }
-                        }
-                    }
-
-                  if (write_tag && has_structure)
-                    {
-                      gboolean                    success = TRUE;
-                      GSList                     *structure;
-                      GSList                     *list;
-                      GimpAttributeStructureType  structure_type;
-
-                      structure      = gimp_attribute_get_attribute_structure (attribute);
-                      structure_type = gimp_attribute_get_structure_type (attribute);
-
-                      for (list = structure; list; list = list->next)
-                        {
-                          const gchar   *structure_element = (const gchar*) list->data;
-                          gboolean       has_tag = gexiv2_metadata_has_tag (gexiv2metadata, 
structure_element);
-
-                          if (!has_tag && ! has_xmp_structure (xmp_structure_list, structure_element))
-                            {
-                              switch (structure_type)
-                              {
-                                case STRUCTURE_TYPE_ALT:
-                                  success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, 
structure_element, GEXIV2_STRUCTURE_XA_ALT); /*start block*/
-                                  break;
-                                case STRUCTURE_TYPE_BAG:
-                                  success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, 
structure_element, GEXIV2_STRUCTURE_XA_BAG); /*start block*/
-                                  break;
-                                case STRUCTURE_TYPE_SEQ:
-                                  success = gexiv2_metadata_set_xmp_tag_struct (gexiv2metadata, 
structure_element, GEXIV2_STRUCTURE_XA_SEQ); /*start block*/
-                                  break;
-                                default:
-                                  success = FALSE;
-                                  break;
-                              }
-
-                              if (success)
-                                xmp_structure_list = g_slist_prepend (xmp_structure_list, 
(gpointer)structure_element);
-                            }
-                        }
-                    }
-                }
-              else if(! g_strcmp0 (category, "iptc") && support_iptc)
-                {
-                  new_tag = g_strdup_printf ("Xmp.iptc.%s", attribute_tag);
-                  sec_tag = g_strdup_printf ("Xmp.iptcExt.%s", attribute_tag);
-                  write_tag = TRUE;
-                }
-              else
-                {
-                  write_tag = FALSE;
-                }
-
-              if (write_tag)
-                {
-                  switch (tag_value_type)
-                  {
-                    case TYPE_INVALID:
-                      break;
-                    case TYPE_LONG:
-                    case TYPE_SLONG:
-                    case TYPE_FLOAT:
-                    case TYPE_DOUBLE:
-                    case TYPE_SHORT:
-                    case TYPE_SSHORT:
-                    case TYPE_DATE:
-                    case TYPE_TIME:
-                    case TYPE_ASCII:
-                    case TYPE_UNICODE:
-                    case TYPE_BYTE:
-                    case TYPE_RATIONAL:
-                    case TYPE_SRATIONAL:
-                      {
-                        gexiv2_metadata_set_tag_string (gexiv2metadata, new_tag, value);
-                        if (sec_tag)
-                          {
-                            gexiv2_metadata_set_tag_string (gexiv2metadata, sec_tag, value);
-                            g_free (sec_tag);
-                          }
-
-                      }
-                      break;
-                    case TYPE_MULTIPLE:
-                      {
-                        GValue h;
-                        gchar **values;
-
-                        h = gimp_attribute_get_value (attribute);
-                        values = (gchar **) g_value_get_boxed (&h);
-                        gexiv2_metadata_set_tag_multiple (gexiv2metadata, new_tag, (const gchar **) values);
-                        if (sec_tag)
-                          {
-                            gexiv2_metadata_set_tag_multiple (gexiv2metadata, sec_tag, (const gchar **) 
values);
-                            g_free (sec_tag);
-                          }
-                        g_strfreev  (values);
-                      }
-                      break;
-                    case TYPE_UNKNOWN:
-                    default:
-                      break;
-
-                  }
-
-                  t_packet = gexiv2_metadata_generate_xmp_packet (gexiv2metadata, GEXIV2_USE_COMPACT_FORMAT 
| GEXIV2_OMIT_ALL_FORMATTING, 0);
-
-                  if (! t_packet || ! g_strcmp0 (t_packet, o_packet))
-                    {
-                      gexiv2_metadata_clear_tag (gexiv2metadata, new_tag);
-                    }
-                  else
-                    {
-                      o_packet = g_strdup (t_packet);
-                    }
-                }
-            }
-
-          if (t_packet)
-            g_free (t_packet);
-          if (value)
-            g_free (value);
-          if (category)
-            g_free (category);
-          if (new_tag)
-            g_free (new_tag);
-
-          if (temp_attribute)
-            g_object_unref (attribute);
-       }
-    }
-
-  if (o_packet)
-    g_free (o_packet);
-  if (xmp_structure_list)
-    g_slist_free (xmp_structure_list);
-
-  packet_string = gexiv2_metadata_generate_xmp_packet (gexiv2metadata, GEXIV2_USE_COMPACT_FORMAT | 
GEXIV2_WRITE_ALIAS_COMMENTS, 0);
-  return packet_string;
-}
-
-/**
- * gimp_metadata_has_tag_type:
- * @metadata:  The metadata
- * @tag_type:  The #GimpAttributeTagType to test
- *
- * tests, if @metadata contains at least one tag of @tag_type
- *
- * Return value: TRUE if found, FALSE otherwise
- *
- * Since: GIMP 2.10
- */
-gboolean
-gimp_metadata_has_tag_type (GimpMetadata         *metadata,
-                            GimpAttributeTagType  tag_type)
-{
-  GHashTableIter  iter;
-  gpointer        p_key, p_value;
-
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), FALSE);
-
-  gimp_metadata_from_gexiv2 (metadata);
-
-  g_hash_table_iter_init (&iter, metadata->priv->attribute_table);
-
-  while (g_hash_table_iter_next (&iter, &p_key, &p_value))
-    {
-      GimpAttribute         *attribute;
-
-      attribute = (GimpAttribute *) p_value;
-
-      if (gimp_attribute_get_tag_type (attribute) == tag_type)
-        return TRUE;
-
-    }
-  return FALSE;
-}
-
-GList *
-gimp_metadata_iter_init (GimpMetadata *metadata, GList **iter)
-{
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), NULL);
-
-  gimp_metadata_from_gexiv2 (metadata);
-
-  *iter = metadata->priv->sorted_key_list;
-  iter_initialized = TRUE;
-
-  return metadata->priv->sorted_key_list;
-}
-
-gboolean
-gimp_metadata_iter_next (GimpMetadata *metadata, GimpAttribute **attribute, GList **prev)
-{
-  gchar         *sorted;
-  GList         *tmp;
-
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), FALSE);
-
-  *attribute = NULL;
-
-  if (iter_initialized)
-    {
-      tmp = g_list_first (*prev);
-    }
-  else
-    {
-      tmp = g_list_next (*prev);
-    }
-
-  if (tmp)
-    {
-      *prev = tmp;
-      sorted = (gchar *) tmp->data;
-
-      *attribute = gimp_metadata_get_attribute_sorted (metadata, sorted);
-    }
-
-  iter_initialized = FALSE;
-
-  if (*attribute)
-    return TRUE;
-  else
-    return FALSE;
-
-}
-
-/**
- * gimp_metadata_error_quark:
- *
- * Return value: #GQuark
- *
- * Since: GIMP 2.10
- */
-static GQuark
-gimp_metadata_error_quark (void)
-{
-  static GQuark quark = 0;
-
-  if (G_UNLIKELY (quark == 0))
-    quark = g_quark_from_static_string ("gimp-metadata-error-quark");
-
-  return quark;
-}
-
-/**
- * gimp_metadata_deserialize_error:
- *
- * Error while parsing
- *
- * Since: GIMP 2.10
- */
-static void
-gimp_metadata_deserialize_error (GMarkupParseContext *context,
-                                   GError              *error,
-                                   gpointer             user_data)
-{
-  g_printerr ("XML parse error: %s\n", error->message);
-}
+          value = gexiv2_metadata_get_tag_string (metadata, exif_data[i]);
+          escaped = gimp_metadata_escape (exif_data[i], value, &base64);
+          g_free (value);
 
-/**
- * gimp_metadata_name_to_value:
- *
- * @attribute_names  : #gchar **
- * @attribute_values : #gchar **
- * @name             : #gchar *
- *
- * searches for values in @attribute_values by a given @name (parsing xml)
- *
- * Since: GIMP 2.10
- */
-static const gchar*
-gimp_metadata_name_to_value (const gchar **attribute_names,
-                             const gchar **attribute_values,
-                             const gchar  *name)
-{
-  while (*attribute_names)
-    {
-      if (! strcmp (*attribute_names, name))
-        {
-          return *attribute_values;
+          gimp_metadata_append_tag (string, exif_data[i], escaped, base64);
         }
 
-      attribute_names++;
-      attribute_values++;
+      g_strfreev (exif_data);
     }
 
-  return NULL;
-}
-
-/**
- * gimp_metadata_deserialize_start_element:
- *
- * @context           : #GMarkupParseContext
- * @element_name      : #gchar *
- * @attribute_names   : #gchar **
- * @attribute_values  : #gchar **
- * @user_data         : #gpointer to #GimpMetadataParseData struct
- * @error             : #GError **
- *
- * start of a tag (parsing xml)
- *
- * Since: GIMP 2.10
- */
-static void
-gimp_metadata_deserialize_start_element (GMarkupParseContext *context,
-                                           const gchar         *element_name,
-                                           const gchar        **attribute_names,
-                                           const gchar        **attribute_values,
-                                           gpointer             user_data,
-                                           GError             **error)
-{
-  GimpMetadataParseData *parse_data = user_data;
+  xmp_data = gexiv2_metadata_get_xmp_tags (metadata);
 
-  if (! strcmp (element_name, "tag"))
+  if (xmp_data)
     {
-      const gchar *name;
-      const gchar *encoding;
-
-      name = gimp_metadata_name_to_value (attribute_names,
-                                                    attribute_values,
-                                                    "name");
-      encoding = gimp_metadata_name_to_value (attribute_names,
-                                                        attribute_values,
-                                                        "encoding");
-
-      if (! name)
-        {
-          g_set_error (error, gimp_metadata_error_quark (), 1001,
-                       "Element 'tag' does not contain required attribute 'name'.");
-          return;
-        }
-
-      strncpy (parse_data->name, name, sizeof (parse_data->name));
-      parse_data->name[sizeof (parse_data->name) - 1] = 0;
-
-      parse_data->base64 = (encoding && ! strcmp (encoding, "base64"));
-    }
-  else if (! strcmp (element_name, "attribute"))
-    {
-      const gchar *name = NULL;
-      const gchar *type = NULL;
-
-      name     = gimp_metadata_name_to_value (attribute_names,
-                                              attribute_values,
-                                              "name");
-      type     = gimp_metadata_name_to_value (attribute_names,
-                                              attribute_values,
-                                              "type");
-
-      if (! name)
+      for (i = 0; xmp_data[i] != NULL; i++)
         {
-          g_set_error (error, gimp_metadata_error_quark (), 1001,
-                       "Element 'tag' does not contain required attribute 'name'.");
-          return;
-        }
+          value = gexiv2_metadata_get_tag_string (metadata, xmp_data[i]);
+          escaped = gimp_metadata_escape (xmp_data[i], value, &base64);
+          g_free (value);
 
-      if (! type)
-        {
-          g_set_error (error, gimp_metadata_error_quark (), 1001,
-                       "Element 'tag' does not contain required attribute 'type'.");
-          return;
+          gimp_metadata_append_tag (string, xmp_data[i], escaped, base64);
         }
 
-      strncpy (parse_data->name, name, sizeof (parse_data->name));
-      parse_data->name[sizeof (parse_data->name) - 1] = 0;
-
-      parse_data->type = (GimpAttributeValueType) atoi (type);
-    }
-  else if (! strcmp (element_name, "value"))
-    {
-      const gchar *encoding = NULL;
-
-      encoding = gimp_metadata_name_to_value (attribute_names,
-                                              attribute_values,
-                                              "encoding");
-
-      parse_data->base64 = (encoding && ! strcmp (encoding, "base64"));
-    }
-  else if (! strcmp (element_name, "interpreted"))
-    {
-      const gchar *encoding = NULL;
-
-      encoding = gimp_metadata_name_to_value (attribute_names,
-                                              attribute_values,
-                                              "encoding");
-
-      parse_data->base64 = (encoding && ! strcmp (encoding, "base64"));
+      g_strfreev (xmp_data);
     }
 
-}
-
-/**
- * gimp_metadata_deserialize_text:
- *
- * @context           : #GMarkupParseContext
- * @text              : const #gchar *
- * @text_len          : #gsize
- * @user_data         : #gpointer to #GimpMetadataParseData struct
- * @error             : #GError **
- *
- * text of a tag (parsing xml)
- *
- * Since: GIMP 2.10
- */
-static void
-gimp_metadata_deserialize_text (GMarkupParseContext  *context,
-                                const gchar          *text,
-                                gsize                 text_len,
-                                gpointer              user_data,
-                                GError              **error)
-{
-  GimpMetadataParseData   *parse_data       = user_data;
-  GimpAttribute           *attribute        = NULL;
-  const gchar             *current_element;
-
-  current_element = g_markup_parse_context_get_element (context);
-
-  if (! g_strcmp0 (current_element, "tag")) /*old metadata*/
-    {
-      gchar *value = g_strndup (text, text_len);
-
-      if (parse_data->base64)
-        {
-          guchar *decoded;
-          gsize   len;
-
-          decoded = g_base64_decode (value, &len);
-
-          if (decoded[len - 1] == '\0')
-            gexiv2_metadata_set_tag_string (GEXIV2_METADATA (parse_data->metadata),
-                                            parse_data->name,
-                                            (const gchar *) decoded);
-
-          g_free (decoded);
-        }
-      else
-        {
-          gexiv2_metadata_set_tag_string (GEXIV2_METADATA (parse_data->metadata),
-                                          parse_data->name,
-                                          value);
-        }
+  iptc_data = gexiv2_metadata_get_iptc_tags (metadata);
 
-      g_free (value);
-    }
-  else if (! g_strcmp0 (current_element, "value"))
+  if (iptc_data)
     {
-      gchar *value = g_strndup (text, text_len);
-
-      if (parse_data->base64)
-        {
-          guchar *decoded;
-          gsize   len;
-
-          decoded = g_base64_decode (value, &len);
-
-          if (decoded[len - 1] == '\0')
-            attribute = gimp_attribute_new_string (parse_data->name,
-                                                   (gchar *)decoded,
-                                                   parse_data->type);
-
-          g_free (decoded);
-        }
-      else
+      for (i = 0; iptc_data[i] != NULL; i++)
         {
-          attribute = gimp_attribute_new_string (parse_data->name,
-                                                 value,
-                                                 parse_data->type);
-        }
-
-      g_free (value);
+          value = gexiv2_metadata_get_tag_string (metadata, iptc_data[i]);
+          escaped = gimp_metadata_escape (iptc_data[i], value, &base64);
+          g_free (value);
 
-      if (attribute && gimp_attribute_is_valid (attribute))
-        {
-          gimp_metadata_add_attribute (parse_data->metadata, attribute);
-          current_attribute = attribute;
+          gimp_metadata_append_tag (string, iptc_data[i], escaped, base64);
         }
-      else
-        g_object_unref (attribute);
-
-    }
-  else if (! g_strcmp0 (current_element, "structure"))
-    {
-      GimpAttribute *attribute = NULL;
-      gchar         *value     = NULL;
-
-      attribute = current_attribute;
-
-      if (attribute)
-        {
-          gint                       v;
-          GimpAttributeStructureType struct_type = STRUCTURE_TYPE_BAG;
-
-          value = g_strndup (text, text_len);
 
-          v = atoi (value);
-
-          if (v > -1)
-            struct_type = (GimpAttributeStructureType) v;
-
-          gimp_attribute_set_structure_type (attribute, struct_type);
-
-          g_free (value);
-        }
+      g_strfreev (iptc_data);
     }
-  else if (! g_strcmp0 (current_element, "interpreted"))
-    {
-      GimpAttribute *attribute = NULL;
-      gchar         *value     = NULL;
-
-      attribute = current_attribute;
-
-      if (attribute)
-        {
-          value = g_strndup (text, text_len);
-
-          if (parse_data->base64)
-            {
-              guchar *decoded = NULL;
-              gsize   len;
 
-              decoded = g_base64_decode (value, &len);
-
-              if (decoded[len - 1] == '\0')
-                gimp_attribute_set_interpreted_string (attribute, (const gchar *)decoded);
+  g_string_append (string, "</metadata>\n");
 
-              g_free (decoded);
-            }
-          else
-            {
-              gimp_attribute_set_interpreted_string (attribute, (const gchar *)value);
-            }
-          g_free (value);
-        }
-    }
+  return g_string_free (string, FALSE);
 }
 
 /**
- * gimp_metadata_deserialize_end_element:
+ * gimp_metadata_load_from_file:
+ * @file:  The #GFile to load the metadata from
+ * @error: Return location for error message
  *
- * @context           : #GMarkupParseContext
- * @element_name      : #gchar *
- * @user_data         : #gpointer to #GimpMetadataParseData struct
- * @error             : #GError **
+ * Loads #GimpMetadata from @file.
  *
- * end of a tag (parsing xml)
+ * Return value: The loaded #GimpMetadata.
  *
- * Since: GIMP 2.10
+ * Since: 2.10
  */
-static void
-gimp_metadata_deserialize_end_element (GMarkupParseContext *context,
-                                         const gchar         *element_name,
-                                         gpointer             user_data,
-                                         GError             **error)
+GimpMetadata  *
+gimp_metadata_load_from_file (GFile   *file,
+                              GError **error)
 {
-  GimpMetadataParseData *parse_data = user_data;
+  GExiv2Metadata *meta = NULL;
+  gchar          *path;
+  gchar          *filename;
 
-  if (! strcmp (element_name, "attribute"))
-    {
-      current_attribute = NULL;
-    }
-  else if (! strcmp (element_name, "value"))
-    {
-      parse_data->base64 = FALSE;
-    }
-  else if (! strcmp (element_name, "interpreted"))
-    {
-      parse_data->base64 = FALSE;
-    }
-}
+  g_return_val_if_fail (G_IS_FILE (file), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-static gboolean
-has_xmp_structure (GSList *xmp_list, const gchar *entry)
-{
-  GSList *list;
+  path = g_file_get_path (file);
 
-  for (list = xmp_list; list; list = list->next)
+  if (! path)
     {
-      const gchar *to_test = (const gchar*) list->data;
-
-       if (! g_strcmp0 (to_test, entry))
-        return TRUE;
+      g_set_error (error, gimp_metadata_error_quark (), 0,
+                   _("Can load metadata only from local files"));
+      return NULL;
     }
 
-  return FALSE;
-}
+#ifdef G_OS_WIN32
+  filename = g_win32_locale_filename_from_utf8 (path);
+#else
+  filename = g_strdup (path);
+#endif
 
-/**
- * gimp_metadata_new_gexiv2metadata:
- *
- * Creates a new #GExiv2Metadata instance.
- *
- * Return value: The new #GExiv2Metadata.
- *
- * Since: 2.10
- */
-GExiv2Metadata *
-gimp_metadata_new_gexiv2metadata (void)
-{
-  GExiv2Metadata *gexiv2metadata = NULL;
-  gint            i;
+  g_free (path);
 
   if (gexiv2_initialize ())
     {
-      gexiv2metadata = gexiv2_metadata_new ();
+      meta = gexiv2_metadata_new ();
 
-      if (! gexiv2_metadata_open_buf (gexiv2metadata, wilber_jpg, wilber_jpg_len,
-                                      NULL))
+      if (! gexiv2_metadata_open_path (meta, filename, error))
         {
-          g_object_unref (gexiv2metadata);
+          g_object_unref (meta);
+          g_free (filename);
 
           return NULL;
         }
-      for (i = 0; i < G_N_ELEMENTS (namespaces_table); i++)
-        {
-          struct Namespaces n_space = namespaces_table[i];
-          gexiv2_metadata_register_xmp_namespace (n_space.namespace_URI, n_space.namespace_name);
-        }
-
     }
-  return gexiv2metadata;
-}
 
+  g_free (filename);
+
+  return meta;
+}
 
 /**
  * gimp_metadata_save_to_file:
@@ -2679,11 +567,11 @@ gimp_metadata_save_to_file (GimpMetadata  *metadata,
                             GFile         *file,
                             GError       **error)
 {
-  gchar          *path;
-  gchar          *filename;
-  gboolean        success;
+  gchar    *path;
+  gchar    *filename;
+  gboolean  success;
 
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), FALSE);
+  g_return_val_if_fail (GEXIV2_IS_METADATA (metadata), FALSE);
   g_return_val_if_fail (G_IS_FILE (file), FALSE);
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
@@ -2704,7 +592,7 @@ gimp_metadata_save_to_file (GimpMetadata  *metadata,
 
   g_free (path);
 
-  success = gexiv2_metadata_save_file (GEXIV2_METADATA (metadata), filename, error);
+  success = gexiv2_metadata_save_file (metadata, filename, error);
 
   g_free (filename);
 
@@ -2712,63 +600,6 @@ gimp_metadata_save_to_file (GimpMetadata  *metadata,
 }
 
 /**
- * gimp_metadata_load_from_file:
- * @file:  The #GFile to load the metadata from
- * @error: Return location for error message
- *
- * Loads #GimpMetadata from @file.
- *
- * Return value: The loaded #GimpMetadata.
- *
- * Since: 2.10
- */
-GimpMetadata  *
-gimp_metadata_load_from_file (GFile   *file,
-                              GError **error)
-{
-  GimpMetadata   *metadata     = NULL;
-  gchar          *path;
-  gchar          *filename;
-
-  g_return_val_if_fail (G_IS_FILE (file), NULL);
-  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-  path = g_file_get_path (file);
-
-  if (! path)
-    {
-      g_set_error (error, gimp_metadata_error_quark (), 0,
-                   _("Can load metadata only from local files"));
-      return NULL;
-    }
-
-#ifdef G_OS_WIN32
-  filename = g_win32_locale_filename_from_utf8 (path);
-#else
-  filename = g_strdup (path);
-#endif
-
-  g_free (path);
-
-  if (gexiv2_initialize ())
-    {
-      metadata = gimp_metadata_new ();
-
-      if (! gexiv2_metadata_open_path (GEXIV2_METADATA (metadata), filename, error))
-        {
-          g_free (filename);
-          g_object_unref (metadata);
-
-          return NULL;
-        }
-    }
-
-  g_free (filename);
-
-  return metadata;
-}
-
-/**
  * gimp_metadata_set_from_exif:
  * @metadata:         A #GimpMetadata instance.
  * @exif_data:        The blob of Exif data to set
@@ -2788,20 +619,17 @@ gimp_metadata_set_from_exif (GimpMetadata  *metadata,
                              GError       **error)
 {
 
-  GByteArray     *exif_bytes;
-  GExiv2Metadata *exif_metadata;
-  guint8          data_size[2] = { 0, };
-  const guint8    eoi[2] = { 0xff, 0xd9 };
+  GByteArray   *exif_bytes;
+  GimpMetadata *exif_metadata;
+  guint8        data_size[2] = { 0, };
+  const guint8  eoi[2] = { 0xff, 0xd9 };
 
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), FALSE);
+  g_return_val_if_fail (GEXIV2_IS_METADATA (metadata), FALSE);
   g_return_val_if_fail (exif_data != NULL, FALSE);
   g_return_val_if_fail (exif_data_length > 0, FALSE);
   g_return_val_if_fail (exif_data_length + 2 < 65536, FALSE);
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-  exif_metadata = GEXIV2_METADATA (metadata);
-  g_object_ref (exif_metadata);
-
   data_size[0] = ((exif_data_length + 2) & 0xFF00) >> 8;
   data_size[1] = ((exif_data_length + 2) & 0x00FF);
 
@@ -2814,6 +642,8 @@ gimp_metadata_set_from_exif (GimpMetadata  *metadata,
                                     (guint8 *) exif_data, exif_data_length);
   exif_bytes = g_byte_array_append (exif_bytes, eoi, 2);
 
+  exif_metadata = gimp_metadata_new ();
+
   if (! gexiv2_metadata_open_buf (exif_metadata,
                                   exif_bytes->data, exif_bytes->len, error))
     {
@@ -2831,6 +661,7 @@ gimp_metadata_set_from_exif (GimpMetadata  *metadata,
       return FALSE;
     }
 
+  gimp_metadata_add (exif_metadata, metadata);
   g_object_unref (exif_metadata);
   g_byte_array_free (exif_bytes, TRUE);
 
@@ -2856,15 +687,14 @@ gimp_metadata_set_from_xmp (GimpMetadata  *metadata,
                             gint           xmp_data_length,
                             GError       **error)
 {
-  GExiv2Metadata *xmp_metadata;
+  GimpMetadata *xmp_metadata;
 
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), FALSE);
+  g_return_val_if_fail (GEXIV2_IS_METADATA (metadata), FALSE);
   g_return_val_if_fail (xmp_data != NULL, FALSE);
   g_return_val_if_fail (xmp_data_length > 0, FALSE);
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-  xmp_metadata = GEXIV2_METADATA (metadata);
-  g_object_ref (xmp_metadata);
+  xmp_metadata = gimp_metadata_new ();
 
   if (! gexiv2_metadata_open_buf (xmp_metadata,
                                   xmp_data, xmp_data_length, error))
@@ -2881,65 +711,200 @@ gimp_metadata_set_from_xmp (GimpMetadata  *metadata,
       return FALSE;
     }
 
+  gimp_metadata_add (xmp_metadata, metadata);
   g_object_unref (xmp_metadata);
+
   return TRUE;
 }
 
 /**
- * gimp_metadata_is_tag_supported:
- * @tag:       A metadata tag name
- * @mime_type: A mime type
+ * gimp_metadata_set_pixel_size:
+ * @metadata: A #GimpMetadata instance.
+ * @width:    Width in pixels
+ * @height:   Height in pixels
  *
- * Returns whether @tag is supported in a file of type @mime_type.
+ * Sets Exif.Image.ImageWidth and Exif.Image.ImageLength on @metadata.
  *
- * Return value: %TRUE if the @tag supported with @mime_type, %FALSE otherwise.
+ * Since: 2.10
+ */
+void
+gimp_metadata_set_pixel_size (GimpMetadata *metadata,
+                              gint          width,
+                              gint          height)
+{
+  gchar buffer[32];
+
+  g_return_if_fail (GEXIV2_IS_METADATA (metadata));
+
+  g_snprintf (buffer, sizeof (buffer), "%d", width);
+  gexiv2_metadata_set_tag_string (metadata, "Exif.Image.ImageWidth", buffer);
+
+  g_snprintf (buffer, sizeof (buffer), "%d", height);
+  gexiv2_metadata_set_tag_string (metadata, "Exif.Image.ImageLength", buffer);
+}
+
+/**
+ * gimp_metadata_set_bits_per_sample:
+ * @metadata:        A #GimpMetadata instance.
+ * @bits_per_sample: Bits per pixel, per component
+ *
+ * Sets Exif.Image.BitsPerSample on @metadata.
+ *
+ * Since: 2.10
+ */
+void
+gimp_metadata_set_bits_per_sample (GimpMetadata *metadata,
+                                   gint          bits_per_sample)
+{
+  gchar buffer[32];
+
+  g_return_if_fail (GEXIV2_IS_METADATA (metadata));
+
+  g_snprintf (buffer, sizeof (buffer), "%d %d %d",
+              bits_per_sample, bits_per_sample, bits_per_sample);
+  gexiv2_metadata_set_tag_string (metadata, "Exif.Image.BitsPerSample", buffer);
+}
+
+/**
+ * gimp_metadata_get_resolution:
+ * @metadata: A #GimpMetadata instance.
+ * @xres:     Return location for the X Resolution, in ppi
+ * @yres:     Return location for the Y Resolution, in ppi
+ * @unit:     Return location for the unit unit
+ *
+ * Returns values based on Exif.Image.XResolution,
+ * Exif.Image.YResolution and Exif.Image.ResolutionUnit of @metadata.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
  *
  * Since: 2.10
  */
 gboolean
-gimp_metadata_is_tag_supported (const gchar *tag,
-                                const gchar *mime_type)
+gimp_metadata_get_resolution (GimpMetadata *metadata,
+                              gdouble      *xres,
+                              gdouble      *yres,
+                              GimpUnit     *unit)
 {
-  gint j;
+  gint xnom, xdenom;
+  gint ynom, ydenom;
 
-  g_return_val_if_fail (tag != NULL, FALSE);
-  g_return_val_if_fail (mime_type != NULL, FALSE);
+  g_return_val_if_fail (GEXIV2_IS_METADATA (metadata), FALSE);
 
-  for (j = 0; j < G_N_ELEMENTS (unsupported_tags); j++)
+  if (gexiv2_metadata_get_exif_tag_rational (metadata,
+                                             "Exif.Image.XResolution",
+                                             &xnom, &xdenom) &&
+      gexiv2_metadata_get_exif_tag_rational (metadata,
+                                             "Exif.Image.YResolution",
+                                             &ynom, &ydenom))
     {
-      if (g_str_has_prefix (tag, unsupported_tags[j]))
+      gchar *un;
+      gint   exif_unit = 2;
+
+      un = gexiv2_metadata_get_tag_string (metadata,
+                                           "Exif.Image.ResolutionUnit");
+      if (un)
         {
-          return FALSE;
+          exif_unit = atoi (un);
+          g_free (un);
         }
-    }
 
-  if (! strcmp (mime_type, "image/jpeg"))
-    {
-      for (j = 0; j < G_N_ELEMENTS (tiff_tags); j++)
+      if (xnom != 0 && xdenom != 0 &&
+          ynom != 0 && ydenom != 0)
         {
-          if (g_str_has_prefix (tag, tiff_tags[j]))
+          gdouble xresolution = (gdouble) xnom / (gdouble) xdenom;
+          gdouble yresolution = (gdouble) ynom / (gdouble) ydenom;
+
+          if (exif_unit == 3)
             {
-              return FALSE;
+              xresolution *= 2.54;
+              yresolution *= 2.54;
             }
+
+         if (xresolution >= GIMP_MIN_RESOLUTION &&
+             xresolution <= GIMP_MAX_RESOLUTION &&
+             yresolution >= GIMP_MIN_RESOLUTION &&
+             yresolution <= GIMP_MAX_RESOLUTION)
+           {
+             if (xres)
+               *xres = xresolution;
+
+             if (yres)
+               *yres = yresolution;
+
+             if (unit)
+               {
+                 if (exif_unit == 3)
+                   *unit = GIMP_UNIT_MM;
+                 else
+                   *unit = GIMP_UNIT_INCH;
+               }
+
+             return TRUE;
+           }
         }
     }
-  else if (! strcmp (mime_type, "image/tiff"))
+
+  return FALSE;
+}
+
+/**
+ * gimp_metadata_set_resolution:
+ * @metadata: A #GimpMetadata instance.
+ * @xres:     The image's X Resolution, in ppi
+ * @yres:     The image's Y Resolution, in ppi
+ * @unit:     The image's unit
+ *
+ * Sets Exif.Image.XResolution, Exif.Image.YResolution and
+ * Exif.Image.ResolutionUnit of @metadata.
+ *
+ * Since: 2.10
+ */
+void
+gimp_metadata_set_resolution (GimpMetadata *metadata,
+                              gdouble       xres,
+                              gdouble       yres,
+                              GimpUnit      unit)
+{
+  gchar buffer[32];
+  gint  exif_unit;
+  gint  factor;
+
+  g_return_if_fail (GEXIV2_IS_METADATA (metadata));
+
+  if (gimp_unit_is_metric (unit))
     {
-      for (j = 0; j < G_N_ELEMENTS (jpeg_tags); j++)
-        {
-          if (g_str_has_prefix (tag, jpeg_tags[j]))
-            {
-              return FALSE;
-            }
-        }
+      xres /= 2.54;
+      yres /= 2.54;
+
+      exif_unit = 3;
+    }
+  else
+    {
+      exif_unit = 2;
     }
 
-  return TRUE;
+  for (factor = 1; factor <= 100 /* arbitrary */; factor++)
+    {
+      if (fabs (xres * factor - ROUND (xres * factor)) < 0.01 &&
+          fabs (yres * factor - ROUND (yres * factor)) < 0.01)
+        break;
+    }
+
+  gexiv2_metadata_set_exif_tag_rational (metadata,
+                                         "Exif.Image.XResolution",
+                                         ROUND (xres * factor), factor);
+
+  gexiv2_metadata_set_exif_tag_rational (metadata,
+                                         "Exif.Image.YResolution",
+                                         ROUND (yres * factor), factor);
+
+  g_snprintf (buffer, sizeof (buffer), "%d", exif_unit);
+  gexiv2_metadata_set_tag_string (metadata, "Exif.Image.ResolutionUnit", buffer);
 }
 
 /**
  * gimp_metadata_get_colorspace:
- * @metadata: Ab #GimpMetadata instance.
+ * @metadata: A #GimpMetadata instance.
  *
  * Returns values based on Exif.Photo.ColorSpace, Xmp.exif.ColorSpace,
  * Exif.Iop.InteroperabilityIndex, Exif.Nikon3.ColorSpace,
@@ -2952,28 +917,22 @@ gimp_metadata_is_tag_supported (const gchar *tag,
 GimpMetadataColorspace
 gimp_metadata_get_colorspace (GimpMetadata *metadata)
 {
-  glong          exif_cs   = -1;
-  GimpAttribute *attribute = NULL;
-  GValue         val;
+  glong exif_cs = -1;
 
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata),
+  g_return_val_if_fail (GEXIV2_IS_METADATA (metadata),
                         GIMP_METADATA_COLORSPACE_UNSPECIFIED);
 
   /*  the logic here was mostly taken from darktable and libkexiv2  */
 
-  attribute = gimp_metadata_get_attribute (metadata, "Exif.Photo.ColorSpace");
-  if ( ! attribute)
+  if (gexiv2_metadata_has_tag (metadata, "Exif.Photo.ColorSpace"))
     {
-      attribute = gimp_metadata_get_attribute (metadata, "Xmp.exif.ColorSpace");
+      exif_cs = gexiv2_metadata_get_tag_long (metadata,
+                                              "Exif.Photo.ColorSpace");
     }
-
-  if (attribute)
+  else if (gexiv2_metadata_has_tag (metadata, "Xmp.exif.ColorSpace"))
     {
-      if (gimp_attribute_get_value_type (attribute) == TYPE_LONG || gimp_attribute_get_value_type 
(attribute) == TYPE_SLONG)
-        {
-          val = gimp_attribute_get_value (attribute);
-          exif_cs = g_value_get_long (&val);
-        }
+      exif_cs = gexiv2_metadata_get_tag_long (metadata,
+                                              "Xmp.exif.ColorSpace");
     }
 
   if (exif_cs == 0x01)
@@ -2990,9 +949,8 @@ gimp_metadata_get_colorspace (GimpMetadata *metadata)
         {
           gchar *iop_index;
 
-          attribute = gimp_metadata_get_attribute (metadata, "Exif.Iop.InteroperabilityIndex");
-          if (attribute)
-            iop_index = gimp_attribute_get_string (attribute);
+          iop_index = gexiv2_metadata_get_tag_string (metadata,
+                                                      "Exif.Iop.InteroperabilityIndex");
 
           if (! g_strcmp0 (iop_index, "R03"))
             {
@@ -3010,45 +968,37 @@ gimp_metadata_get_colorspace (GimpMetadata *metadata)
           g_free (iop_index);
         }
 
-      attribute = gimp_metadata_get_attribute (metadata, "Exif.Nikon3.ColorSpace");
-      if (attribute)
+      if (gexiv2_metadata_has_tag (metadata, "Exif.Nikon3.ColorSpace"))
         {
-          if (gimp_attribute_get_value_type (attribute) == TYPE_LONG || gimp_attribute_get_value_type 
(attribute) == TYPE_SLONG)
+          glong nikon_cs;
+
+          nikon_cs = gexiv2_metadata_get_tag_long (metadata,
+                                                   "Exif.Nikon3.ColorSpace");
+
+          if (nikon_cs == 0x01)
             {
-              glong nikon_cs;
-
-              val = gimp_attribute_get_value (attribute);
-              nikon_cs = g_value_get_long (&val);
-
-              if (nikon_cs == 0x01)
-                {
-                  return GIMP_METADATA_COLORSPACE_SRGB;
-                }
-              else if (nikon_cs == 0x02)
-                {
-                  return GIMP_METADATA_COLORSPACE_ADOBERGB;
-                }
+              return GIMP_METADATA_COLORSPACE_SRGB;
+            }
+          else if (nikon_cs == 0x02)
+            {
+              return GIMP_METADATA_COLORSPACE_ADOBERGB;
             }
         }
 
-      attribute = gimp_metadata_get_attribute (metadata, "Exif.Canon.ColorSpace");
-      if (attribute)
+      if (gexiv2_metadata_has_tag (metadata, "Exif.Canon.ColorSpace"))
         {
-          if (gimp_attribute_get_value_type (attribute) == TYPE_LONG || gimp_attribute_get_value_type 
(attribute) == TYPE_SLONG)
+          glong canon_cs;
+
+          canon_cs = gexiv2_metadata_get_tag_long (metadata,
+                                                   "Exif.Canon.ColorSpace");
+
+          if (canon_cs == 0x01)
             {
-              glong canon_cs;
-
-              val = gimp_attribute_get_value (attribute);
-              canon_cs = g_value_get_long (&val);
-
-              if (canon_cs == 0x01)
-                {
-                  return GIMP_METADATA_COLORSPACE_SRGB;
-                }
-              else if (canon_cs == 0x02)
-                {
-                  return GIMP_METADATA_COLORSPACE_ADOBERGB;
-                }
+              return GIMP_METADATA_COLORSPACE_SRGB;
+            }
+          else if (canon_cs == 0x02)
+            {
+              return GIMP_METADATA_COLORSPACE_ADOBERGB;
             }
         }
 
@@ -3060,295 +1010,201 @@ gimp_metadata_get_colorspace (GimpMetadata *metadata)
 }
 
 /**
- * gimp_metadata_get_resolution:
- * @metadata: A #GimpMetadata instance.
- * @xres:     Return location for the X Resolution, in ppi
- * @yres:     Return location for the Y Resolution, in ppi
- * @unit:     Return location for the unit unit
- *
- * Returns values based on Exif.Image.XResolution,
- * Exif.Image.YResolution and Exif.Image.ResolutionUnit of @metadata.
+ * gimp_metadata_set_colorspace:
+ * @metadata:   A #GimpMetadata instance.
+ * @colorspace: The color space.
  *
- * Return value: %TRUE on success, %FALSE otherwise.
+ * Sets Exif.Photo.ColorSpace, Xmp.exif.ColorSpace,
+ * Exif.Iop.InteroperabilityIndex, Exif.Nikon3.ColorSpace,
+ * Exif.Canon.ColorSpace of @metadata.
  *
- * Since: GIMP 2.10
+ * Since: 2.10
  */
-gboolean
-gimp_metadata_get_resolution (GimpMetadata *metadata,
-                              gdouble        *xres,
-                              gdouble        *yres,
-                              GimpUnit       *unit)
+void
+gimp_metadata_set_colorspace (GimpMetadata           *metadata,
+                              GimpMetadataColorspace  colorspace)
 {
-  GimpAttribute *x_attribute;
-  GimpAttribute *y_attribute;
-  GimpAttribute *res_attribute;
-
-  gint   xnom, xdenom;
-  gint   ynom, ydenom;
-  gint   exif_unit = 2;
+  g_return_if_fail (GEXIV2_IS_METADATA (metadata));
 
-  g_return_val_if_fail (IS_GIMP_METADATA (metadata), FALSE);
+  switch (colorspace)
+    {
+    case GIMP_METADATA_COLORSPACE_UNSPECIFIED:
+      gexiv2_metadata_clear_tag (metadata, "Exif.Photo.ColorSpace");
+      gexiv2_metadata_clear_tag (metadata, "Xmp.exif.ColorSpace");
+      gexiv2_metadata_clear_tag (metadata, "Exif.Iop.InteroperabilityIndex");
+      gexiv2_metadata_clear_tag (metadata, "Exif.Nikon3.ColorSpace");
+      gexiv2_metadata_clear_tag (metadata, "Exif.Canon.ColorSpace");
+      break;
 
-  x_attribute = gimp_metadata_get_attribute (metadata, "Exif.Image.XResolution");
-  y_attribute = gimp_metadata_get_attribute (metadata, "Exif.Image.YResolution");
-  res_attribute = gimp_metadata_get_attribute (metadata, "Exif.Image.ResolutionUnit");
+    case GIMP_METADATA_COLORSPACE_UNCALIBRATED:
+      gexiv2_metadata_set_tag_long (metadata, "Exif.Photo.ColorSpace", 0xffff);
+      if (gexiv2_metadata_has_tag (metadata, "Xmp.exif.ColorSpace"))
+        gexiv2_metadata_set_tag_long (metadata, "Xmp.exif.ColorSpace", 0xffff);
+      gexiv2_metadata_clear_tag (metadata, "Exif.Iop.InteroperabilityIndex");
+      gexiv2_metadata_clear_tag (metadata, "Exif.Nikon3.ColorSpace");
+      gexiv2_metadata_clear_tag (metadata, "Exif.Canon.ColorSpace");
+      break;
 
-  if (x_attribute)
-    {
-      GValue    value;
-      Rational *rats;
-      gint     *_nom;
-      gint     *_denom;
-      gint      l;
+    case GIMP_METADATA_COLORSPACE_SRGB:
+      gexiv2_metadata_set_tag_long (metadata, "Exif.Photo.ColorSpace", 0x01);
 
-      value = gimp_attribute_get_value (x_attribute);
+      if (gexiv2_metadata_has_tag (metadata, "Xmp.exif.ColorSpace"))
+        gexiv2_metadata_set_tag_long (metadata, "Xmp.exif.ColorSpace", 0x01);
 
-      rats = g_value_get_boxed (&value);
+      if (gexiv2_metadata_has_tag (metadata, "Exif.Iop.InteroperabilityIndex"))
+        gexiv2_metadata_set_tag_string (metadata,
+                                        "Exif.Iop.InteroperabilityIndex", "R98");
 
-      rational_to_int (rats, &_nom, &_denom, &l);
+      if (gexiv2_metadata_has_tag (metadata, "Exif.Nikon3.ColorSpace"))
+        gexiv2_metadata_set_tag_long (metadata, "Exif.Nikon3.ColorSpace", 0x01);
 
-      if (l > 0)
-        {
-          xnom = _nom[0];
-          xdenom = _denom[0];
-        }
-      rational_free (rats);
-    }
-  else
-    return FALSE;
+      if (gexiv2_metadata_has_tag (metadata, "Exif.Canon.ColorSpace"))
+        gexiv2_metadata_set_tag_long (metadata, "Exif.Canon.ColorSpace", 0x01);
+      break;
 
-  if (y_attribute)
-    {
-      GValue    value;
-      Rational *rats;
-      gint     *_nom;
-      gint     *_denom;
-      gint      l;
+    case GIMP_METADATA_COLORSPACE_ADOBERGB:
+      gexiv2_metadata_set_tag_long (metadata, "Exif.Photo.ColorSpace", 0x02);
 
-      value = gimp_attribute_get_value (y_attribute);
+      if (gexiv2_metadata_has_tag (metadata, "Xmp.exif.ColorSpace"))
+        gexiv2_metadata_set_tag_long (metadata, "Xmp.exif.ColorSpace", 0x02);
 
-      rats = g_value_get_boxed (&value);
+      if (gexiv2_metadata_has_tag (metadata, "Exif.Iop.InteroperabilityIndex"))
+        gexiv2_metadata_set_tag_string (metadata,
+                                        "Exif.Iop.InteroperabilityIndex", "R03");
 
-      rational_to_int (rats, &_nom, &_denom, &l);
+      if (gexiv2_metadata_has_tag (metadata, "Exif.Nikon3.ColorSpace"))
+        gexiv2_metadata_set_tag_long (metadata, "Exif.Nikon3.ColorSpace", 0x02);
 
-      if (l > 0)
-        {
-          ynom = _nom[0];
-          ydenom = _denom[0];
-        }
-      rational_free (rats);
+      if (gexiv2_metadata_has_tag (metadata, "Exif.Canon.ColorSpace"))
+        gexiv2_metadata_set_tag_long (metadata, "Exif.Canon.ColorSpace", 0x02);
+      break;
     }
-  else
-    return FALSE;
+}
 
-  if (res_attribute)
-    {
-      GValue value = gimp_attribute_get_value (res_attribute);
+/**
+ * gimp_metadata_is_tag_supported:
+ * @tag:       A metadata tag name
+ * @mime_type: A mime type
+ *
+ * Returns whether @tag is supported in a file of type @mime_type.
+ *
+ * Return value: %TRUE if the @tag supported with @mime_type, %FALSE otherwise.
+ *
+ * Since: 2.10
+ */
+gboolean
+gimp_metadata_is_tag_supported (const gchar *tag,
+                                const gchar *mime_type)
+{
+  gint j;
 
-      exif_unit = (gint) g_value_get_uint (&value);
-    }
+  g_return_val_if_fail (tag != NULL, FALSE);
+  g_return_val_if_fail (mime_type != NULL, FALSE);
 
-  if (xnom != 0 && xdenom != 0 &&
-      ynom != 0 && ydenom != 0)
+  for (j = 0; j < G_N_ELEMENTS (unsupported_tags); j++)
     {
-      gdouble xresolution = (gdouble) xnom / (gdouble) xdenom;
-      gdouble yresolution = (gdouble) ynom / (gdouble) ydenom;
-
-      if (exif_unit == 3)
+      if (g_str_has_prefix (tag, unsupported_tags[j]))
         {
-          xresolution *= 2.54;
-          yresolution *= 2.54;
+          return FALSE;
         }
+    }
 
-      if (xresolution >= GIMP_MIN_RESOLUTION &&
-          xresolution <= GIMP_MAX_RESOLUTION &&
-          yresolution >= GIMP_MIN_RESOLUTION &&
-          yresolution <= GIMP_MAX_RESOLUTION)
+  if (! strcmp (mime_type, "image/jpeg"))
+    {
+      for (j = 0; j < G_N_ELEMENTS (tiff_tags); j++)
         {
-          if (xres)
-            *xres = xresolution;
-
-          if (yres)
-            *yres = yresolution;
-
-          if (unit)
+          if (g_str_has_prefix (tag, tiff_tags[j]))
             {
-              if (exif_unit == 3)
-                *unit = GIMP_UNIT_MM;
-              else
-                *unit = GIMP_UNIT_INCH;
+              return FALSE;
+            }
+        }
+    }
+  else if (! strcmp (mime_type, "image/tiff"))
+    {
+      for (j = 0; j < G_N_ELEMENTS (jpeg_tags); j++)
+        {
+          if (g_str_has_prefix (tag, jpeg_tags[j]))
+            {
+              return FALSE;
             }
-
-          return TRUE;
         }
     }
-  return FALSE;
-}
 
-/**
- * gimp_metadata_set_bits_per_sample:
- * @metadata: A #GimpMetadata instance.
- * @bps:      Bytes per pixel, per component
- *
- * Sets Exif.Image.BitsPerSample on @metadata.
- *
- * Since: GIMP 2.10
- */
-void
-gimp_metadata_set_bits_per_sample (GimpMetadata *metadata,
-                                   gint            bps)
-{
-  gchar buffer[32];
+  return TRUE;
+}
 
-  g_return_if_fail ( (metadata));
 
-  g_snprintf (buffer, sizeof (buffer), "%d", bps);
-  gimp_metadata_new_attribute (metadata, "Exif.Image.BitsPerSample", buffer, TYPE_SHORT);
-}
+/* private functions */
 
-/**
- * gimp_metadata_set_pixel_size:
- * @metadata: A #GimpMetadata instance.
- * @width:    Width in pixels
- * @height:   Height in pixels
- *
- * Sets Exif.Image.ImageWidth and Exif.Image.ImageLength on @metadata.
- *
- * Since: GIMP 2.10
- */
-void
-gimp_metadata_set_pixel_size (GimpMetadata *metadata,
-                              gint            width,
-                              gint            height)
+static GQuark
+gimp_metadata_error_quark (void)
 {
-  gchar buffer[32];
-
-  g_return_if_fail (IS_GIMP_METADATA (metadata));
+  static GQuark quark = 0;
 
-  g_snprintf (buffer, sizeof (buffer), "%d", width);
-  gimp_metadata_new_attribute (metadata, "Exif.Image.ImageWidth", buffer, TYPE_LONG);
+  if (G_UNLIKELY (quark == 0))
+    quark = g_quark_from_static_string ("gimp-metadata-error-quark");
 
-  g_snprintf (buffer, sizeof (buffer), "%d", height);
-  gimp_metadata_new_attribute (metadata, "Exif.Image.ImageLength", buffer, TYPE_LONG);
+  return quark;
 }
 
-/**
- * gimp_metadata_set_colorspace:
- * @metadata:   A #GimpMetadata instance.
- * @colorspace: The color space.
- *
- * Sets Exif.Photo.ColorSpace, Xmp.exif.ColorSpace,
- * Exif.Iop.InteroperabilityIndex, Exif.Nikon3.ColorSpace,
- * Exif.Canon.ColorSpace of @metadata.
- *
- * Since: 2.10
- */
-void
-gimp_metadata_set_colorspace (GimpMetadata           *metadata,
-                              GimpMetadataColorspace  colorspace)
+static void
+gimp_metadata_add (GimpMetadata *src,
+                   GimpMetadata *dest)
 {
-  g_return_if_fail (IS_GIMP_METADATA (metadata));
+  gchar *value;
+  gint   i;
 
-  gimp_metadata_remove_attribute (metadata, "Exif.Photo.ColorSpace");
-  gimp_metadata_remove_attribute (metadata, "Xmp.exif.ColorSpace");
-  gimp_metadata_remove_attribute (metadata, "Exif.Iop.InteroperabilityIndex");
-
-  switch (colorspace)
+  if (gexiv2_metadata_get_supports_exif (src) &&
+      gexiv2_metadata_get_supports_exif (dest))
     {
-    case GIMP_METADATA_COLORSPACE_UNSPECIFIED:
-      gimp_metadata_remove_attribute (metadata, "Exif.Nikon3.ColorSpace");
-      gimp_metadata_remove_attribute (metadata, "Exif.Canon.ColorSpace");
-      break;
+      gchar **exif_data = gexiv2_metadata_get_exif_tags (src);
 
-    case GIMP_METADATA_COLORSPACE_UNCALIBRATED:
-      gimp_metadata_new_attribute (metadata, "Exif.Photo.ColorSpace", "0xffff", TYPE_LONG);
-      gimp_metadata_new_attribute (metadata, "Xmp.exif.ColorSpace", "0xffff", TYPE_LONG);
-      break;
-
-    case GIMP_METADATA_COLORSPACE_SRGB:
-      gimp_metadata_new_attribute (metadata, "Exif.Photo.ColorSpace", "0x01", TYPE_LONG);
-      gimp_metadata_new_attribute (metadata, "Xmp.exif.ColorSpace", "0x01", TYPE_LONG);
-      gimp_metadata_new_attribute (metadata, "Exif.Iop.InteroperabilityIndex", "R98", TYPE_ASCII);
-      if (gimp_metadata_has_attribute (metadata, "Exif.Nikon3.ColorSpace"))
-        {
-          gimp_metadata_remove_attribute (metadata, "Exif.Nikon3.ColorSpace");
-          gimp_metadata_new_attribute (metadata, "Exif.Nikon3.ColorSpace", "0x01", TYPE_LONG);
-        }
-      if (gimp_metadata_has_attribute (metadata, "Exif.Canon.ColorSpace"))
+      if (exif_data)
         {
-          gimp_metadata_remove_attribute (metadata, "Exif.Canon.ColorSpace");
-          gimp_metadata_new_attribute (metadata, "Exif.Canon.ColorSpace", "0x01", TYPE_LONG);
-        }
-      break;
+          for (i = 0; exif_data[i] != NULL; i++)
+            {
+              value = gexiv2_metadata_get_tag_string (src, exif_data[i]);
+              gexiv2_metadata_set_tag_string (dest, exif_data[i], value);
+              g_free (value);
+            }
 
-    case GIMP_METADATA_COLORSPACE_ADOBERGB:
-      gimp_metadata_new_attribute (metadata, "Exif.Photo.ColorSpace", "0x02", TYPE_LONG);
-      gimp_metadata_new_attribute (metadata, "Xmp.exif.ColorSpace", "0x02", TYPE_LONG);
-      gimp_metadata_new_attribute (metadata, "Exif.Iop.InteroperabilityIndex", "R03", TYPE_ASCII);
-      if (gimp_metadata_has_attribute (metadata, "Exif.Nikon3.ColorSpace"))
-        {
-          gimp_metadata_remove_attribute (metadata, "Exif.Nikon3.ColorSpace");
-          gimp_metadata_new_attribute (metadata, "Exif.Nikon3.ColorSpace", "0x02", TYPE_LONG);
-        }
-      if (gimp_metadata_has_attribute (metadata, "Exif.Canon.ColorSpace"))
-        {
-          gimp_metadata_remove_attribute (metadata, "Exif.Canon.ColorSpace");
-          gimp_metadata_new_attribute (metadata, "Exif.Canon.ColorSpace", "0x02", TYPE_LONG);
+          g_strfreev (exif_data);
         }
-      break;
     }
-}
-
-/**
- * gimp_metadata_set_resolution:
- * @metadata: A #GimpMetadata instance.
- * @xres:     The image's X Resolution, in ppi
- * @yres:     The image's Y Resolution, in ppi
- * @unit:     The image's unit
- *
- * Sets Exif.Image.XResolution, Exif.Image.YResolution and
- * Exif.Image.ResolutionUnit @metadata.
- *
- * Since: GIMP 2.10
- */
-void
-gimp_metadata_set_resolution (GimpMetadata *metadata,
-                              gdouble         xres,
-                              gdouble         yres,
-                              GimpUnit        unit)
-{
-  gchar buffer[64];
-  gint  exif_unit;
-  gint  factor;
 
-  g_return_if_fail (IS_GIMP_METADATA (metadata));
-
-  if (gimp_unit_is_metric (unit))
+  if (gexiv2_metadata_get_supports_xmp (src) &&
+      gexiv2_metadata_get_supports_xmp (dest))
     {
-      xres /= 2.54;
-      yres /= 2.54;
+      gchar **xmp_data = gexiv2_metadata_get_xmp_tags (src);
 
-      exif_unit = 3;
-    }
-  else
-    {
-      exif_unit = 2;
-    }
+      if (xmp_data)
+        {
+          for (i = 0; xmp_data[i] != NULL; i++)
+            {
+              value = gexiv2_metadata_get_tag_string (src, xmp_data[i]);
+              gexiv2_metadata_set_tag_string (dest, xmp_data[i], value);
+              g_free (value);
+            }
 
-  for (factor = 1; factor <= 100 /* arbitrary */; factor++)
-    {
-      if (fabs (xres * factor - ROUND (xres * factor)) < 0.01 &&
-          fabs (yres * factor - ROUND (yres * factor)) < 0.01)
-        break;
+          g_strfreev (xmp_data);
+        }
     }
 
-  g_snprintf (buffer, sizeof (buffer), "%d/%d", ROUND (xres * factor), factor);
-  gimp_metadata_new_attribute (metadata, "Exif.Image.XResolution", buffer, TYPE_RATIONAL);
+  if (gexiv2_metadata_get_supports_iptc (src) &&
+      gexiv2_metadata_get_supports_iptc (dest))
+    {
+      gchar **iptc_data = gexiv2_metadata_get_iptc_tags (src);
 
-  g_snprintf (buffer, sizeof (buffer), "%d/%d", ROUND (yres * factor), factor);
-  gimp_metadata_new_attribute (metadata, "Exif.Image.YResolution", buffer, TYPE_RATIONAL);
+      if (iptc_data)
+        {
+          for (i = 0; iptc_data[i] != NULL; i++)
+            {
+              value = gexiv2_metadata_get_tag_string (src, iptc_data[i]);
+              gexiv2_metadata_set_tag_string (dest, iptc_data[i], value);
+              g_free (value);
+            }
 
-  g_snprintf (buffer, sizeof (buffer), "%d", exif_unit);
-  gimp_metadata_new_attribute (metadata, "Exif.Image.ResolutionUnit", buffer, TYPE_SHORT);
+          g_strfreev (iptc_data);
+        }
+    }
 }
-
diff --git a/libgimpbase/gimpmetadata.h b/libgimpbase/gimpmetadata.h
index cac1d8e..3a6b27c 100644
--- a/libgimpbase/gimpmetadata.h
+++ b/libgimpbase/gimpmetadata.h
@@ -1,19 +1,29 @@
+/* LIBGIMPBASE - The GIMP Basic Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpmetadata.h
+ * Copyright (C) 2013 Hartmut Kuhse <hartmutkuhse src gnome org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
 
-#ifndef __GIMPMETADATA_H__
-#define __GIMPMETADATA_H__
+#ifndef __GIMP_METADATA_H__
+#define __GIMP_METADATA_H__
 
 G_BEGIN_DECLS
 
-#include <gexiv2/gexiv2.h>
-
-#define TYPE_GIMP_METADATA (gimp_metadata_get_type ())
-#define GIMP_METADATA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_GIMP_METADATA, GimpMetadata))
-#define GIMP_METADATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_GIMP_METADATA, GimpMetadataClass))
-#define IS_GIMP_METADATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_GIMP_METADATA))
-#define IS_GIMP_METADATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_GIMP_METADATA))
-#define GIMP_METADATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_GIMP_METADATA, 
GimpMetadataClass))
-#define GIMP_METADATA_GET_PRIVATE(obj)  (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_GIMP_METADATA, 
GimpMetadataPrivate))
-
 typedef enum
 {
   GIMP_METADATA_LOAD_COMMENT     = 1 << 0,
@@ -42,73 +52,51 @@ typedef enum
   GIMP_METADATA_COLORSPACE_ADOBERGB
 } GimpMetadataColorspace;
 
-GType                                     gimp_metadata_get_type                                   (void) 
G_GNUC_CONST;
-GimpMetadata *                            gimp_metadata_new                                        (void);
-gint                                      gimp_metadata_size                                       
(GimpMetadata             *metadata);
-GimpMetadata *                            gimp_metadata_duplicate                                  
(GimpMetadata             *metadata);
-GHashTable *                              gimp_metadata_get_table                                  
(GimpMetadata             *metadata);
-void                                      gimp_metadata_add_attribute                              
(GimpMetadata             *metadata,
-                                                                                                    
GimpAttribute            *attribute);
-GimpAttribute *                           gimp_metadata_get_attribute                              
(GimpMetadata             *metadata,
-                                                                                                    const 
gchar              *name);
-gboolean                                  gimp_metadata_remove_attribute                           
(GimpMetadata             *metadata,
-                                                                                                    const 
gchar              *name);
-gboolean                                  gimp_metadata_has_attribute                              
(GimpMetadata             *metadata,
-                                                                                                    const 
gchar              *name);
-gboolean                                  gimp_metadata_new_attribute                              
(GimpMetadata             *metadata,
-                                                                                                    const 
gchar              *name,
-                                                                                                    gchar    
                *value,
-                                                                                                    
GimpAttributeValueType    type);
-gchar *                                   gimp_metadata_serialize                                  
(GimpMetadata             *metadata);
-GimpMetadata *                            gimp_metadata_deserialize                                (const 
gchar              *xml);
-void                                      gimp_metadata_print                                      
(GimpMetadata             *metadata);
-const gchar *                             gimp_metadata_to_xmp_packet                              
(GimpMetadata             *metadata,
-                                                                                                    const 
gchar              *mime_type);
-gboolean                                  gimp_metadata_has_tag_type                               
(GimpMetadata             *metadata,
-                                                                                                    
GimpAttributeTagType      tag_type);
-GList *                                   gimp_metadata_iter_init                                  
(GimpMetadata             *metadata,
-                                                                                                    GList    
               **iter);
-gboolean                                  gimp_metadata_iter_next                                  
(GimpMetadata             *metadata,
-                                                                                                    
GimpAttribute           **attribute,
-                                                                                                    GList    
               **prev);
-gboolean                                  gimp_metadata_save_to_file                               
(GimpMetadata             *metadata,
-                                                                                                    GFile    
                *file,
-                                                                                                    GError   
               **error);
-GimpMetadata *                            gimp_metadata_load_from_file                             (GFile    
                *file,
-                                                                                                    GError   
               **error);
-gboolean                                  gimp_metadata_set_from_exif                              
(GimpMetadata             *metadata,
-                                                                                                    const 
guchar             *exif_data,
-                                                                                                    gint     
                 exif_data_length,
-                                                                                                    GError   
               **error);
-gboolean                                  gimp_metadata_set_from_xmp                               
(GimpMetadata             *metadata,
-                                                                                                    const 
guchar             *xmp_data,
-                                                                                                    gint     
                 xmp_data_length,
-                                                                                                    GError   
               **error);
-gboolean                                  gimp_metadata_is_tag_supported                           (const 
gchar              *tag,
-                                                                                                    const 
gchar              *mime_type);
-GimpMetadataColorspace                    gimp_metadata_get_colorspace                             
(GimpMetadata             *metadata);
-gboolean                                  gimp_metadata_get_resolution                             
(GimpMetadata             *metadata,
-                                                                                                    gdouble  
                *xres,
-                                                                                                    gdouble  
                *yres,
-                                                                                                    GimpUnit 
                *unit);
-void                                      gimp_metadata_set_resolution                             
(GimpMetadata             *metadata,
-                                                                                                    gdouble  
                 xres,
-                                                                                                    gdouble  
                 yres,
-                                                                                                    GimpUnit 
                 unit);
-void                                      gimp_metadata_set_bits_per_sample                        
(GimpMetadata             *metadata,
-                                                                                                    gint     
                 bits_per_sample);
-void                                      gimp_metadata_set_pixel_size                             
(GimpMetadata             *metadata,
-                                                                                                    gint     
                 width,
-                                                                                                    gint     
                 height);
-void                                      gimp_metadata_set_colorspace                             
(GimpMetadata             *metadata,
-                                                                                                    
GimpMetadataColorspace    colorspace);
-//GimpMetadata *                            gimp_metadata_from_gexiv2metadata                        
(GimpMetadata             *metadata,
-//                                                                                                    
GimpMetadata             *gexivdata);
-//void                                      gimp_metadata_to_gexiv2metadata                          
(GimpMetadata             *metadata,
-//                                                                                                    
GimpMetadata             *gexivdata,
-//                                                                                                    const 
gchar              *mime_type);
 
+GimpMetadata * gimp_metadata_new                 (void);
+GimpMetadata * gimp_metadata_duplicate           (GimpMetadata           *metadata);
+
+GimpMetadata * gimp_metadata_deserialize         (const gchar            *metadata_xml);
+gchar        * gimp_metadata_serialize           (GimpMetadata           *metadata);
+
+GimpMetadata * gimp_metadata_load_from_file      (GFile                  *file,
+                                                  GError                **error);
+gboolean       gimp_metadata_save_to_file        (GimpMetadata           *metadata,
+                                                  GFile                  *file,
+                                                  GError                **error);
+
+gboolean       gimp_metadata_set_from_exif       (GimpMetadata           *metadata,
+                                                  const guchar           *exif_data,
+                                                  gint                    exif_data_length,
+                                                  GError                **error);
+gboolean       gimp_metadata_set_from_xmp        (GimpMetadata           *metadata,
+                                                  const guchar           *xmp_data,
+                                                  gint                    xmp_data_length,
+                                                  GError                **error);
+
+void           gimp_metadata_set_pixel_size      (GimpMetadata           *metadata,
+                                                  gint                    width,
+                                                  gint                    height);
+void           gimp_metadata_set_bits_per_sample (GimpMetadata           *metadata,
+                                                  gint                    bits_per_sample);
+
+gboolean       gimp_metadata_get_resolution      (GimpMetadata           *metadata,
+                                                  gdouble                *xres,
+                                                  gdouble                *yres,
+                                                  GimpUnit               *unit);
+void           gimp_metadata_set_resolution      (GimpMetadata           *metadata,
+                                                  gdouble                 xres,
+                                                  gdouble                 yres,
+                                                  GimpUnit                unit);
+
+GimpMetadataColorspace
+               gimp_metadata_get_colorspace      (GimpMetadata           *metadata);
+void           gimp_metadata_set_colorspace      (GimpMetadata           *metadata,
+                                                  GimpMetadataColorspace  colorspace);
+
+gboolean       gimp_metadata_is_tag_supported    (const gchar            *tag,
+                                                  const gchar            *mime_type);
 
 G_END_DECLS
 
-#endif
+#endif /* __GIMP_METADATA_H__ */
diff --git a/libgimpwidgets/gimpicons.c b/libgimpwidgets/gimpicons.c
index 2ddd6ed..0bec46e 100644
--- a/libgimpwidgets/gimpicons.c
+++ b/libgimpwidgets/gimpicons.c
@@ -166,7 +166,6 @@ static const GtkStockItem gimp_stock_items[] =
   { GIMP_STOCK_TOOL_PRESET,              NULL,        0, 0, LIBGIMP_DOMAIN },
 
   { GIMP_STOCK_IMAGE,                    NULL,        0, 0, LIBGIMP_DOMAIN },
-  { GIMP_STOCK_IMAGE_METADATA,           NULL,        0, 0, LIBGIMP_DOMAIN },
   { GIMP_STOCK_LAYER,                    NULL,        0, 0, LIBGIMP_DOMAIN },
   { GIMP_STOCK_TEXT_LAYER,               NULL,        0, 0, LIBGIMP_DOMAIN },
   { GIMP_STOCK_FLOATING_SELECTION,       NULL,        0, 0, LIBGIMP_DOMAIN },
diff --git a/libgimpwidgets/gimpicons.h b/libgimpwidgets/gimpicons.h
index 66f423a..4d82e5c 100644
--- a/libgimpwidgets/gimpicons.h
+++ b/libgimpwidgets/gimpicons.h
@@ -182,7 +182,6 @@ G_BEGIN_DECLS
 #define GIMP_STOCK_FLIP_VERTICAL            "gimp-flip-vertical"
 
 #define GIMP_STOCK_IMAGE                    "gimp-image"
-#define GIMP_STOCK_IMAGE_METADATA           "gimp-image-metadata"
 #define GIMP_STOCK_LAYER                    "gimp-layer"
 #define GIMP_STOCK_TEXT_LAYER               "gimp-text-layer"
 #define GIMP_STOCK_FLOATING_SELECTION       "gimp-floating-selection"
diff --git a/plug-ins/common/Makefile.am b/plug-ins/common/Makefile.am
index 57f1f3f..90b048b 100644
--- a/plug-ins/common/Makefile.am
+++ b/plug-ins/common/Makefile.am
@@ -52,7 +52,6 @@ libexec_PROGRAMS = \
        align-layers \
        animation-optimize \
        animation-play \
-       attributes      \
        blinds \
        blur \
        border-average \
@@ -117,10 +116,10 @@ libexec_PROGRAMS = \
        grid \
        guillotine \
        hot \
-       iptc    \
        jigsaw \
        $(MAIL) \
        max-rgb \
+       metadata \
        newsprint \
        nl-filter \
        oilify \
@@ -219,24 +218,6 @@ animation_play_LDADD = \
        $(INTLLIBS)             \
        $(animation_play_RC)
 
-attributes_SOURCES = \
-       attributes.c
-
-attributes_LDADD = \
-       $(libgimpui)            \
-       $(libgimpwidgets)       \
-       $(libgimpmodule)        \
-       $(libgimp)              \
-       $(libgimpmath)          \
-       $(libgimpconfig)        \
-       $(libgimpcolor)         \
-       $(libgimpbase)          \
-       $(GTK_LIBS)             \
-       $(GEGL_LIBS)            \
-       $(RT_LIBS)              \
-       $(INTLLIBS)             \
-       $(attributes_RC)
-
 blinds_SOURCES = \
        blinds.c
 
@@ -1373,12 +1354,10 @@ hot_LDADD = \
        $(INTLLIBS)             \
        $(hot_RC)
 
-iptc_CFLAGS = $(GEXIV2_CFLAGS)
-
-iptc_SOURCES = \
-       iptc.c
+jigsaw_SOURCES = \
+       jigsaw.c
 
-iptc_LDADD = \
+jigsaw_LDADD = \
        $(libgimpui)            \
        $(libgimpwidgets)       \
        $(libgimpmodule)        \
@@ -1388,15 +1367,14 @@ iptc_LDADD = \
        $(libgimpcolor)         \
        $(libgimpbase)          \
        $(GTK_LIBS)             \
-       $(GEXIV2_LIBS)          \
        $(RT_LIBS)              \
        $(INTLLIBS)             \
-       $(iptc_RC)
+       $(jigsaw_RC)
 
-jigsaw_SOURCES = \
-       jigsaw.c
+mail_SOURCES = \
+       mail.c
 
-jigsaw_LDADD = \
+mail_LDADD = \
        $(libgimpui)            \
        $(libgimpwidgets)       \
        $(libgimpmodule)        \
@@ -1408,12 +1386,12 @@ jigsaw_LDADD = \
        $(GTK_LIBS)             \
        $(RT_LIBS)              \
        $(INTLLIBS)             \
-       $(jigsaw_RC)
+       $(mail_RC)
 
-mail_SOURCES = \
-       mail.c
+max_rgb_SOURCES = \
+       max-rgb.c
 
-mail_LDADD = \
+max_rgb_LDADD = \
        $(libgimpui)            \
        $(libgimpwidgets)       \
        $(libgimpmodule)        \
@@ -1425,12 +1403,14 @@ mail_LDADD = \
        $(GTK_LIBS)             \
        $(RT_LIBS)              \
        $(INTLLIBS)             \
-       $(mail_RC)
+       $(max_rgb_RC)
 
-max_rgb_SOURCES = \
-       max-rgb.c
+metadata_CFLAGS = $(GEXIV2_CFLAGS)
 
-max_rgb_LDADD = \
+metadata_SOURCES = \
+       metadata.c
+
+metadata_LDADD = \
        $(libgimpui)            \
        $(libgimpwidgets)       \
        $(libgimpmodule)        \
@@ -1440,9 +1420,10 @@ max_rgb_LDADD = \
        $(libgimpcolor)         \
        $(libgimpbase)          \
        $(GTK_LIBS)             \
+       $(GEXIV2_LIBS)          \
        $(RT_LIBS)              \
        $(INTLLIBS)             \
-       $(max_rgb_RC)
+       $(metadata_RC)
 
 newsprint_SOURCES = \
        newsprint.c
diff --git a/plug-ins/common/file-jp2-load.c b/plug-ins/common/file-jp2-load.c
index 2803617..0facb3c 100644
--- a/plug-ins/common/file-jp2-load.c
+++ b/plug-ins/common/file-jp2-load.c
@@ -57,7 +57,6 @@ static void     run               (const gchar      *name,
                                    gint             *nreturn_vals,
                                    GimpParam       **return_vals);
 static gint32   load_image        (const gchar      *filename,
-                                   gint32           *layer_ID,
                                    GError          **error);
 static gboolean load_icc_profile  (jas_image_t      *jas_image,
                                    gint              image_ID,
@@ -127,7 +126,6 @@ run (const gchar      *name,
   GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
   gint               image_ID;
   GError            *error = NULL;
-  gint32             layer_ID;
 
   run_mode = param[0].data.d_int32;
 
@@ -156,7 +154,7 @@ run (const gchar      *name,
           break;
         }
 
-      image_ID = load_image (param[1].data.d_string, &layer_ID, &error);
+      image_ID = load_image (param[1].data.d_string, &error);
 
       if (image_ID != -1)
         {
@@ -170,7 +168,7 @@ run (const gchar      *name,
             {
               GimpMetadataLoadFlags flags = GIMP_METADATA_LOAD_ALL;
 
-              gimp_image_metadata_load_finish (image_ID, layer_ID, "image/jp2",
+              gimp_image_metadata_load_finish (image_ID, "image/jp2",
                                                metadata, flags,
                                                interactive);
 
@@ -205,13 +203,13 @@ run (const gchar      *name,
 
 static gint32
 load_image (const gchar  *filename,
-            gint32       *layer_ID,
             GError      **error)
 {
   gint               fd;
   jas_stream_t      *stream;
   gint32             image_ID = -1;
   jas_image_t       *image;
+  gint32             layer_ID;
   GimpImageType      image_type;
   GimpImageBaseType  base_type;
   gint               width;
diff --git a/plug-ins/common/file-png.c b/plug-ins/common/file-png.c
index 12c9030..6efb7f1 100644
--- a/plug-ins/common/file-png.c
+++ b/plug-ins/common/file-png.c
@@ -140,7 +140,6 @@ static void      run                       (const gchar      *name,
                                             GimpParam       **return_vals);
 
 static gint32    load_image                (const gchar      *filename,
-                                            gint32           *layer_ID,
                                             gboolean          interactive,
                                             gboolean         *resolution_loaded,
                                             GError          **error);
@@ -148,7 +147,6 @@ static gboolean  save_image                (const gchar      *filename,
                                             gint32            image_ID,
                                             gint32            drawable_ID,
                                             gint32            orig_image_ID,
-                                            gint             *bits_depth,
                                             GError          **error);
 
 static int       respin_cmap               (png_structp       pp,
@@ -418,7 +416,6 @@ run (const gchar      *name,
   GimpRunMode       run_mode;
   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
   gint32            image_ID;
-  gint32            layer_ID;
   gint32            drawable_ID;
   GError           *error  = NULL;
 
@@ -451,7 +448,6 @@ run (const gchar      *name,
         }
 
       image_ID = load_image (param[1].data.d_string,
-                             &layer_ID,
                              interactive,
                              &resolution_loaded,
                              &error);
@@ -471,7 +467,7 @@ run (const gchar      *name,
               if (resolution_loaded)
                 flags &= ~GIMP_METADATA_LOAD_RESOLUTION;
 
-              gimp_image_metadata_load_finish (image_ID, layer_ID, "image/png",
+              gimp_image_metadata_load_finish (image_ID, "image/png",
                                                metadata, flags,
                                                interactive);
 
@@ -496,7 +492,6 @@ run (const gchar      *name,
       GimpMetadata          *metadata;
       GimpMetadataSaveFlags  metadata_flags;
       gint32                 orig_image_ID;
-      gint                   bits_depth;
       GimpExportReturn       export = GIMP_EXPORT_CANCEL;
       gboolean               alpha;
 
@@ -530,8 +525,8 @@ run (const gchar      *name,
         }
 
       metadata = gimp_image_metadata_save_prepare (orig_image_ID,
-                                                     "image/png",
-                                                     &metadata_flags);
+                                                   "image/png",
+                                                   &metadata_flags);
 
       pngvals.save_exif      = (metadata_flags & GIMP_METADATA_SAVE_EXIF) != 0;
       pngvals.save_xmp       = (metadata_flags & GIMP_METADATA_SAVE_XMP) != 0;
@@ -613,7 +608,7 @@ run (const gchar      *name,
       if (status == GIMP_PDB_SUCCESS)
         {
           if (save_image (param[3].data.d_string,
-                          image_ID, drawable_ID, orig_image_ID, &bits_depth, &error))
+                          image_ID, drawable_ID, orig_image_ID, &error))
             {
               if (metadata)
                 {
@@ -642,12 +637,10 @@ run (const gchar      *name,
                     metadata_flags &= ~GIMP_METADATA_SAVE_THUMBNAIL;
 
                   file = g_file_new_for_path (param[3].data.d_string);
-
                   gimp_image_metadata_save_finish (orig_image_ID,
                                                    "image/png",
                                                    metadata, metadata_flags,
                                                    file, NULL);
-                  g_object_unref (metadata);
                   g_object_unref (file);
                 }
 
@@ -662,6 +655,8 @@ run (const gchar      *name,
       if (export == GIMP_EXPORT_EXPORT)
         gimp_image_delete (image_ID);
 
+      if (metadata)
+        g_object_unref (metadata);
     }
   else if (strcmp (name, GET_DEFAULTS_PROC) == 0)
     {
@@ -822,7 +817,6 @@ load_color_profile (png_structp   pp,
  */
 static gint32
 load_image (const gchar  *filename,
-            gint32       *layer_ID,
             gboolean      interactive,
             gboolean     *resolution_loaded,
             GError      **error)
@@ -1356,8 +1350,6 @@ load_image (const gchar  *filename,
       g_object_unref (buffer);
     }
 
-  *layer_ID = layer;
-
   return image;
 }
 
@@ -1435,7 +1427,6 @@ save_image (const gchar  *filename,
             gint32        image_ID,
             gint32        drawable_ID,
             gint32        orig_image_ID,
-            gint         *bits_depth,
             GError      **error)
 {
   gint              i, k;             /* Looping vars */
@@ -1509,8 +1500,6 @@ save_image (const gchar  *filename,
       break;
     }
 
-  *bits_depth = bit_depth;
-
   pp = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   if (!pp)
     {
diff --git a/plug-ins/common/gimprc.common b/plug-ins/common/gimprc.common
index a8e6406..0ff328d 100644
--- a/plug-ins/common/gimprc.common
+++ b/plug-ins/common/gimprc.common
@@ -1,7 +1,6 @@
 align_layers_RC = align-layers.rc.o
 animation_optimize_RC = animation-optimize.rc.o
 animation_play_RC = animation-play.rc.o
-attributes_RC = attributes.rc.o
 blinds_RC = blinds.rc.o
 blur_RC = blur.rc.o
 border_average_RC = border-average.rc.o
@@ -66,10 +65,10 @@ gradient_map_RC = gradient-map.rc.o
 grid_RC = grid.rc.o
 guillotine_RC = guillotine.rc.o
 hot_RC = hot.rc.o
-iptc_RC = iptc.rc.o
 jigsaw_RC = jigsaw.rc.o
 mail_RC = mail.rc.o
 max_rgb_RC = max-rgb.rc.o
+metadata_RC = metadata.rc.o
 newsprint_RC = newsprint.rc.o
 nl_filter_RC = nl-filter.rc.o
 oilify_RC = oilify.rc.o
diff --git a/plug-ins/common/plugin-defs.pl b/plug-ins/common/plugin-defs.pl
index 4c79517..324e7da 100644
--- a/plug-ins/common/plugin-defs.pl
+++ b/plug-ins/common/plugin-defs.pl
@@ -2,7 +2,6 @@
     'align-layers' => { ui => 1 },
     'animation-optimize' => {},
     'animation-play' => { ui => 1, gegl => 1 },
-    'attributes' => { ui => 1, gegl => 1 },
     'blinds' => { ui => 1 },
     'blur' => {},
     'border-average' => { ui => 1, gegl => 1 },
@@ -67,10 +66,10 @@
     'grid' => { ui => 1 },
     'guillotine' => {},
     'hot' => { ui => 1 },
-    'iptc' => { ui => 1, libs => 'GEXIV2_LIBS', cflags => 'GEXIV2_CFLAGS' },
     'jigsaw' => { ui => 1 },
     'mail' => { ui => 1, optional => 1 },
     'max-rgb' => { ui => 1 },
+    'metadata' => { ui => 1, libs => 'GEXIV2_LIBS', cflags => 'GEXIV2_CFLAGS' },
     'newsprint' => { ui => 1 },
     'nl-filter' => { ui => 1 },
     'oilify' => { ui => 1 },
diff --git a/plug-ins/file-jpeg/jpeg-load.c b/plug-ins/file-jpeg/jpeg-load.c
index ed1ac6b..6cc945f 100644
--- a/plug-ins/file-jpeg/jpeg-load.c
+++ b/plug-ins/file-jpeg/jpeg-load.c
@@ -58,13 +58,12 @@ gint32           preview_layer_ID;
 gint32
 load_image (const gchar  *filename,
             GimpRunMode   runmode,
-            gint32       *layer_ID,
             gboolean      preview,
             gboolean     *resolution_loaded,
             GError      **error)
 {
   gint32 volatile  image_ID;
-  gint32           _layer_ID;
+  gint32           layer_ID;
   struct jpeg_decompress_struct cinfo;
   struct my_error_mgr           jerr;
   jpeg_saved_marker_ptr         marker;
@@ -233,11 +232,11 @@ load_image (const gchar  *filename,
                                          cinfo.output_width,
                                          cinfo.output_height,
                                          layer_type, 100, GIMP_NORMAL_MODE);
-      _layer_ID = preview_layer_ID;
+      layer_ID = preview_layer_ID;
     }
   else
     {
-      _layer_ID = gimp_layer_new (image_ID, _("Background"),
+      layer_ID = gimp_layer_new (image_ID, _("Background"),
                                  cinfo.output_width,
                                  cinfo.output_height,
                                  layer_type, 100, GIMP_NORMAL_MODE);
@@ -344,7 +343,7 @@ load_image (const gchar  *filename,
    * loop counter, so that we don't have to keep track ourselves.
    */
 
-  buffer = gimp_drawable_get_buffer (_layer_ID);
+  buffer = gimp_drawable_get_buffer (layer_ID);
   format = babl_format (image_type == GIMP_RGB ? "R'G'B' u8" : "Y' u8");
 
   while (cinfo.output_scanline < cinfo.output_height)
@@ -413,9 +412,7 @@ load_image (const gchar  *filename,
       gimp_progress_update (1.0);
     }
 
-  gimp_image_insert_layer (image_ID, _layer_ID, -1, 0);
-
-  *layer_ID = _layer_ID;
+  gimp_image_insert_layer (image_ID, layer_ID, -1, 0);
 
   return image_ID;
 }
diff --git a/plug-ins/file-jpeg/jpeg-load.h b/plug-ins/file-jpeg/jpeg-load.h
index 281e03d..d4e61b0 100644
--- a/plug-ins/file-jpeg/jpeg-load.h
+++ b/plug-ins/file-jpeg/jpeg-load.h
@@ -20,7 +20,6 @@
 
 gint32 load_image           (const gchar  *filename,
                              GimpRunMode   runmode,
-                             gint32       *layer_ID,
                              gboolean      preview,
                              gboolean     *resolution_loaded,
                              GError      **error);
diff --git a/plug-ins/file-jpeg/jpeg-save.c b/plug-ins/file-jpeg/jpeg-save.c
index e01cef6..c38ff5c 100644
--- a/plug-ins/file-jpeg/jpeg-save.c
+++ b/plug-ins/file-jpeg/jpeg-save.c
@@ -188,7 +188,6 @@ background_jpeg_save (PreviewPersistent *pp)
           GFile     *file = g_file_new_for_path (pp->file_name);
           GFileInfo *info;
           gchar     *text;
-          gint32     layer_ID;
           GError    *error = NULL;
 
           info = g_file_query_info (file,
@@ -219,7 +218,7 @@ background_jpeg_save (PreviewPersistent *pp)
           g_object_unref (file);
 
           /* and load the preview */
-          load_image (pp->file_name, GIMP_RUN_NONINTERACTIVE, &layer_ID, TRUE, NULL, NULL);
+          load_image (pp->file_name, GIMP_RUN_NONINTERACTIVE, TRUE, NULL, NULL);
         }
 
       /* we cleanup here (load_image doesn't run in the background) */
diff --git a/plug-ins/file-jpeg/jpeg.c b/plug-ins/file-jpeg/jpeg.c
index 298d1e3..5808348 100644
--- a/plug-ins/file-jpeg/jpeg.c
+++ b/plug-ins/file-jpeg/jpeg.c
@@ -173,7 +173,6 @@ run (const gchar      *name,
   GimpRunMode        run_mode;
   GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
   gint32             image_ID;
-  gint32             layer_ID;
   gint32             drawable_ID;
   GimpParasite      *parasite;
   GError            *error  = NULL;
@@ -211,7 +210,7 @@ run (const gchar      *name,
           break;
         }
 
-      image_ID = load_image (param[1].data.d_string, run_mode, &layer_ID, FALSE,
+      image_ID = load_image (param[1].data.d_string, run_mode, FALSE,
                              &resolution_loaded, &error);
 
       if (image_ID != -1)
@@ -224,12 +223,12 @@ run (const gchar      *name,
 
           if (metadata)
             {
-              GimpMetadataLoadFlags  flags = GIMP_METADATA_LOAD_ALL;
+              GimpMetadataLoadFlags flags = GIMP_METADATA_LOAD_ALL;
 
               if (resolution_loaded)
                 flags &= ~GIMP_METADATA_LOAD_RESOLUTION;
 
-              gimp_image_metadata_load_finish (image_ID, layer_ID, "image/jpeg",
+              gimp_image_metadata_load_finish (image_ID, "image/jpeg",
                                                metadata, flags,
                                                load_interactive);
 
@@ -575,6 +574,7 @@ run (const gchar      *name,
               g_object_unref (file);
             }
         }
+
       if (metadata)
         g_object_unref (metadata);
     }
diff --git a/plug-ins/file-psd/psd.c b/plug-ins/file-psd/psd.c
index f8cb84f..0a52c00 100644
--- a/plug-ins/file-psd/psd.c
+++ b/plug-ins/file-psd/psd.c
@@ -211,7 +211,7 @@ run (const gchar      *name,
               if (resolution_loaded)
                 flags &= ~GIMP_METADATA_LOAD_RESOLUTION;
 
-              gimp_image_metadata_load_finish (image_ID, -1, "image/x-psd",
+              gimp_image_metadata_load_finish (image_ID, "image/x-psd",
                                                metadata, flags,
                                                interactive);
 
@@ -315,8 +315,6 @@ run (const gchar      *name,
                                                metadata, metadata_flags,
                                                file, NULL);
               g_object_unref (file);
-
-              g_object_unref (metadata);
             }
 
           values[0].data.d_status = GIMP_PDB_SUCCESS;
@@ -336,6 +334,8 @@ run (const gchar      *name,
       if (export == GIMP_EXPORT_EXPORT)
         gimp_image_delete (image_ID);
 
+      if (metadata)
+        g_object_unref (metadata);
     }
 
   /* Unknown procedure */
diff --git a/plug-ins/file-tiff/file-tiff-load.c b/plug-ins/file-tiff/file-tiff-load.c
index 34a2b59..fe83b94 100644
--- a/plug-ins/file-tiff/file-tiff-load.c
+++ b/plug-ins/file-tiff/file-tiff-load.c
@@ -219,7 +219,6 @@ load_dialog (TIFF              *tif,
 
 gint32
 load_image (GFile              *file,
-            gint32             *layer_ID,
             TIFF               *tif,
             TiffSelectedPages  *pages,
             gboolean           *resolution_loaded,
@@ -930,8 +929,6 @@ load_image (GFile              *file,
           g_free (name);
         }
 
-      *layer_ID         = layer;
-
       if (! base_format && image_type == GIMP_INDEXED)
         {
           /* can't create the palette format here, need to get it from
diff --git a/plug-ins/file-tiff/file-tiff-load.h b/plug-ins/file-tiff/file-tiff-load.h
index 5695039..372af71 100644
--- a/plug-ins/file-tiff/file-tiff-load.h
+++ b/plug-ins/file-tiff/file-tiff-load.h
@@ -37,7 +37,6 @@ gboolean   load_dialog (TIFF               *tif,
                         TiffSelectedPages  *pages);
 
 gint32     load_image  (GFile              *file,
-                        gint32             *layer_ID,
                         TIFF               *tif,
                         TiffSelectedPages  *pages,
                         gboolean           *resolution_loaded,
diff --git a/plug-ins/file-tiff/file-tiff.c b/plug-ins/file-tiff/file-tiff.c
index d5dd476..aa57870 100644
--- a/plug-ins/file-tiff/file-tiff.c
+++ b/plug-ins/file-tiff/file-tiff.c
@@ -264,14 +264,13 @@ run (const gchar      *name,
 
               if (run_it)
                 {
-                  gint32   image;
-                  gint32   layer_ID;
-                  gboolean resolution_loaded = FALSE;
+                  gint32    image;
+                  gboolean  resolution_loaded = FALSE;
 
                   gimp_set_data (LOAD_PROC,
                                  &pages.target, sizeof (pages.target));
 
-                  image = load_image (file, &layer_ID, tif, &pages,
+                  image = load_image (file, tif, &pages,
                                       &resolution_loaded,
                                       &error);
 
@@ -292,7 +291,7 @@ run (const gchar      *name,
                           if (resolution_loaded)
                             flags &= ~GIMP_METADATA_LOAD_RESOLUTION;
 
-                          gimp_image_metadata_load_finish (image, layer_ID, "image/tiff",
+                          gimp_image_metadata_load_finish (image, "image/tiff",
                                                            metadata, flags,
                                                            run_mode == GIMP_RUN_INTERACTIVE);
 
@@ -472,9 +471,9 @@ run (const gchar      *name,
                    * exiv2 saves them with wrong type and the original values
                    * could be invalid, see also bug 761823
                    */
-                  gimp_metadata_remove_attribute (metadata, "Exif.Image.0x0118");
-                  gimp_metadata_remove_attribute (metadata, "Exif.Image.0x0119");
-                  gimp_metadata_remove_attribute (metadata, "Exif.Image.PageNumber");
+                  gexiv2_metadata_clear_tag (metadata, "Exif.Image.0x0118");
+                  gexiv2_metadata_clear_tag (metadata, "Exif.Image.0x0119");
+                  gexiv2_metadata_clear_tag (metadata, "Exif.Image.PageNumber");
 
                   gimp_metadata_set_bits_per_sample (metadata, saved_bpp);
 
@@ -500,7 +499,6 @@ run (const gchar      *name,
                                                    "image/tiff",
                                                    metadata, metadata_flags,
                                                    file, NULL);
-                  g_object_unref (metadata);
                 }
 
               /*  Store mvals data  */
@@ -517,6 +515,8 @@ run (const gchar      *name,
       if (export == GIMP_EXPORT_EXPORT)
         gimp_image_delete (image);
 
+      if (metadata)
+        g_object_unref (metadata);
     }
   else
     {
diff --git a/plug-ins/ui/Makefile.am b/plug-ins/ui/Makefile.am
index 16de1db..1b569f8 100644
--- a/plug-ins/ui/Makefile.am
+++ b/plug-ins/ui/Makefile.am
@@ -5,8 +5,6 @@ uidata_DATA = \
        plug-in-file-png.ui     \
        plug-in-file-raw.ui     \
        plug-in-file-tiff.ui    \
-       plug-in-attributes.ui   \
-       plug-in-iptc.ui 
-
+       plug-in-metadata.ui
 
 EXTRA_DIST = $(uidata_DATA)
diff --git a/plug-ins/ui/plug-in-metadata.ui b/plug-ins/ui/plug-in-metadata.ui
new file mode 100644
index 0000000..1e34d8d
--- /dev/null
+++ b/plug-ins/ui/plug-in-metadata.ui
@@ -0,0 +1,908 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkListStore" id="exif-liststore">
+    <columns>
+      <!-- column-name c_exif_tag -->
+      <column type="gchararray"/>
+      <!-- column-name c_exif_value -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkListStore" id="xmp-liststore">
+    <columns>
+      <!-- column-name c_xmp_tag -->
+      <column type="gchararray"/>
+      <!-- column-name c_xmp_value -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkVBox" id="metadata-vbox">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkNotebook" id="metadata-notebook">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="scrollable">True</property>
+        <child>
+          <object class="GtkScrolledWindow" id="exif-scroll">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="border_width">6</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTreeView" id="exif-treeview">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="model">exif-liststore</property>
+                <property name="headers_clickable">False</property>
+                <property name="search_column">0</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="exif-treeview-selection"/>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="exif_tag_column">
+                    <property name="resizable">True</property>
+                    <property name="spacing">3</property>
+                    <property name="title" translatable="yes">Exif Tag</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="exif_tag_cell_renderer"/>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="exif_value_column">
+                    <property name="resizable">True</property>
+                    <property name="spacing">3</property>
+                    <property name="title" translatable="yes">Value</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="exif_value_cell_renderer"/>
+                      <attributes>
+                        <attribute name="text">1</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child type="tab">
+          <object class="GtkLabel" id="exif">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xpad">4</property>
+            <property name="ypad">4</property>
+            <property name="label" translatable="yes">Exif</property>
+          </object>
+          <packing>
+            <property name="tab_expand">True</property>
+            <property name="tab_fill">False</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="xmp-scroll">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="border_width">6</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTreeView" id="xm-ptreeview">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="model">xmp-liststore</property>
+                <property name="headers_clickable">False</property>
+                <property name="search_column">0</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="xmp-treeview-selection"/>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="xmp_tag_column">
+                    <property name="resizable">True</property>
+                    <property name="spacing">3</property>
+                    <property name="title" translatable="yes">XMP Tag</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="xmp_tag_cell_renderer"/>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="xmp_value_column">
+                    <property name="resizable">True</property>
+                    <property name="spacing">3</property>
+                    <property name="title" translatable="yes">Value</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="xmp_value_cell_renderer"/>
+                      <attributes>
+                        <attribute name="text">1</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child type="tab">
+          <object class="GtkLabel" id="xmp">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xpad">4</property>
+            <property name="ypad">4</property>
+            <property name="label" translatable="yes">XMP</property>
+          </object>
+          <packing>
+            <property name="position">1</property>
+            <property name="tab_fill">False</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkVBox" id="box1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="border_width">6</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkNotebook" id="iptc-notebook">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <child>
+                  <object class="GtkVBox" id="box2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkTable" id="desctable">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="border_width">6</property>
+                        <property name="n_rows">8</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">3</property>
+                        <property name="row_spacing">3</property>
+                        <child>
+                          <object class="GtkLabel" id="l_title">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Title</property>
+                            <property name="single_line_mode">True</property>
+                          </object>
+                          <packing>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_author">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Author</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_authortitle">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Authortitle</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_copyright">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Copyright</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_caption">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Caption</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">4</property>
+                            <property name="bottom_attach">5</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_captionwriter">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Captionwriter</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">5</property>
+                            <property name="bottom_attach">6</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_headline">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Headline</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">6</property>
+                            <property name="bottom_attach">7</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_specialinstruct">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Special
+Instructions</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">7</property>
+                            <property name="bottom_attach">8</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.ObjectName">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.Byline">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.BylineTitle">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.Copyright">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.Writer">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">5</property>
+                            <property name="bottom_attach">6</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkScrolledWindow" id="caption_scroll">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="shadow_type">in</property>
+                            <child>
+                              <object class="GtkTextView" id="Iptc.Application2.Caption">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">4</property>
+                            <property name="bottom_attach">5</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkScrolledWindow" id="headline_scroll">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="shadow_type">in</property>
+                            <child>
+                              <object class="GtkTextView" id="Iptc.Application2.Headline">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">6</property>
+                            <property name="bottom_attach">7</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkScrolledWindow" id="instruct_scroll">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="shadow_type">in</property>
+                            <child>
+                              <object class="GtkTextView" id="Iptc.Application2.SpecialInstructions">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">7</property>
+                            <property name="bottom_attach">8</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel" id="iptcdesc">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xpad">2</property>
+                    <property name="ypad">2</property>
+                    <property name="label" translatable="yes">Description</property>
+                  </object>
+                  <packing>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkVBox" id="box3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkTable" id="table3">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="border_width">6</property>
+                        <property name="n_rows">4</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">3</property>
+                        <property name="row_spacing">3</property>
+                        <child>
+                          <object class="GtkLabel" id="l_keywords1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Keywords</property>
+                          </object>
+                          <packing>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_category1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Category</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_suppcat1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Supplemental
+Category</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_urgency1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Urgency</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkScrolledWindow" id="scrolledwindow10">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="shadow_type">in</property>
+                            <child>
+                              <object class="GtkTextView" id="Iptc.Application2.Keywords">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkScrolledWindow" id="scrolledwindow12">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="shadow_type">in</property>
+                            <child>
+                              <object class="GtkTextView" id="Iptc.Application2.SuppCategory">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.Urgency">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.Category">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel" id="iptckeys">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xpad">2</property>
+                    <property name="ypad">2</property>
+                    <property name="label" translatable="yes">Keywords/Categories</property>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkVBox" id="box4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkTable" id="table4">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="border_width">6</property>
+                        <property name="n_rows">9</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">3</property>
+                        <property name="row_spacing">3</property>
+                        <child>
+                          <object class="GtkHSeparator" id="hseparator4">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                          </object>
+                          <packing>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_credit">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Credit</property>
+                          </object>
+                          <packing>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_source">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Source</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.Credit">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.Source">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_transmission">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Transmission
+reference</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">8</property>
+                            <property name="bottom_attach">9</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.TransmissionReference">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">8</property>
+                            <property name="bottom_attach">9</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_city">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">City</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.City">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_sublocation">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Sublocation</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">4</property>
+                            <property name="bottom_attach">5</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.SubLocation">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">4</property>
+                            <property name="bottom_attach">5</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_province">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">3</property>
+                            <property name="ypad">3</property>
+                            <property name="label" translatable="yes">Province/State</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">5</property>
+                            <property name="bottom_attach">6</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.ProvinceState">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">5</property>
+                            <property name="bottom_attach">6</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="l_country">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Country</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">6</property>
+                            <property name="bottom_attach">7</property>
+                            <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="Iptc.Application2.CountryName">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">●</property>
+                            <property name="invisible_char_set">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">6</property>
+                            <property name="bottom_attach">7</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHSeparator" id="hseparator2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                          </object>
+                          <packing>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">7</property>
+                            <property name="bottom_attach">8</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel" id="iptccredits">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xpad">2</property>
+                    <property name="ypad">2</property>
+                    <property name="label" translatable="yes">Credits/Origin</property>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="iptc-write-button">
+                <property name="label" translatable="yes">Write IPTC Data</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child type="tab">
+          <object class="GtkLabel" id="iptc">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xpad">4</property>
+            <property name="ypad">4</property>
+            <property name="label" translatable="yes">IPTC</property>
+          </object>
+          <packing>
+            <property name="position">2</property>
+            <property name="tab_fill">False</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/po-plug-ins/POTFILES.in b/po-plug-ins/POTFILES.in
index 10c4437..2d3c511 100644
--- a/po-plug-ins/POTFILES.in
+++ b/po-plug-ins/POTFILES.in
@@ -6,7 +6,6 @@
 plug-ins/common/align-layers.c
 plug-ins/common/animation-optimize.c
 plug-ins/common/animation-play.c
-plug-ins/common/attributes.c
 plug-ins/common/blinds.c
 plug-ins/common/blur.c
 plug-ins/common/border-average.c
@@ -74,6 +73,7 @@ plug-ins/common/hot.c
 plug-ins/common/jigsaw.c
 plug-ins/common/mail.c
 plug-ins/common/max-rgb.c
+plug-ins/common/metadata.c
 plug-ins/common/newsprint.c
 plug-ins/common/nl-filter.c
 plug-ins/common/oilify.c
@@ -159,8 +159,7 @@ plug-ins/gimpressionist/utils.c
 [type: gettext/glade]plug-ins/ui/plug-in-file-png.ui
 [type: gettext/glade]plug-ins/ui/plug-in-file-raw.ui
 [type: gettext/glade]plug-ins/ui/plug-in-file-tiff.ui
-[type: gettext/glade]plug-ins/ui/plug-in-metainfo.ui
-[type: gettext/glade]plug-ins/ui/plug-in-attributes.ui
+[type: gettext/glade]plug-ins/ui/plug-in-metadata.ui
 plug-ins/gradient-flare/gradient-flare.c
 plug-ins/help-browser/dialog.c
 plug-ins/help-browser/help-browser.c
@@ -218,11 +217,6 @@ plug-ins/lighting/lighting-ui.c
 plug-ins/map-object/map-object-apply.c
 plug-ins/map-object/map-object-main.c
 plug-ins/map-object/map-object-ui.c
-plug-ins/metainfo/interface.c
-plug-ins/metainfo/page-administration.c
-plug-ins/metainfo/page-rights.c
-plug-ins/metainfo/page-description.c
-plug-ins/metainfo/page-artwork.c
 plug-ins/pagecurl/pagecurl.c
 plug-ins/print/print-draw-page.c
 plug-ins/print/print-page-layout.c
diff --git a/tools/pdbgen/pdb/item.pdb b/tools/pdbgen/pdb/item.pdb
index 2aff3cf..b6f5ff9 100644
--- a/tools/pdbgen/pdb/item.pdb
+++ b/tools/pdbgen/pdb/item.pdb
@@ -783,61 +783,6 @@ CODE
     );
 }
 
-sub item_get_metadata {
-    $blurb = "Returns the item's metadata.";
-    $help  = 'Returns metadata from the item.';
-
-    &std_pdb_misc('2016', '2.10');
-
-    @inargs = (
-        { name => 'item', type => 'item',
-          desc => 'The item' }
-    );
-
-    @outargs = (
-       { name => 'metadata_string', type => 'string', wrap => 1,
-         desc => 'The metadata as a xml string'}
-    );
-
-    %invoke = (
-       code => <<'CODE'
-{
-  GimpMetadata *metadata = gimp_item_get_metadata (item);
-
-  if (metadata)
-    metadata_string = gimp_metadata_serialize (metadata);
-}
-CODE
-    );
-}
-
-sub item_set_metadata {
-    $blurb = "Set the item's metadata.";
-    $help  = 'Sets metadata on the item.';
-
-    &std_pdb_misc('2016', '2.10');
-
-    @inargs = (
-        { name => 'item', type => 'item',
-          desc => 'The item' },
-       { name => 'metadata_string', type => 'string', wrap => 1,
-         desc => 'The metadata as a xml string' }
-    );
-
-    %invoke = (
-       code => <<'CODE'
-{
-  GimpMetadata *metadata = gimp_metadata_deserialize (metadata_string);
-
-  gimp_item_set_metadata (item, metadata, TRUE);
-
-  if (metadata)
-    g_object_unref (metadata);
-}
-CODE
-    );
-}
-
 sub item_attach_parasite {
     $blurb = 'Add a parasite to an item.';
 
@@ -951,12 +896,10 @@ CODE
 }
 
 @headers = qw("core/gimplayermask.h"
-              "libgimpbase/gimpbase.h"
               "core/gimplist.h"
               "core/gimpselection.h"
-              "core/gimpitem.h"
               "text/gimptextlayer.h"
-              "vectors/gimpvectors.h"
+             "vectors/gimpvectors.h"
               "gimppdb-utils.h"
               "gimppdbcontext.h"
               "gimp-intl.h");
@@ -967,13 +910,13 @@ CODE
             item_is_drawable
             item_is_layer
             item_is_text_layer
-            item_is_channel
-            item_is_layer_mask
-            item_is_selection
-            item_is_vectors
-            item_is_group
+           item_is_channel
+           item_is_layer_mask
+           item_is_selection
+           item_is_vectors
+           item_is_group
             item_get_parent
-            item_get_children
+           item_get_children
             item_get_name item_set_name
             item_get_visible item_set_visible
             item_get_linked item_set_linked
@@ -981,10 +924,9 @@ CODE
             item_get_lock_position item_set_lock_position
             item_get_color_tag item_set_color_tag
             item_get_tattoo item_set_tattoo
-            item_get_metadata item_set_metadata
-            item_attach_parasite item_detach_parasite
-            item_get_parasite
-            item_get_parasite_list);
+           item_attach_parasite item_detach_parasite
+           item_get_parasite
+           item_get_parasite_list);
 
 %exports = (app => [@procs], lib => [@procs]);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]