tag: exif: Adds mapping for GST_TAG_IMAGE_ORIENTATION
authorThiago Santos <thiago.sousa.santos@collabora.co.uk>
Wed, 16 Jun 2010 14:19:37 +0000 (11:19 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.co.uk>
Wed, 23 Jun 2010 15:03:47 +0000 (12:03 -0300)
Adds GST_TAG_IMAGE_ORIENTATION to the exif helper lib mapped tags.
Tests included.

gst-libs/gst/tag/Makefile.am
gst-libs/gst/tag/gstexiftag.c
gst-libs/gst/tag/gsttageditingprivate.c [new file with mode: 0644]
gst-libs/gst/tag/gsttageditingprivate.h
tests/check/libs/tag.c
win32/common/libgsttag.def

index 757bb58..7a8dc54 100644 (file)
@@ -8,7 +8,7 @@ lib_LTLIBRARIES = libgsttag-@GST_MAJORMINOR@.la
 
 libgsttag_@GST_MAJORMINOR@_la_SOURCES = \
     gstvorbistag.c gstid3tag.c gstxmptag.c gstexiftag.c \
-    lang.c tags.c gsttagdemux.c
+    lang.c tags.c gsttagdemux.c gsttageditingprivate.c
 libgsttag_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
 libgsttag_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) 
 libgsttag_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
index d452ff6..4112802 100644 (file)
@@ -129,6 +129,12 @@ struct _GstExifReader
   gint byte_order;
 };
 
