2013-10-20 00:38:01 +08:00
|
|
|
/* LIBGIMPBASE - The GIMP Basic Library
|
|
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
|
|
*
|
|
|
|
* gimpmetadata.c
|
|
|
|
* Copyright (C) 2013 Hartmut Kuhse <hartmutkuhse@src.gnome.org>
|
2013-10-28 04:11:19 +08:00
|
|
|
* Michael Natterer <mitch@gimp.org>
|
2013-10-20 00:38:01 +08:00
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <gio/gio.h>
|
|
|
|
#include <gexiv2/gexiv2.h>
|
|
|
|
|
2013-11-02 00:36:26 +08:00
|
|
|
#include "libgimpmath/gimpmath.h"
|
|
|
|
|
2013-10-20 00:38:01 +08:00
|
|
|
#include "gimpbasetypes.h"
|
|
|
|
|
2013-11-02 00:01:44 +08:00
|
|
|
#include "gimplimits.h"
|
2013-10-20 00:38:01 +08:00
|
|
|
#include "gimpmetadata.h"
|
|
|
|
#include "gimpunit.h"
|
|
|
|
|
|
|
|
#include "libgimp/libgimp-intl.h"
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
typedef struct _GimpMetadataPrivate GimpMetadataPrivate;
|
2018-05-03 18:51:36 +08:00
|
|
|
typedef struct _GimpMetadataClass GimpMetadataClass;
|
2017-01-30 23:42:27 +08:00
|
|
|
|
|
|
|
struct _GimpMetadata
|
|
|
|
{
|
|
|
|
GExiv2Metadata parent_instance;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _GimpMetadataPrivate
|
|
|
|
{
|
2017-01-31 00:05:23 +08:00
|
|
|
/* dummy entry to avoid a critical warning due to size 0 */
|
|
|
|
gpointer _gimp_reserved1;
|
2017-01-30 23:42:27 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct _GimpMetadataClass
|
|
|
|
{
|
|
|
|
GExiv2MetadataClass parent_class;
|
|
|
|
|
|
|
|
/* Padding for future expansion */
|
|
|
|
void (*_gimp_reserved1) (void);
|
|
|
|
void (*_gimp_reserved2) (void);
|
|
|
|
void (*_gimp_reserved3) (void);
|
|
|
|
void (*_gimp_reserved4) (void);
|
|
|
|
void (*_gimp_reserved5) (void);
|
|
|
|
void (*_gimp_reserved6) (void);
|
|
|
|
void (*_gimp_reserved7) (void);
|
|
|
|
void (*_gimp_reserved8) (void);
|
|
|
|
};
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
**/
|
2013-10-28 04:11:19 +08:00
|
|
|
|
|
|
|
|
2017-09-03 21:46:17 +08:00
|
|
|
#define GIMP_METADATA_ERROR gimp_metadata_error_quark ()
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
static GQuark gimp_metadata_error_quark (void);
|
|
|
|
static void gimp_metadata_add (GimpMetadata *src,
|
|
|
|
GimpMetadata *dest);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
|
|
|
|
|
|
|
static const gchar *tiff_tags[] =
|
|
|
|
{
|
|
|
|
"Xmp.tiff",
|
|
|
|
"Exif.Image.ImageWidth",
|
|
|
|
"Exif.Image.ImageLength",
|
|
|
|
"Exif.Image.BitsPerSample",
|
|
|
|
"Exif.Image.Compression",
|
|
|
|
"Exif.Image.PhotometricInterpretation",
|
|
|
|
"Exif.Image.FillOrder",
|
|
|
|
"Exif.Image.SamplesPerPixel",
|
|
|
|
"Exif.Image.StripOffsets",
|
|
|
|
"Exif.Image.RowsPerStrip",
|
|
|
|
"Exif.Image.StripByteCounts",
|
|
|
|
"Exif.Image.PlanarConfiguration"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const gchar *jpeg_tags[] =
|
|
|
|
{
|
|
|
|
"Exif.Image.JPEGProc",
|
|
|
|
"Exif.Image.JPEGInterchangeFormat",
|
|
|
|
"Exif.Image.JPEGInterchangeFormatLength",
|
|
|
|
"Exif.Image.JPEGRestartInterval",
|
|
|
|
"Exif.Image.JPEGLosslessPredictors",
|
|
|
|
"Exif.Image.JPEGPointTransforms",
|
|
|
|
"Exif.Image.JPEGQTables",
|
|
|
|
"Exif.Image.JPEGDCTables",
|
|
|
|
"Exif.Image.JPEGACTables"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const gchar *unsupported_tags[] =
|
|
|
|
{
|
|
|
|
"Exif.Image.SubIFDs",
|
|
|
|
"Exif.Image.ClipPath",
|
|
|
|
"Exif.Image.XClipPathUnits",
|
|
|
|
"Exif.Image.YClipPathUnits",
|
|
|
|
"Exif.Image.XPTitle",
|
|
|
|
"Exif.Image.XPComment",
|
|
|
|
"Exif.Image.XPAuthor",
|
|
|
|
"Exif.Image.XPKeywords",
|
|
|
|
"Exif.Image.XPSubject",
|
|
|
|
"Exif.Image.DNGVersion",
|
|
|
|
"Exif.Image.DNGBackwardVersion",
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Iop"
|
|
|
|
};
|
2013-10-20 00:38:01 +08:00
|
|
|
|
|
|
|
static const guint8 minimal_exif[] =
|
|
|
|
{
|
|
|
|
0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
|
|
|
|
0x01, 0x01, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x00, 0xff, 0xe1
|
|
|
|
};
|
|
|
|
|
|
|
|
static const guint8 wilber_jpg[] =
|
|
|
|
{
|
|
|
|
0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
|
|
|
|
0x01, 0x01, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
|
|
|
|
0x00, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x50, 0x46, 0x41, 0x46, 0x5a,
|
|
|
|
0x55, 0x50, 0x5f, 0x78, 0xc8, 0x82, 0x78, 0x6e, 0x6e, 0x78, 0xf5, 0xaf,
|
|
|
|
0xb9, 0x91, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x55, 0x5a,
|
|
|
|
0x5a, 0x78, 0x69, 0x78, 0xeb, 0x82, 0x82, 0xeb, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, 0x10, 0x00, 0x10, 0x03,
|
|
|
|
0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
|
|
|
|
0x16, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0xff, 0xc4, 0x00,
|
|
|
|
0x1e, 0x10, 0x00, 0x01, 0x05, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x03, 0x11, 0x31,
|
|
|
|
0x04, 0x12, 0x51, 0x61, 0x71, 0xff, 0xc4, 0x00, 0x14, 0x01, 0x01, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x14, 0x11, 0x01, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
|
|
|
|
0x00, 0x3f, 0x00, 0x18, 0xa0, 0x0e, 0x6d, 0xbc, 0xf5, 0xca, 0xf7, 0x78,
|
|
|
|
0xb6, 0xfe, 0x3b, 0x23, 0xb2, 0x1d, 0x64, 0x68, 0xf0, 0x8a, 0x39, 0x4b,
|
|
|
|
0x74, 0x9c, 0xa5, 0x5f, 0x35, 0x8a, 0xb2, 0x7e, 0xa0, 0xff, 0xd9, 0x00
|
|
|
|
};
|
|
|
|
|
|
|
|
static const guint wilber_jpg_len = G_N_ELEMENTS (wilber_jpg);
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (GimpMetadata, gimp_metadata, GEXIV2_TYPE_METADATA)
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_metadata_class_init (GimpMetadataClass *klass)
|
|
|
|
{
|
2017-07-08 01:09:59 +08:00
|
|
|
if (! gexiv2_metadata_register_xmp_namespace ("http://ns.adobe.com/DICOM/",
|
|
|
|
"DICOM"))
|
|
|
|
{
|
|
|
|
g_printerr ("Failed to register XMP namespace 'DICOM'\n");
|
|
|
|
}
|
2017-07-06 07:24:54 +08:00
|
|
|
|
2018-01-09 14:58:01 +08:00
|
|
|
if (! gexiv2_metadata_register_xmp_namespace ("http://darktable.sf.net/",
|
|
|
|
"darktable"))
|
|
|
|
{
|
|
|
|
g_printerr ("Failed to register XMP namespace 'darktable'\n");
|
|
|
|
}
|
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
/* Usage example Xmp.GIMP.tagname */
|
|
|
|
if (! gexiv2_metadata_register_xmp_namespace ("http://www.gimp.org/xmp/",
|
|
|
|
"GIMP"))
|
2017-07-06 07:24:54 +08:00
|
|
|
{
|
2017-07-08 01:09:59 +08:00
|
|
|
g_printerr ("Failed to register XMP namespace 'GIMP'\n");
|
2017-07-06 07:24:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
static void
|
|
|
|
gimp_metadata_init (GimpMetadata *metadata)
|
2017-07-06 07:24:54 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_metadata_get_guid:
|
|
|
|
*
|
|
|
|
* Generate Version 4 UUID/GUID.
|
|
|
|
*
|
|
|
|
* Return value: The new GUID/UUID string.
|
|
|
|
*
|
|
|
|
* Since: 2.10
|
|
|
|
*/
|
2017-07-08 01:09:59 +08:00
|
|
|
gchar *
|
2017-07-06 07:24:54 +08:00
|
|
|
gimp_metadata_get_guid (void)
|
|
|
|
{
|
2017-07-16 20:01:18 +08:00
|
|
|
GRand *rand;
|
|
|
|
gint bake;
|
|
|
|
gchar *GUID;
|
|
|
|
const gchar *szHex = "0123456789abcdef-";
|
2017-07-06 07:24:54 +08:00
|
|
|
|
2017-07-16 20:01:18 +08:00
|
|
|
rand = g_rand_new ();
|
2017-07-06 07:24:54 +08:00
|
|
|
|
2017-07-16 20:01:18 +08:00
|
|
|
#define DALLOC 36
|
|
|
|
|
2017-07-17 14:20:46 +08:00
|
|
|
GUID = g_malloc0 (DALLOC + 1);
|
2017-07-06 07:24:54 +08:00
|
|
|
|
|
|
|
for (bake = 0; bake < DALLOC; bake++)
|
2017-07-08 01:09:59 +08:00
|
|
|
{
|
2017-07-16 20:01:18 +08:00
|
|
|
gint r = g_rand_int (rand) % 16;
|
2017-07-08 01:09:59 +08:00
|
|
|
gchar c = ' ';
|
2017-07-06 07:24:54 +08:00
|
|
|
|
|
|
|
switch (bake)
|
2017-07-08 01:09:59 +08:00
|
|
|
{
|
|
|
|
default:
|
|
|
|
c = szHex [r];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 19 :
|
|
|
|
c = szHex [(r & 0x03) | 0x08];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
case 13:
|
|
|
|
case 18:
|
|
|
|
case 23:
|
|
|
|
c = '-';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 14:
|
|
|
|
c = '4';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
GUID[bake] = (bake < DALLOC) ? c : 0x00;
|
|
|
|
}
|
2017-07-06 07:24:54 +08:00
|
|
|
|
2017-07-16 20:01:18 +08:00
|
|
|
g_rand_free (rand);
|
|
|
|
|
2017-07-06 07:24:54 +08:00
|
|
|
return GUID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_metadata_add_history:
|
|
|
|
*
|
|
|
|
* Add XMP mm History data to file metadata.
|
|
|
|
*
|
|
|
|
* Since: 2.10
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
gimp_metadata_add_xmp_history (GimpMetadata *metadata,
|
2017-07-08 01:09:59 +08:00
|
|
|
gchar *state_status)
|
2017-07-06 07:24:54 +08:00
|
|
|
{
|
|
|
|
time_t now;
|
|
|
|
struct tm* now_tm;
|
|
|
|
char timestr[256];
|
|
|
|
char tzstr[7];
|
|
|
|
gchar iid_data[256];
|
|
|
|
gchar strdata[1024];
|
|
|
|
gchar tagstr[1024];
|
|
|
|
gchar *uuid;
|
2017-07-08 01:09:59 +08:00
|
|
|
gchar *did;
|
|
|
|
gchar *odid;
|
2017-07-06 07:24:54 +08:00
|
|
|
gint id_count;
|
|
|
|
gint found;
|
|
|
|
gint lastfound;
|
2017-08-11 22:34:24 +08:00
|
|
|
gint count;
|
|
|
|
int ii;
|
2017-07-06 07:24:54 +08:00
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
static const gchar *tags[] =
|
|
|
|
{
|
|
|
|
"Xmp.xmpMM.InstanceID",
|
|
|
|
"Xmp.xmpMM.DocumentID",
|
|
|
|
"Xmp.xmpMM.OriginalDocumentID",
|
|
|
|
"Xmp.xmpMM.History"
|
|
|
|
};
|
2017-07-06 07:24:54 +08:00
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
static const gchar *history_tags[] =
|
|
|
|
{
|
|
|
|
"/stEvt:action",
|
|
|
|
"/stEvt:instanceID",
|
|
|
|
"/stEvt:when",
|
|
|
|
"/stEvt:softwareAgent",
|
|
|
|
"/stEvt:changed"
|
|
|
|
};
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_METADATA (metadata));
|
2017-07-06 07:24:54 +08:00
|
|
|
|
|
|
|
/* Update new Instance ID */
|
2017-07-08 01:09:59 +08:00
|
|
|
uuid = gimp_metadata_get_guid ();
|
|
|
|
|
|
|
|
strcpy (iid_data, "xmp.iid:");
|
|
|
|
strcat (iid_data, uuid);
|
|
|
|
|
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
tags[0], iid_data);
|
|
|
|
g_free (uuid);
|
2017-07-06 07:24:54 +08:00
|
|
|
|
|
|
|
/* Update new Document ID if none found */
|
2017-07-08 01:09:59 +08:00
|
|
|
did = gexiv2_metadata_get_tag_interpreted_string (GEXIV2_METADATA (metadata),
|
|
|
|
tags[1]);
|
|
|
|
if (! did || ! strlen (did))
|
2017-07-06 07:24:54 +08:00
|
|
|
{
|
|
|
|
gchar did_data[256];
|
2017-07-08 01:09:59 +08:00
|
|
|
|
|
|
|
uuid = gimp_metadata_get_guid ();
|
|
|
|
|
|
|
|
strcpy (did_data, "gimp:docid:gimp:");
|
|
|
|
strcat (did_data, uuid);
|
|
|
|
|
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
tags[1], did_data);
|
|
|
|
g_free (uuid);
|
2017-07-06 07:24:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Update new Original Document ID if none found */
|
2017-07-08 01:09:59 +08:00
|
|
|
odid = gexiv2_metadata_get_tag_interpreted_string (GEXIV2_METADATA (metadata),
|
|
|
|
tags[2]);
|
|
|
|
if (! odid || ! strlen (odid))
|
2017-07-06 07:24:54 +08:00
|
|
|
{
|
2017-07-08 01:09:59 +08:00
|
|
|
gchar did_data[256];
|
|
|
|
gchar *uuid = gimp_metadata_get_guid ();
|
|
|
|
|
|
|
|
strcpy (did_data, "xmp.did:");
|
|
|
|
strcat (did_data, uuid);
|
|
|
|
|
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
tags[2], did_data);
|
|
|
|
g_free (uuid);
|
2017-07-06 07:24:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle Xmp.xmpMM.History */
|
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
gexiv2_metadata_set_xmp_tag_struct (GEXIV2_METADATA (metadata),
|
|
|
|
tags[3],
|
|
|
|
GEXIV2_STRUCTURE_XA_SEQ);
|
2017-07-06 07:24:54 +08:00
|
|
|
|
|
|
|
/* Find current number of entries for Xmp.xmpMM.History */
|
|
|
|
found = 0;
|
2017-08-11 22:34:24 +08:00
|
|
|
for (count = 1; count < 65536; count++)
|
2017-07-06 07:24:54 +08:00
|
|
|
{
|
|
|
|
lastfound = 0;
|
2017-08-11 22:34:24 +08:00
|
|
|
for (ii = 0; ii < 5; ii++)
|
2017-07-06 07:24:54 +08:00
|
|
|
{
|
2017-07-08 01:09:59 +08:00
|
|
|
g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
|
|
|
|
tags[3], count, history_tags[ii]);
|
|
|
|
|
|
|
|
if (gexiv2_metadata_has_tag (GEXIV2_METADATA (metadata),
|
|
|
|
tagstr))
|
2017-07-06 07:24:54 +08:00
|
|
|
{
|
|
|
|
lastfound = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lastfound == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
found++;
|
|
|
|
}
|
|
|
|
|
|
|
|
id_count = found + 1;
|
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
memset (tagstr, 0, sizeof (tagstr));
|
|
|
|
memset (strdata, 0, sizeof (strdata));
|
|
|
|
|
|
|
|
g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
|
|
|
|
tags[3], id_count, history_tags[0]);
|
|
|
|
|
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
tagstr, "saved");
|
|
|
|
|
|
|
|
memset (tagstr, 0, sizeof (tagstr));
|
|
|
|
memset (strdata, 0, sizeof (strdata));
|
|
|
|
|
|
|
|
uuid = gimp_metadata_get_guid ();
|
|
|
|
|
|
|
|
g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
|
|
|
|
tags[3], id_count, history_tags[1]);
|
|
|
|
g_snprintf (strdata, sizeof (strdata), "xmp.iid:%s",
|
|
|
|
uuid);
|
|
|
|
|
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
tagstr, strdata);
|
|
|
|
g_free(uuid);
|
|
|
|
|
|
|
|
memset (tagstr, 0, sizeof (tagstr));
|
|
|
|
memset (strdata, 0, sizeof (strdata));
|
|
|
|
|
|
|
|
g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
|
|
|
|
tags[3], id_count, history_tags[2]);
|
2017-07-06 07:24:54 +08:00
|
|
|
|
|
|
|
/* get local time */
|
2017-07-08 01:09:59 +08:00
|
|
|
time (&now);
|
|
|
|
now_tm = localtime (&now);
|
2017-07-06 07:24:54 +08:00
|
|
|
|
|
|
|
/* get timezone and fix format */
|
|
|
|
strftime (tzstr, 7, "%z", now_tm);
|
|
|
|
tzstr[5] = tzstr[4];
|
|
|
|
tzstr[4] = tzstr[3];
|
|
|
|
tzstr[3] = ':';
|
|
|
|
|
|
|
|
/* get current time and timezone string */
|
|
|
|
strftime (timestr, 256, "%Y-%m-%dT%H:%M:%S", now_tm);
|
2017-07-08 01:09:59 +08:00
|
|
|
g_snprintf (timestr, sizeof (timestr), "%s%s",
|
|
|
|
timestr, tzstr);
|
|
|
|
|
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
tagstr, timestr);
|
|
|
|
|
|
|
|
memset (tagstr, 0, sizeof (tagstr));
|
|
|
|
memset (strdata, 0, sizeof (strdata));
|
|
|
|
|
|
|
|
g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
|
|
|
|
tags[3], id_count, history_tags[3]);
|
|
|
|
|
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
tagstr,
|
2018-04-26 22:06:32 +08:00
|
|
|
"Gimp 2.10 "
|
2017-07-06 07:24:54 +08:00
|
|
|
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
|
2017-07-08 01:09:59 +08:00
|
|
|
"(Windows)");
|
2017-07-06 07:24:54 +08:00
|
|
|
#elif defined(__linux__)
|
2017-07-08 01:09:59 +08:00
|
|
|
"(Linux)");
|
2017-07-06 07:24:54 +08:00
|
|
|
#elif defined(__APPLE__) && defined(__MACH__)
|
2017-07-08 01:09:59 +08:00
|
|
|
"(Mac OS)");
|
2017-07-06 07:24:54 +08:00
|
|
|
#elif defined(unix) || defined(__unix__) || defined(__unix)
|
2017-07-08 01:09:59 +08:00
|
|
|
"(Unix)");
|
2017-07-06 07:24:54 +08:00
|
|
|
#else
|
2017-07-08 01:09:59 +08:00
|
|
|
"(Unknown)");
|
2017-07-06 07:24:54 +08:00
|
|
|
#endif
|
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
memset (tagstr, 0, sizeof (tagstr));
|
|
|
|
memset (strdata, 0, sizeof (tagstr));
|
|
|
|
|
|
|
|
g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
|
|
|
|
tags[3], id_count, history_tags[4]);
|
|
|
|
|
|
|
|
strcpy (strdata, "/");
|
|
|
|
strcat (strdata, state_status);
|
|
|
|
|
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
tagstr, strdata);
|
2017-07-06 07:24:54 +08:00
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2013-10-28 04:11:19 +08:00
|
|
|
/**
|
|
|
|
* gimp_metadata_new:
|
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Creates a new #GimpMetadata instance.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Return value: The new #GimpMetadata.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Since: 2.10
|
2013-10-28 04:11:19 +08:00
|
|
|
*/
|
2013-10-20 00:38:01 +08:00
|
|
|
GimpMetadata *
|
|
|
|
gimp_metadata_new (void)
|
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
GimpMetadata *metadata = NULL;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
|
|
|
if (gexiv2_initialize ())
|
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
metadata = g_object_new (GIMP_TYPE_METADATA, NULL);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (! gexiv2_metadata_open_buf (GEXIV2_METADATA (metadata),
|
|
|
|
wilber_jpg, wilber_jpg_len,
|
2017-01-04 02:36:22 +08:00
|
|
|
NULL))
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
g_object_unref (metadata);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
return NULL;
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
return metadata;
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
|
2013-10-28 04:11:19 +08:00
|
|
|
/**
|
|
|
|
* gimp_metadata_duplicate:
|
2017-01-04 02:36:22 +08:00
|
|
|
* @metadata: The object to duplicate, or %NULL.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Duplicates a #GimpMetadata instance.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Return value: The new #GimpMetadata, or %NULL if @metadata is %NULL.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Since: 2.10
|
2013-10-28 04:11:19 +08:00
|
|
|
*/
|
2013-10-20 00:38:01 +08:00
|
|
|
GimpMetadata *
|
|
|
|
gimp_metadata_duplicate (GimpMetadata *metadata)
|
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
GimpMetadata *new_metadata = NULL;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
g_return_val_if_fail (metadata == NULL || GIMP_IS_METADATA (metadata), NULL);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
|
|
|
if (metadata)
|
|
|
|
{
|
|
|
|
gchar *xml;
|
|
|
|
|
|
|
|
xml = gimp_metadata_serialize (metadata);
|
|
|
|
new_metadata = gimp_metadata_deserialize (xml);
|
2017-01-04 02:36:22 +08:00
|
|
|
g_free (xml);
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return new_metadata;
|
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
typedef struct
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
gchar name[1024];
|
|
|
|
gboolean base64;
|
|
|
|
GimpMetadata *metadata;
|
|
|
|
} GimpMetadataParseData;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
static const gchar*
|
|
|
|
gimp_metadata_attribute_name_to_value (const gchar **attribute_names,
|
|
|
|
const gchar **attribute_values,
|
|
|
|
const gchar *name)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
while (*attribute_names)
|
|
|
|
{
|
|
|
|
if (! strcmp (*attribute_names, name))
|
|
|
|
{
|
|
|
|
return *attribute_values;
|
|
|
|
}
|
|
|
|
|
|
|
|
attribute_names++;
|
|
|
|
attribute_values++;
|
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
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;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (! strcmp (element_name, "tag"))
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
const gchar *name;
|
|
|
|
const gchar *encoding;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
name = gimp_metadata_attribute_name_to_value (attribute_names,
|
|
|
|
attribute_values,
|
|
|
|
"name");
|
|
|
|
encoding = gimp_metadata_attribute_name_to_value (attribute_names,
|
|
|
|
attribute_values,
|
|
|
|
"encoding");
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (! name)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-09-03 21:46:17 +08:00
|
|
|
g_set_error (error, GIMP_METADATA_ERROR, 1001,
|
2017-01-04 02:36:22 +08:00
|
|
|
"Element 'tag' does not contain required attribute 'name'.");
|
|
|
|
return;
|
|
|
|
}
|
2013-11-11 07:11:43 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
strncpy (parse_data->name, name, sizeof (parse_data->name));
|
|
|
|
parse_data->name[sizeof (parse_data->name) - 1] = 0;
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
parse_data->base64 = (encoding && ! strcmp (encoding, "base64"));
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
static void
|
|
|
|
gimp_metadata_deserialize_end_element (GMarkupParseContext *context,
|
|
|
|
const gchar *element_name,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
static void
|
|
|
|
gimp_metadata_deserialize_text (GMarkupParseContext *context,
|
|
|
|
const gchar *text,
|
|
|
|
gsize text_len,
|
|
|
|
gpointer user_data,
|
|
|
|
GError **error)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
GimpMetadataParseData *parse_data = user_data;
|
|
|
|
const gchar *current_element;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
current_element = g_markup_parse_context_get_element (context);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (! g_strcmp0 (current_element, "tag"))
|
|
|
|
{
|
|
|
|
gchar *value = g_strndup (text, text_len);
|
2013-11-11 07:11:43 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (parse_data->base64)
|
|
|
|
{
|
|
|
|
guchar *decoded;
|
|
|
|
gsize len;
|
2013-11-11 07:11:43 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
decoded = g_base64_decode (value, &len);
|
|
|
|
|
|
|
|
if (decoded[len - 1] == '\0')
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (parse_data->metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
parse_data->name,
|
|
|
|
(const gchar *) decoded);
|
2013-11-11 07:11:43 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_free (decoded);
|
|
|
|
}
|
|
|
|
else
|
2013-11-11 07:11:43 +08:00
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (parse_data->metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
parse_data->name,
|
|
|
|
value);
|
2013-11-11 07:11:43 +08:00
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_free (value);
|
|
|
|
}
|
|
|
|
}
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
static void
|
|
|
|
gimp_metadata_deserialize_error (GMarkupParseContext *context,
|
|
|
|
GError *error,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
g_printerr ("Metadata parse error: %s\n", error->message);
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-01-04 02:36:22 +08:00
|
|
|
* gimp_metadata_deserialize:
|
|
|
|
* @metadata_xml: A string of serialized metadata XML.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Deserializes a string of XML that has been created by
|
|
|
|
* gimp_metadata_serialize().
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Return value: The new #GimpMetadata.
|
2017-01-04 02:19:10 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Since: 2.10
|
2013-10-28 04:11:19 +08:00
|
|
|
*/
|
2017-01-04 02:36:22 +08:00
|
|
|
GimpMetadata *
|
|
|
|
gimp_metadata_deserialize (const gchar *metadata_xml)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
GimpMetadata *metadata;
|
|
|
|
GMarkupParser markup_parser;
|
|
|
|
GimpMetadataParseData parse_data;
|
|
|
|
GMarkupParseContext *context;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_return_val_if_fail (metadata_xml != NULL, NULL);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
metadata = gimp_metadata_new ();
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
parse_data.metadata = metadata;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
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;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
context = g_markup_parse_context_new (&markup_parser, 0, &parse_data, NULL);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_markup_parse_context_parse (context,
|
|
|
|
metadata_xml, strlen (metadata_xml),
|
|
|
|
NULL);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_markup_parse_context_unref (context);
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
return metadata;
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
static gchar *
|
|
|
|
gimp_metadata_escape (const gchar *name,
|
|
|
|
const gchar *value,
|
|
|
|
gboolean *base64)
|
2013-11-01 21:15:15 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
if (! g_utf8_validate (value, -1, NULL))
|
|
|
|
{
|
|
|
|
gchar *encoded;
|
2013-11-11 07:11:43 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
encoded = g_base64_encode ((const guchar *) value, strlen (value) + 1);
|
2013-11-11 07:11:43 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_printerr ("Invalid UTF-8 in metadata value %s, encoding as base64: %s\n",
|
|
|
|
name, encoded);
|
2013-11-11 07:11:43 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
*base64 = TRUE;
|
2013-11-11 07:11:43 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
return encoded;
|
|
|
|
}
|
|
|
|
|
|
|
|
*base64 = FALSE;
|
|
|
|
|
|
|
|
return g_markup_escape_text (value, -1);
|
2013-11-01 21:15:15 +08:00
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
static void
|
|
|
|
gimp_metadata_append_tag (GString *string,
|
|
|
|
const gchar *name,
|
|
|
|
gchar *value,
|
|
|
|
gboolean base64)
|
2013-11-11 07:11:43 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
if (value)
|
2017-01-04 02:19:10 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
if (base64)
|
|
|
|
{
|
|
|
|
g_string_append_printf (string, " <tag name=\"%s\" encoding=\"base64\">%s</tag>\n",
|
|
|
|
name, value);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_string_append_printf (string, " <tag name=\"%s\">%s</tag>\n",
|
|
|
|
name, value);
|
|
|
|
}
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_free (value);
|
|
|
|
}
|
2013-11-11 07:11:43 +08:00
|
|
|
}
|
|
|
|
|
2013-10-20 00:38:01 +08:00
|
|
|
/**
|
2017-01-04 02:36:22 +08:00
|
|
|
* gimp_metadata_serialize:
|
|
|
|
* @metadata: A #GimpMetadata instance.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Serializes @metadata into an XML string that can later be deserialized
|
|
|
|
* using gimp_metadata_deserialize().
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Return value: The serialized XML string.
|
2017-01-04 02:19:10 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Since: 2.10
|
2013-10-20 00:38:01 +08:00
|
|
|
*/
|
|
|
|
gchar *
|
|
|
|
gimp_metadata_serialize (GimpMetadata *metadata)
|
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
GString *string;
|
|
|
|
gchar **exif_data = NULL;
|
|
|
|
gchar **iptc_data = NULL;
|
|
|
|
gchar **xmp_data = NULL;
|
|
|
|
gchar *value;
|
|
|
|
gchar *escaped;
|
|
|
|
gboolean base64;
|
|
|
|
gint i;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_METADATA (metadata), NULL);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
|
|
|
string = g_string_new (NULL);
|
|
|
|
|
|
|
|
g_string_append (string, "<?xml version='1.0' encoding='UTF-8'?>\n");
|
|
|
|
g_string_append (string, "<metadata>\n");
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
exif_data = gexiv2_metadata_get_exif_tags (GEXIV2_METADATA (metadata));
|
2017-01-04 02:36:22 +08:00
|
|
|
|
|
|
|
if (exif_data)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
for (i = 0; exif_data[i] != NULL; i++)
|
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
value = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
exif_data[i]);
|
2017-01-04 02:36:22 +08:00
|
|
|
escaped = gimp_metadata_escape (exif_data[i], value, &base64);
|
|
|
|
g_free (value);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
gimp_metadata_append_tag (string, exif_data[i], escaped, base64);
|
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_strfreev (exif_data);
|
|
|
|
}
|
2013-11-01 21:15:15 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
xmp_data = gexiv2_metadata_get_xmp_tags (GEXIV2_METADATA (metadata));
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (xmp_data)
|
|
|
|
{
|
|
|
|
for (i = 0; xmp_data[i] != NULL; i++)
|
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
value = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
xmp_data[i]);
|
2017-01-04 02:36:22 +08:00
|
|
|
escaped = gimp_metadata_escape (xmp_data[i], value, &base64);
|
|
|
|
g_free (value);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
gimp_metadata_append_tag (string, xmp_data[i], escaped, base64);
|
|
|
|
}
|
2013-11-01 21:15:15 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_strfreev (xmp_data);
|
|
|
|
}
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
iptc_data = gexiv2_metadata_get_iptc_tags (GEXIV2_METADATA (metadata));
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (iptc_data)
|
2017-01-04 02:19:10 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
for (i = 0; iptc_data[i] != NULL; i++)
|
2017-01-04 02:19:10 +08:00
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
value = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
iptc_data[i]);
|
2017-01-04 02:36:22 +08:00
|
|
|
escaped = gimp_metadata_escape (iptc_data[i], value, &base64);
|
|
|
|
g_free (value);
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
gimp_metadata_append_tag (string, iptc_data[i], escaped, base64);
|
2017-01-04 02:19:10 +08:00
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_strfreev (iptc_data);
|
2017-01-04 02:19:10 +08:00
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_string_append (string, "</metadata>\n");
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
return g_string_free (string, FALSE);
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
|
2013-10-28 04:11:19 +08:00
|
|
|
/**
|
2017-01-04 02:36:22 +08:00
|
|
|
* gimp_metadata_load_from_file:
|
|
|
|
* @file: The #GFile to load the metadata from
|
|
|
|
* @error: Return location for error message
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Loads #GimpMetadata from @file.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Return value: The loaded #GimpMetadata.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Since: 2.10
|
2013-10-20 00:38:01 +08:00
|
|
|
*/
|
2017-01-04 02:36:22 +08:00
|
|
|
GimpMetadata *
|
|
|
|
gimp_metadata_load_from_file (GFile *file,
|
|
|
|
GError **error)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
GimpMetadata *meta = NULL;
|
|
|
|
gchar *path;
|
|
|
|
gchar *filename;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
path = g_file_get_path (file);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (! path)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-09-03 21:46:17 +08:00
|
|
|
g_set_error (error, GIMP_METADATA_ERROR, 0,
|
2017-01-04 02:36:22 +08:00
|
|
|
_("Can load metadata only from local files"));
|
|
|
|
return NULL;
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
filename = g_win32_locale_filename_from_utf8 (path);
|
2018-04-05 06:12:00 +08:00
|
|
|
/* FIXME!
|
|
|
|
* This call can return NULL, which later crashes the call to
|
|
|
|
* gexiv2_metadata_open_path().
|
|
|
|
* See bug 794949.
|
|
|
|
*/
|
|
|
|
if (! filename)
|
|
|
|
{
|
|
|
|
g_set_error (error, GIMP_METADATA_ERROR, 0,
|
|
|
|
_("Conversion of the filename to system codepage failed."));
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-01-04 02:36:22 +08:00
|
|
|
#else
|
|
|
|
filename = g_strdup (path);
|
|
|
|
#endif
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_free (path);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
|
|
|
if (gexiv2_initialize ())
|
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
meta = g_object_new (GIMP_TYPE_METADATA, NULL);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (! gexiv2_metadata_open_path (GEXIV2_METADATA (meta), filename, error))
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
g_object_unref (meta);
|
|
|
|
g_free (filename);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-01-04 02:19:10 +08:00
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_free (filename);
|
|
|
|
|
|
|
|
return meta;
|
|
|
|
}
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2013-10-28 04:11:19 +08:00
|
|
|
/**
|
|
|
|
* gimp_metadata_save_to_file:
|
|
|
|
* @metadata: A #GimpMetadata instance.
|
|
|
|
* @file: The file to save the metadata to
|
|
|
|
* @error: Return location for error message
|
|
|
|
*
|
|
|
|
* Saves @metadata to @file.
|
|
|
|
*
|
|
|
|
* Return value: %TRUE on success, %FALSE otherwise.
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.10
|
2013-10-20 00:38:01 +08:00
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
gimp_metadata_save_to_file (GimpMetadata *metadata,
|
|
|
|
GFile *file,
|
|
|
|
GError **error)
|
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
gchar *path;
|
|
|
|
gchar *filename;
|
|
|
|
gboolean success;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_METADATA (metadata), FALSE);
|
2013-10-20 00:38:01 +08:00
|
|
|
g_return_val_if_fail (G_IS_FILE (file), FALSE);
|
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
|
|
|
|
path = g_file_get_path (file);
|
|
|
|
|
|
|
|
if (! path)
|
|
|
|
{
|
2017-09-03 21:46:17 +08:00
|
|
|
g_set_error (error, GIMP_METADATA_ERROR, 0,
|
2013-10-27 23:32:26 +08:00
|
|
|
_("Can save metadata only to local files"));
|
2013-10-20 00:38:01 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
filename = g_win32_locale_filename_from_utf8 (path);
|
2018-05-01 04:14:51 +08:00
|
|
|
/* FIXME!
|
|
|
|
* This call can return NULL.
|
|
|
|
*/
|
|
|
|
if (! filename)
|
|
|
|
{
|
|
|
|
g_free (path);
|
|
|
|
g_set_error (error, GIMP_METADATA_ERROR, 0,
|
|
|
|
_("Conversion of the filename to system codepage failed."));
|
|
|
|
return FALSE;
|
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
#else
|
|
|
|
filename = g_strdup (path);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
g_free (path);
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
success = gexiv2_metadata_save_file (GEXIV2_METADATA (metadata),
|
|
|
|
filename, error);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
|
|
|
g_free (filename);
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2013-10-28 04:11:19 +08:00
|
|
|
/**
|
|
|
|
* gimp_metadata_set_from_exif:
|
|
|
|
* @metadata: A #GimpMetadata instance.
|
2013-10-30 05:48:46 +08:00
|
|
|
* @exif_data: The blob of Exif data to set
|
2013-10-28 04:11:19 +08:00
|
|
|
* @exif_data_length: Length of @exif_data, in bytes
|
|
|
|
* @error: Return location for error message
|
|
|
|
*
|
2013-10-30 05:48:46 +08:00
|
|
|
* Sets the tags from a piece of Exif data on @metadata.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
|
|
|
* Return value: %TRUE on success, %FALSE otherwise.
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.10
|
2013-10-28 04:11:19 +08:00
|
|
|
*/
|
2013-10-20 00:38:01 +08:00
|
|
|
gboolean
|
|
|
|
gimp_metadata_set_from_exif (GimpMetadata *metadata,
|
|
|
|
const guchar *exif_data,
|
|
|
|
gint exif_data_length,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
GByteArray *exif_bytes;
|
|
|
|
GimpMetadata *exif_metadata;
|
|
|
|
guint8 data_size[2] = { 0, };
|
|
|
|
const guint8 eoi[2] = { 0xff, 0xd9 };
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_METADATA (metadata), FALSE);
|
2013-10-20 00:38:01 +08:00
|
|
|
g_return_val_if_fail (exif_data != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (exif_data_length > 0, FALSE);
|
2016-04-22 23:15:23 +08:00
|
|
|
g_return_val_if_fail (exif_data_length + 2 < 65536, FALSE);
|
2013-10-20 00:38:01 +08:00
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
|
2016-04-22 23:15:23 +08:00
|
|
|
data_size[0] = ((exif_data_length + 2) & 0xFF00) >> 8;
|
|
|
|
data_size[1] = ((exif_data_length + 2) & 0x00FF);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
|
|
|
exif_bytes = g_byte_array_new ();
|
|
|
|
exif_bytes = g_byte_array_append (exif_bytes,
|
|
|
|
minimal_exif, G_N_ELEMENTS (minimal_exif));
|
|
|
|
exif_bytes = g_byte_array_append (exif_bytes,
|
|
|
|
data_size, 2);
|
|
|
|
exif_bytes = g_byte_array_append (exif_bytes,
|
|
|
|
(guint8 *) exif_data, exif_data_length);
|
2016-04-22 23:15:23 +08:00
|
|
|
exif_bytes = g_byte_array_append (exif_bytes, eoi, 2);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
exif_metadata = gimp_metadata_new ();
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (! gexiv2_metadata_open_buf (GEXIV2_METADATA (exif_metadata),
|
2013-10-20 00:38:01 +08:00
|
|
|
exif_bytes->data, exif_bytes->len, error))
|
|
|
|
{
|
|
|
|
g_object_unref (exif_metadata);
|
|
|
|
g_byte_array_free (exif_bytes, TRUE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (! gexiv2_metadata_has_exif (GEXIV2_METADATA (exif_metadata)))
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-09-03 21:46:17 +08:00
|
|
|
g_set_error (error, GIMP_METADATA_ERROR, 0,
|
2013-10-30 05:48:46 +08:00
|
|
|
_("Parsing Exif data failed."));
|
2013-10-20 00:38:01 +08:00
|
|
|
g_object_unref (exif_metadata);
|
|
|
|
g_byte_array_free (exif_bytes, TRUE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
gimp_metadata_add (exif_metadata, metadata);
|
2013-10-20 00:38:01 +08:00
|
|
|
g_object_unref (exif_metadata);
|
|
|
|
g_byte_array_free (exif_bytes, TRUE);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-07-06 07:24:54 +08:00
|
|
|
/**
|
|
|
|
* gimp_metadata_set_from_iptc:
|
|
|
|
* @metadata: A #GimpMetadata instance.
|
|
|
|
* @iptc_data: The blob of Ipc data to set
|
|
|
|
* @iptc_data_length:Length of @iptc_data, in bytes
|
|
|
|
* @error: Return location for error message
|
|
|
|
*
|
|
|
|
* Sets the tags from a piece of IPTC data on @metadata.
|
|
|
|
*
|
|
|
|
* Return value: %TRUE on success, %FALSE otherwise.
|
|
|
|
*
|
|
|
|
* Since: 2.10
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
gimp_metadata_set_from_iptc (GimpMetadata *metadata,
|
|
|
|
const guchar *iptc_data,
|
|
|
|
gint iptc_data_length,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
GimpMetadata *iptc_metadata;
|
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_METADATA (metadata), FALSE);
|
2017-07-06 07:24:54 +08:00
|
|
|
g_return_val_if_fail (iptc_data != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (iptc_data_length > 0, FALSE);
|
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
|
|
|
|
iptc_metadata = gimp_metadata_new ();
|
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
if (! gexiv2_metadata_open_buf (GEXIV2_METADATA (iptc_metadata),
|
2017-07-06 07:24:54 +08:00
|
|
|
iptc_data, iptc_data_length, error))
|
|
|
|
{
|
|
|
|
g_object_unref (iptc_metadata);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
if (! gexiv2_metadata_has_iptc (GEXIV2_METADATA (iptc_metadata)))
|
2017-07-06 07:24:54 +08:00
|
|
|
{
|
2017-09-03 21:46:17 +08:00
|
|
|
g_set_error (error, GIMP_METADATA_ERROR, 0,
|
2017-07-06 07:24:54 +08:00
|
|
|
_("Parsing IPTC data failed."));
|
|
|
|
g_object_unref (iptc_metadata);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_metadata_add (iptc_metadata, metadata);
|
|
|
|
g_object_unref (iptc_metadata);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2013-10-28 04:11:19 +08:00
|
|
|
/**
|
|
|
|
* gimp_metadata_set_from_xmp:
|
|
|
|
* @metadata: A #GimpMetadata instance.
|
2013-10-30 05:48:46 +08:00
|
|
|
* @xmp_data: The blob of Exif data to set
|
2013-10-28 04:11:19 +08:00
|
|
|
* @xmp_data_length: Length of @exif_data, in bytes
|
|
|
|
* @error: Return location for error message
|
|
|
|
*
|
|
|
|
* Sets the tags from a piece of XMP data on @metadata.
|
|
|
|
*
|
|
|
|
* Return value: %TRUE on success, %FALSE otherwise.
|
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.10
|
2013-10-28 04:11:19 +08:00
|
|
|
*/
|
2013-10-20 00:38:01 +08:00
|
|
|
gboolean
|
|
|
|
gimp_metadata_set_from_xmp (GimpMetadata *metadata,
|
|
|
|
const guchar *xmp_data,
|
|
|
|
gint xmp_data_length,
|
|
|
|
GError **error)
|
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
GimpMetadata *xmp_metadata;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_METADATA (metadata), FALSE);
|
2013-10-20 00:38:01 +08:00
|
|
|
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);
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
xmp_metadata = gimp_metadata_new ();
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (! gexiv2_metadata_open_buf (GEXIV2_METADATA (xmp_metadata),
|
2013-10-20 00:38:01 +08:00
|
|
|
xmp_data, xmp_data_length, error))
|
|
|
|
{
|
|
|
|
g_object_unref (xmp_metadata);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (! gexiv2_metadata_has_xmp (GEXIV2_METADATA (xmp_metadata)))
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-09-03 21:46:17 +08:00
|
|
|
g_set_error (error, GIMP_METADATA_ERROR, 0,
|
2013-10-20 00:38:01 +08:00
|
|
|
_("Parsing XMP data failed."));
|
|
|
|
g_object_unref (xmp_metadata);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
gimp_metadata_add (xmp_metadata, metadata);
|
2013-10-20 00:38:01 +08:00
|
|
|
g_object_unref (xmp_metadata);
|
2017-01-04 02:36:22 +08:00
|
|
|
|
2013-10-20 00:38:01 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2013-10-28 04:11:19 +08:00
|
|
|
/**
|
2017-01-04 02:36:22 +08:00
|
|
|
* gimp_metadata_set_pixel_size:
|
|
|
|
* @metadata: A #GimpMetadata instance.
|
|
|
|
* @width: Width in pixels
|
|
|
|
* @height: Height in pixels
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Sets Exif.Image.ImageWidth and Exif.Image.ImageLength on @metadata.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Since: 2.10
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
gimp_metadata_set_pixel_size (GimpMetadata *metadata,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
|
|
|
{
|
|
|
|
gchar buffer[32];
|
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
g_return_if_fail (GIMP_IS_METADATA (metadata));
|
2017-01-04 02:36:22 +08:00
|
|
|
|
|
|
|
g_snprintf (buffer, sizeof (buffer), "%d", width);
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
"Exif.Image.ImageWidth", buffer);
|
2017-01-04 02:36:22 +08:00
|
|
|
|
|
|
|
g_snprintf (buffer, sizeof (buffer), "%d", height);
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
"Exif.Image.ImageLength", buffer);
|
2017-01-04 02:36:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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];
|
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
g_return_if_fail (GIMP_IS_METADATA (metadata));
|
2017-01-04 02:36:22 +08:00
|
|
|
|
|
|
|
g_snprintf (buffer, sizeof (buffer), "%d %d %d",
|
|
|
|
bits_per_sample, bits_per_sample, bits_per_sample);
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
"Exif.Image.BitsPerSample", buffer);
|
2017-01-04 02:36:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
2013-10-28 04:11:19 +08:00
|
|
|
*
|
2015-06-01 03:18:09 +08:00
|
|
|
* Since: 2.10
|
2013-10-20 00:38:01 +08:00
|
|
|
*/
|
|
|
|
gboolean
|
2017-01-04 02:36:22 +08:00
|
|
|
gimp_metadata_get_resolution (GimpMetadata *metadata,
|
|
|
|
gdouble *xres,
|
|
|
|
gdouble *yres,
|
|
|
|
GimpUnit *unit)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
gint xnom, xdenom;
|
|
|
|
gint ynom, ydenom;
|
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_METADATA (metadata), FALSE);
|
2017-01-04 02:36:22 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_get_exif_tag_rational (GEXIV2_METADATA (metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Image.XResolution",
|
|
|
|
&xnom, &xdenom) &&
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_get_exif_tag_rational (GEXIV2_METADATA (metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Image.YResolution",
|
|
|
|
&ynom, &ydenom))
|
|
|
|
{
|
|
|
|
gchar *un;
|
|
|
|
gint exif_unit = 2;
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
un = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Image.ResolutionUnit");
|
|
|
|
if (un)
|
|
|
|
{
|
|
|
|
exif_unit = atoi (un);
|
|
|
|
g_free (un);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xnom != 0 && xdenom != 0 &&
|
|
|
|
ynom != 0 && ydenom != 0)
|
|
|
|
{
|
|
|
|
gdouble xresolution = (gdouble) xnom / (gdouble) xdenom;
|
|
|
|
gdouble yresolution = (gdouble) ynom / (gdouble) ydenom;
|
|
|
|
|
|
|
|
if (exif_unit == 3)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-07-08 01:09:59 +08:00
|
|
|
g_return_if_fail (GIMP_IS_METADATA (metadata));
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (gimp_unit_is_metric (unit))
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
xres /= 2.54;
|
|
|
|
yres /= 2.54;
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
exif_unit = 3;
|
|
|
|
}
|
|
|
|
else
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
exif_unit = 2;
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
2017-01-04 02:36:22 +08:00
|
|
|
|
|
|
|
for (factor = 1; factor <= 100 /* arbitrary */; factor++)
|
2013-11-02 00:36:26 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
if (fabs (xres * factor - ROUND (xres * factor)) < 0.01 &&
|
|
|
|
fabs (yres * factor - ROUND (yres * factor)) < 0.01)
|
|
|
|
break;
|
2013-11-02 00:36:26 +08:00
|
|
|
}
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_set_exif_tag_rational (GEXIV2_METADATA (metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Image.XResolution",
|
|
|
|
ROUND (xres * factor), factor);
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_set_exif_tag_rational (GEXIV2_METADATA (metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Image.YResolution",
|
|
|
|
ROUND (yres * factor), factor);
|
|
|
|
|
|
|
|
g_snprintf (buffer, sizeof (buffer), "%d", exif_unit);
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
|
|
|
|
"Exif.Image.ResolutionUnit", buffer);
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
|
2015-10-01 02:47:52 +08:00
|
|
|
/**
|
|
|
|
* gimp_metadata_get_colorspace:
|
2017-01-04 02:36:22 +08:00
|
|
|
* @metadata: A #GimpMetadata instance.
|
2015-10-01 02:47:52 +08:00
|
|
|
*
|
|
|
|
* Returns values based on Exif.Photo.ColorSpace, Xmp.exif.ColorSpace,
|
|
|
|
* Exif.Iop.InteroperabilityIndex, Exif.Nikon3.ColorSpace,
|
|
|
|
* Exif.Canon.ColorSpace of @metadata.
|
|
|
|
*
|
|
|
|
* Return value: The colorspace specified by above tags.
|
|
|
|
*
|
|
|
|
* Since: 2.10
|
|
|
|
*/
|
|
|
|
GimpMetadataColorspace
|
|
|
|
gimp_metadata_get_colorspace (GimpMetadata *metadata)
|
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
glong exif_cs = -1;
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_METADATA (metadata),
|
2015-10-01 02:47:52 +08:00
|
|
|
GIMP_METADATA_COLORSPACE_UNSPECIFIED);
|
|
|
|
|
|
|
|
/* the logic here was mostly taken from darktable and libkexiv2 */
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_has_tag (GEXIV2_METADATA (metadata),
|
|
|
|
"Exif.Photo.ColorSpace"))
|
2015-10-01 02:47:52 +08:00
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
exif_cs = gexiv2_metadata_get_tag_long (GEXIV2_METADATA (metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Photo.ColorSpace");
|
2015-10-01 02:47:52 +08:00
|
|
|
}
|
2017-01-30 23:42:27 +08:00
|
|
|
else if (gexiv2_metadata_has_tag (GEXIV2_METADATA (metadata),
|
|
|
|
"Xmp.exif.ColorSpace"))
|
2015-10-01 02:47:52 +08:00
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
exif_cs = gexiv2_metadata_get_tag_long (GEXIV2_METADATA (metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
"Xmp.exif.ColorSpace");
|
2015-10-01 02:47:52 +08:00
|
|
|
}
|
|
|
|
|
2015-10-07 03:32:12 +08:00
|
|
|
if (exif_cs == 0x01)
|
2015-10-01 02:47:52 +08:00
|
|
|
{
|
|
|
|
return GIMP_METADATA_COLORSPACE_SRGB;
|
|
|
|
}
|
2015-10-07 03:32:12 +08:00
|
|
|
else if (exif_cs == 0x02)
|
2015-10-01 02:47:52 +08:00
|
|
|
{
|
|
|
|
return GIMP_METADATA_COLORSPACE_ADOBERGB;
|
|
|
|
}
|
2015-10-07 03:32:12 +08:00
|
|
|
else
|
2015-10-01 02:47:52 +08:00
|
|
|
{
|
2015-10-07 03:32:12 +08:00
|
|
|
if (exif_cs == 0xffff)
|
2015-10-01 02:47:52 +08:00
|
|
|
{
|
2015-10-07 03:32:12 +08:00
|
|
|
gchar *iop_index;
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
iop_index = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Iop.InteroperabilityIndex");
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2015-10-07 03:32:12 +08:00
|
|
|
if (! g_strcmp0 (iop_index, "R03"))
|
|
|
|
{
|
|
|
|
g_free (iop_index);
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2015-10-07 03:32:12 +08:00
|
|
|
return GIMP_METADATA_COLORSPACE_ADOBERGB;
|
|
|
|
}
|
|
|
|
else if (! g_strcmp0 (iop_index, "R98"))
|
|
|
|
{
|
|
|
|
g_free (iop_index);
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2015-10-07 03:32:12 +08:00
|
|
|
return GIMP_METADATA_COLORSPACE_SRGB;
|
|
|
|
}
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2015-10-07 03:32:12 +08:00
|
|
|
g_free (iop_index);
|
2015-10-01 02:47:52 +08:00
|
|
|
}
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_has_tag (GEXIV2_METADATA (metadata),
|
|
|
|
"Exif.Nikon3.ColorSpace"))
|
2015-10-01 02:47:52 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
glong nikon_cs;
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
nikon_cs = gexiv2_metadata_get_tag_long (GEXIV2_METADATA (metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Nikon3.ColorSpace");
|
|
|
|
|
|
|
|
if (nikon_cs == 0x01)
|
|
|
|
{
|
|
|
|
return GIMP_METADATA_COLORSPACE_SRGB;
|
|
|
|
}
|
|
|
|
else if (nikon_cs == 0x02)
|
2015-10-07 03:32:12 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
return GIMP_METADATA_COLORSPACE_ADOBERGB;
|
2015-10-07 03:32:12 +08:00
|
|
|
}
|
2015-10-01 02:47:52 +08:00
|
|
|
}
|
2015-10-07 03:32:12 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_has_tag (GEXIV2_METADATA (metadata),
|
|
|
|
"Exif.Canon.ColorSpace"))
|
2015-10-01 02:47:52 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
glong canon_cs;
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
canon_cs = gexiv2_metadata_get_tag_long (GEXIV2_METADATA (metadata),
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Canon.ColorSpace");
|
|
|
|
|
|
|
|
if (canon_cs == 0x01)
|
2015-10-07 03:32:12 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
return GIMP_METADATA_COLORSPACE_SRGB;
|
|
|
|
}
|
|
|
|
else if (canon_cs == 0x02)
|
|
|
|
{
|
|
|
|
return GIMP_METADATA_COLORSPACE_ADOBERGB;
|
2015-10-07 03:32:12 +08:00
|
|
|
}
|
2015-10-01 02:47:52 +08:00
|
|
|
}
|
2015-10-07 03:32:12 +08:00
|
|
|
|
|
|
|
if (exif_cs == 0xffff)
|
|
|
|
return GIMP_METADATA_COLORSPACE_UNCALIBRATED;
|
2015-10-01 02:47:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return GIMP_METADATA_COLORSPACE_UNSPECIFIED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-01-04 02:36:22 +08:00
|
|
|
* gimp_metadata_set_colorspace:
|
|
|
|
* @metadata: A #GimpMetadata instance.
|
|
|
|
* @colorspace: The color space.
|
2015-10-01 02:47:52 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Sets Exif.Photo.ColorSpace, Xmp.exif.ColorSpace,
|
|
|
|
* Exif.Iop.InteroperabilityIndex, Exif.Nikon3.ColorSpace,
|
|
|
|
* Exif.Canon.ColorSpace of @metadata.
|
2017-01-04 02:19:10 +08:00
|
|
|
*
|
2017-01-04 02:36:22 +08:00
|
|
|
* Since: 2.10
|
2015-10-01 02:47:52 +08:00
|
|
|
*/
|
2017-01-04 02:36:22 +08:00
|
|
|
void
|
|
|
|
gimp_metadata_set_colorspace (GimpMetadata *metadata,
|
|
|
|
GimpMetadataColorspace colorspace)
|
2015-10-01 02:47:52 +08:00
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
GExiv2Metadata *g2metadata = GEXIV2_METADATA (metadata);
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
switch (colorspace)
|
|
|
|
{
|
|
|
|
case GIMP_METADATA_COLORSPACE_UNSPECIFIED:
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_clear_tag (g2metadata, "Exif.Photo.ColorSpace");
|
|
|
|
gexiv2_metadata_clear_tag (g2metadata, "Xmp.exif.ColorSpace");
|
|
|
|
gexiv2_metadata_clear_tag (g2metadata, "Exif.Iop.InteroperabilityIndex");
|
|
|
|
gexiv2_metadata_clear_tag (g2metadata, "Exif.Nikon3.ColorSpace");
|
|
|
|
gexiv2_metadata_clear_tag (g2metadata, "Exif.Canon.ColorSpace");
|
2017-01-04 02:36:22 +08:00
|
|
|
break;
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
case GIMP_METADATA_COLORSPACE_UNCALIBRATED:
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_set_tag_long (g2metadata, "Exif.Photo.ColorSpace", 0xffff);
|
|
|
|
if (gexiv2_metadata_has_tag (g2metadata, "Xmp.exif.ColorSpace"))
|
|
|
|
gexiv2_metadata_set_tag_long (g2metadata, "Xmp.exif.ColorSpace", 0xffff);
|
|
|
|
gexiv2_metadata_clear_tag (g2metadata, "Exif.Iop.InteroperabilityIndex");
|
|
|
|
gexiv2_metadata_clear_tag (g2metadata, "Exif.Nikon3.ColorSpace");
|
|
|
|
gexiv2_metadata_clear_tag (g2metadata, "Exif.Canon.ColorSpace");
|
2017-01-04 02:36:22 +08:00
|
|
|
break;
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
case GIMP_METADATA_COLORSPACE_SRGB:
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_set_tag_long (g2metadata, "Exif.Photo.ColorSpace", 0x01);
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_has_tag (g2metadata, "Xmp.exif.ColorSpace"))
|
|
|
|
gexiv2_metadata_set_tag_long (g2metadata, "Xmp.exif.ColorSpace", 0x01);
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_has_tag (g2metadata, "Exif.Iop.InteroperabilityIndex"))
|
|
|
|
gexiv2_metadata_set_tag_string (g2metadata,
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Iop.InteroperabilityIndex", "R98");
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_has_tag (g2metadata, "Exif.Nikon3.ColorSpace"))
|
|
|
|
gexiv2_metadata_set_tag_long (g2metadata, "Exif.Nikon3.ColorSpace", 0x01);
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_has_tag (g2metadata, "Exif.Canon.ColorSpace"))
|
|
|
|
gexiv2_metadata_set_tag_long (g2metadata, "Exif.Canon.ColorSpace", 0x01);
|
2017-01-04 02:36:22 +08:00
|
|
|
break;
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
case GIMP_METADATA_COLORSPACE_ADOBERGB:
|
2017-01-30 23:42:27 +08:00
|
|
|
gexiv2_metadata_set_tag_long (g2metadata, "Exif.Photo.ColorSpace", 0x02);
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_has_tag (g2metadata, "Xmp.exif.ColorSpace"))
|
|
|
|
gexiv2_metadata_set_tag_long (g2metadata, "Xmp.exif.ColorSpace", 0x02);
|
2015-10-01 02:47:52 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_has_tag (g2metadata, "Exif.Iop.InteroperabilityIndex"))
|
|
|
|
gexiv2_metadata_set_tag_string (g2metadata,
|
2017-01-04 02:36:22 +08:00
|
|
|
"Exif.Iop.InteroperabilityIndex", "R03");
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_has_tag (g2metadata, "Exif.Nikon3.ColorSpace"))
|
|
|
|
gexiv2_metadata_set_tag_long (g2metadata, "Exif.Nikon3.ColorSpace", 0x02);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_has_tag (g2metadata, "Exif.Canon.ColorSpace"))
|
|
|
|
gexiv2_metadata_set_tag_long (g2metadata, "Exif.Canon.ColorSpace", 0x02);
|
2017-01-04 02:36:22 +08:00
|
|
|
break;
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
2017-01-04 02:36:22 +08:00
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
/**
|
|
|
|
* 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;
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_return_val_if_fail (tag != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (mime_type != NULL, FALSE);
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
for (j = 0; j < G_N_ELEMENTS (unsupported_tags); j++)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
if (g_str_has_prefix (tag, unsupported_tags[j]))
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
return FALSE;
|
2017-01-04 02:19:10 +08:00
|
|
|
}
|
2017-01-04 02:36:22 +08:00
|
|
|
}
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (! strcmp (mime_type, "image/jpeg"))
|
|
|
|
{
|
|
|
|
for (j = 0; j < G_N_ELEMENTS (tiff_tags); j++)
|
2017-01-04 02:19:10 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
if (g_str_has_prefix (tag, tiff_tags[j]))
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
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;
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
/* private functions */
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
static GQuark
|
|
|
|
gimp_metadata_error_quark (void)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
static GQuark quark = 0;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (G_UNLIKELY (quark == 0))
|
|
|
|
quark = g_quark_from_static_string ("gimp-metadata-error-quark");
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
return quark;
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
static void
|
|
|
|
gimp_metadata_add (GimpMetadata *src,
|
|
|
|
GimpMetadata *dest)
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
GExiv2Metadata *g2src = GEXIV2_METADATA (src);
|
|
|
|
GExiv2Metadata *g2dest = GEXIV2_METADATA (dest);
|
2017-01-04 02:36:22 +08:00
|
|
|
gchar *value;
|
|
|
|
gint i;
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_get_supports_exif (g2src) &&
|
|
|
|
gexiv2_metadata_get_supports_exif (g2dest))
|
2013-10-20 00:38:01 +08:00
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
gchar **exif_data = gexiv2_metadata_get_exif_tags (g2src);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (exif_data)
|
2017-01-04 02:19:10 +08:00
|
|
|
{
|
2017-01-04 02:36:22 +08:00
|
|
|
for (i = 0; exif_data[i] != NULL; i++)
|
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
value = gexiv2_metadata_get_tag_string (g2src, exif_data[i]);
|
|
|
|
gexiv2_metadata_set_tag_string (g2dest, exif_data[i], value);
|
2017-01-04 02:36:22 +08:00
|
|
|
g_free (value);
|
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_strfreev (exif_data);
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_get_supports_xmp (g2src) &&
|
|
|
|
gexiv2_metadata_get_supports_xmp (g2dest))
|
2017-01-04 02:19:10 +08:00
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
gchar **xmp_data = gexiv2_metadata_get_xmp_tags (g2src);
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (xmp_data)
|
|
|
|
{
|
|
|
|
for (i = 0; xmp_data[i] != NULL; i++)
|
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
value = gexiv2_metadata_get_tag_string (g2src, xmp_data[i]);
|
|
|
|
gexiv2_metadata_set_tag_string (g2dest, xmp_data[i], value);
|
2017-01-04 02:36:22 +08:00
|
|
|
g_free (value);
|
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_strfreev (xmp_data);
|
|
|
|
}
|
2017-01-04 02:19:10 +08:00
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-30 23:42:27 +08:00
|
|
|
if (gexiv2_metadata_get_supports_iptc (g2src) &&
|
|
|
|
gexiv2_metadata_get_supports_iptc (g2dest))
|
2017-01-04 02:36:22 +08:00
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
gchar **iptc_data = gexiv2_metadata_get_iptc_tags (g2src);
|
2013-10-20 00:38:01 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
if (iptc_data)
|
|
|
|
{
|
|
|
|
for (i = 0; iptc_data[i] != NULL; i++)
|
|
|
|
{
|
2017-01-30 23:42:27 +08:00
|
|
|
value = gexiv2_metadata_get_tag_string (g2src, iptc_data[i]);
|
|
|
|
gexiv2_metadata_set_tag_string (g2dest, iptc_data[i], value);
|
2017-01-04 02:36:22 +08:00
|
|
|
g_free (value);
|
|
|
|
}
|
2017-01-04 02:19:10 +08:00
|
|
|
|
2017-01-04 02:36:22 +08:00
|
|
|
g_strfreev (iptc_data);
|
|
|
|
}
|
|
|
|
}
|
2013-10-20 00:38:01 +08:00
|
|
|
}
|