From e327be5a9619adab8cf8a22d8fbbe9bbb051319c Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 16 Jun 2010 11:19:37 -0300 Subject: [PATCH] tag: exif: Adds mapping for GST_TAG_IMAGE_ORIENTATION Adds GST_TAG_IMAGE_ORIENTATION to the exif helper lib mapped tags. Tests included. --- gst-libs/gst/tag/Makefile.am | 2 +- gst-libs/gst/tag/gstexiftag.c | 83 +++++++++++++++++++++++++ gst-libs/gst/tag/gsttageditingprivate.c | 76 ++++++++++++++++++++++ gst-libs/gst/tag/gsttageditingprivate.h | 3 + tests/check/libs/tag.c | 18 ++++++ win32/common/libgsttag.def | 2 + 6 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 gst-libs/gst/tag/gsttageditingprivate.c diff --git a/gst-libs/gst/tag/Makefile.am b/gst-libs/gst/tag/Makefile.am index 757bb58d28..7a8dc54b61 100644 --- a/gst-libs/gst/tag/Makefile.am +++ b/gst-libs/gst/tag/Makefile.am @@ -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) diff --git a/gst-libs/gst/tag/gstexiftag.c b/gst-libs/gst/tag/gstexiftag.c index d452ff6d27..411280265e 100644 --- a/gst-libs/gst/tag/gstexiftag.c +++ b/gst-libs/gst/tag/gstexiftag.c @@ -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}, @@ -369,6 +377,22 @@ gst_exif_writer_write_byte_tag (GstExifWriter * writer, guint16 tag, 1, offset, TRUE); } +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) { @@ -1007,6 +1031,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 index 0000000000..ebebfdf646 --- /dev/null +++ b/gst-libs/gst/tag/gsttageditingprivate.c @@ -0,0 +1,76 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * 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 + +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; + } +} diff --git a/gst-libs/gst/tag/gsttageditingprivate.h b/gst-libs/gst/tag/gsttageditingprivate.h index 04275230f8..89e63787f9 100644 --- a/gst-libs/gst/tag/gsttageditingprivate.h +++ b/gst-libs/gst/tag/gsttageditingprivate.h @@ -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 diff --git a/tests/check/libs/tag.c b/tests/check/libs/tag.c index 448ca2ea08..adbf78edcf 100644 --- a/tests/check/libs/tag.c +++ b/tests/check/libs/tag.c @@ -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); diff --git a/win32/common/libgsttag.def b/win32/common/libgsttag.def index 846bba6604..6cae63a0ea 100644 --- a/win32/common/libgsttag.def +++ b/win32/common/libgsttag.def @@ -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