+static void serialize_orientation (GstExifWriter * writer,
+    const GstTagList * taglist, const GstExifTagMatch * exiftag);
+static gint deserialize_orientation (GstExifReader * exif_reader,
+    GstByteReader * reader, const GstExifTagMatch * exiftag,
+    GstExifTagData * tagdata);
+
 static void serialize_geo_coordinate (GstExifWriter * writer,
     const GstTagList * taglist, const GstExifTagMatch * exiftag);
 static gint deserialize_geo_coordinate (GstExifReader * exif_reader,
@@ -170,6 +176,8 @@ static const GstExifTagMatch tag_map_ifd0[] = {
   {GST_TAG_DESCRIPTION, 0x10E, EXIF_TYPE_ASCII, 0, NULL, NULL},
   {GST_TAG_DEVICE_MANUFACTURER, 0x10F, EXIF_TYPE_ASCII, 0, NULL, NULL},
   {GST_TAG_DEVICE_MODEL, 0x110, EXIF_TYPE_ASCII, 0, NULL, NULL},
+  {GST_TAG_IMAGE_ORIENTATION, 0x112, EXIF_TYPE_SHORT, 0, serialize_orientation,
+      deserialize_orientation},
   {GST_TAG_ARTIST, 0x13B, EXIF_TYPE_ASCII, 0, NULL, NULL},
   {GST_TAG_COPYRIGHT, 0x8298, EXIF_TYPE_ASCII, 0, NULL, NULL},
   {NULL, EXIF_GPS_IFD_TAG, EXIF_TYPE_LONG, 0, NULL, NULL},
@@ -370,6 +378,22 @@ gst_exif_writer_write_byte_tag (GstExifWriter * writer, guint16 tag,
 }
 
 static void
+gst_exif_writer_write_short_tag (GstExifWriter * writer, guint16 tag,
+    guint16 value)
+{
+  guint32 offset = 0;
+
+  if (writer->byte_order == G_LITTLE_ENDIAN) {
+    GST_WRITE_UINT16_LE ((guint8 *) & offset, value);
+  } else {
+    GST_WRITE_UINT16_BE ((guint8 *) & offset, value);
+  }
+
+  gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_SHORT,
+      1, offset, TRUE);
+}
+
+static void
 write_exif_ascii_tag (GstExifWriter * writer, guint16 tag, const gchar * str)
 {
   gint size;
@@ -1008,6 +1032,65 @@ byte_reader_fail:
 
 /* special serialization functions */
 static void
+serialize_orientation (GstExifWriter * writer, const GstTagList * taglist,
+    const GstExifTagMatch * exiftag)
+{
+  gchar *str = NULL;
+  gint exif_value;
+
+  if (!gst_tag_list_get_string_index (taglist, GST_TAG_IMAGE_ORIENTATION, 0,
+          &str)) {
+    GST_WARNING ("No image orientation tag present in taglist");
+    return;
+  }
+
+  exif_value = gst_tag_image_orientation_to_exif_value (str);
+  if (exif_value == -1) {
+    GST_WARNING ("Invalid image orientation value: %s", str);
+    g_free (str);
+    return;
+  }
+  g_free (str);
+
+  gst_exif_writer_write_short_tag (writer, exiftag->exif_tag, exif_value);
+}
+
+static gint
+deserialize_orientation (GstExifReader * exif_reader,
+    GstByteReader * reader, const GstExifTagMatch * exiftag,
+    GstExifTagData * tagdata)
+{
+  gint ret = 1;
+  const gchar *str = NULL;
+  gint value;
+
+  GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag,
+      exiftag->exif_tag);
+
+  /* validate tag */
+  if (tagdata->tag_type != EXIF_TYPE_SHORT || tagdata->count != 1) {
+    GST_WARNING ("Orientation tag has unexpected type/count");
+    return ret;
+  }
+
+  if (exif_reader->byte_order == G_LITTLE_ENDIAN) {
+    value = GST_READ_UINT16_LE (tagdata->offset_as_data);
+  } else {
+    value = GST_READ_UINT16_BE (tagdata->offset_as_data);
+  }
+
+  str = gst_tag_image_orientation_from_exif_value (value);
+  if (str == NULL) {
+    GST_WARNING ("Invalid value for exif orientation tag: %d", value);
+    return ret;
+  }
+  gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_REPLACE,
+      exiftag->gst_tag, str, NULL);
+
+  return ret;
+}
+
+static void
 serialize_geo_coordinate (GstExifWriter * writer, const GstTagList * taglist,
     const GstExifTagMatch * exiftag)
 {
diff --git a/gst-libs/gst/tag/gsttageditingprivate.c b/gst-libs/gst/tag/gsttageditingprivate.c
new file mode 100644 (file)
index 0000000..ebebfdf
--- /dev/null
@@ -0,0 +1,76 @@
+/* GStreamer
+ * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gsttageditingprivate.h"
+
+#include <string.h>
+
+gint
+gst_tag_image_orientation_to_exif_value (const gchar * str)
+{
+  if (str == NULL)
+    goto end;
+
+  if (strcmp (str, "rotate-0") == 0)
+    return 1;
+  else if (strcmp (str, "flip-rotate-0") == 0)
+    return 2;
+  else if (strcmp (str, "rotate-180") == 0)
+    return 3;
+  else if (strcmp (str, "flip-rotate-180") == 0)
+    return 4;
+  else if (strcmp (str, "flip-rotate-270") == 0)
+    return 5;
+  else if (strcmp (str, "rotate-90") == 0)
+    return 6;
+  else if (strcmp (str, "flip-rotate-90") == 0)
+    return 7;
+  else if (strcmp (str, "rotate-270") == 0)
+    return 8;
+
+end:
+  GST_WARNING ("Invalid image orientation tag: %d", str);
+  return -1;
+}
+
+const gchar *
+gst_tag_image_orientation_from_exif_value (gint value)
+{
+  switch (value) {
+    case 1:
+      return "rotate-0";
+    case 2:
+      return "flip-rotate-0";
+    case 3:
+      return "rotate-180";
+    case 4:
+      return "flip-rotate-180";
+    case 5:
+      return "flip-rotate-270";
+    case 6:
+      return "rotate-90";
+    case 7:
+      return "flip-rotate-90";
+    case 8:
+      return "rotate-270";
+    default:
+      GST_WARNING ("Invalid tiff orientation tag value: %d", value);
+      return NULL;
+  }
+}
index 0427523..89e6378 100644 (file)
@@ -35,6 +35,9 @@ struct _GstTagEntryMatch {
 
 GType gst_vorbis_tag_get_type (void);
 
+gint gst_tag_image_orientation_to_exif_value (const gchar * str);
+const gchar * gst_tag_image_orientation_from_exif_value (gint value);
+
 
 G_END_DECLS
 
index 448ca2e..adbf78e 100644 (file)
@@ -1126,6 +1126,24 @@ GST_START_TEST (test_exif_tags_serialization_deserialization)
   do_exif_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value);
   g_value_set_static_string (&value, "ty");
   do_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
+
+  /* image orientation tests */
+  g_value_set_static_string (&value, "rotate-0");
+  do_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, &value);
+  g_value_set_static_string (&value, "flip-rotate-0");
+  do_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, &value);
+  g_value_set_static_string (&value, "rotate-180");
+  do_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, &value);
+  g_value_set_static_string (&value, "flip-rotate-180");
+  do_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, &value);
+  g_value_set_static_string (&value, "flip-rotate-270");
+  do_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, &value);
+  g_value_set_static_string (&value, "rotate-90");
+  do_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, &value);
+  g_value_set_static_string (&value, "flip-rotate-90");
+  do_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, &value);
+  g_value_set_static_string (&value, "rotate-270");
+  do_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, &value);
   g_value_unset (&value);
 
   g_value_init (&value, G_TYPE_DOUBLE);
index 846bba6..6cae63a 100644 (file)
@@ -13,6 +13,8 @@ EXPORTS
        gst_tag_id3_genre_count
        gst_tag_id3_genre_get
        gst_tag_image_data_to_image_buffer
+       gst_tag_image_orientation_from_exif_value
+       gst_tag_image_orientation_to_exif_value
        gst_tag_image_type_get_type
        gst_tag_list_add_id3_image
        gst_tag_list_from_exif_buffer