From 5dd720e064f6740fcf41afd706d10afe21048f12 Mon Sep 17 00:00:00 2001 From: Paulo Neves Date: Sat, 11 Jun 2016 17:11:30 +0200 Subject: [PATCH] exiftag: Increase serialized geo precision The serialization of double typed geographical coordinates to DMS system supported by the exif standards was previously truncated without need. The previous code truncated the seconds part of the coordinate to a fraction with denominator equal to 1 causing a bug on the deserialization when the test for the coordinate to be serialized was more precise. This patch applies a 10E6 multiplier to the numerator equal to the denominator of the rational number. Eg. Latitude = 89.5688643 Serialization DMS Old code = 89/1 deg, 34/1 min, 7/1 sec DMS New code = 89/1 deg, 34/1 min, 79114800UL/10000000UL Deserialization DMS Old code = 89.5686111111 DMS New code = 89.5688643 The new test tries to serialize a higher precision coordinate. The types of the coordinates are also guint32 instead of gint like previously. guint32 is the type of the fraction components in the exif. https://bugzilla.gnome.org/show_bug.cgi?id=767537 --- gst-libs/gst/tag/gstexiftag.c | 26 ++++++++++++++------------ tests/check/libs/tag.c | 5 +++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/gst-libs/gst/tag/gstexiftag.c b/gst-libs/gst/tag/gstexiftag.c index 895727faf4..bcdcdde1ea 100644 --- a/gst-libs/gst/tag/gstexiftag.c +++ b/gst-libs/gst/tag/gstexiftag.c @@ -2090,9 +2090,9 @@ serialize_geo_coordinate (GstExifWriter * writer, const GstTagList * taglist, { gboolean latitude; gdouble value; - gint degrees; - gint minutes; - gint seconds; + guint32 degrees; + guint32 minutes; + guint32 seconds_numerator, seconds_denominator; guint32 offset; latitude = exiftag->exif_tag == EXIF_TAG_GPS_LATITUDE; /* exif tag for latitude */ @@ -2120,21 +2120,24 @@ serialize_geo_coordinate (GstExifWriter * writer, const GstTagList * taglist, } /* now write the degrees stuff */ - GST_LOG ("Converting geo location %lf to degrees", value); - degrees = (gint) value; + GST_DEBUG ("Converting %lf degrees geo location to HMS", value); + degrees = (guint32) value; value -= degrees; - minutes = (gint) (value * 60); + minutes = (guint32) (value * 60); value = (value * 60) - minutes; - seconds = (gint) (value * 60); - GST_LOG ("Converted geo location to %d.%d'%d'' degrees", degrees, - minutes, seconds); + seconds_denominator = 10000000UL; + seconds_numerator = (guint32) (value * 60 * seconds_denominator); + + GST_DEBUG ("Converted rational geo location to %u/%u %u/%u %u/%u degrees ", + degrees, 1U, minutes, 1U, seconds_numerator, seconds_denominator); offset = gst_byte_writer_get_size (&writer->datawriter); gst_exif_writer_write_tag_header (writer, exiftag->exif_tag, EXIF_TYPE_RATIONAL, 3, offset, NULL); gst_exif_writer_write_rational_data (writer, degrees, 1); gst_exif_writer_write_rational_data (writer, minutes, 1); - gst_exif_writer_write_rational_data (writer, seconds, 1); + gst_exif_writer_write_rational_data (writer, seconds_numerator, + seconds_denominator); } static gint @@ -2251,12 +2254,11 @@ deserialize_geo_coordinate (GstExifReader * exif_reader, gst_util_fraction_to_double (degrees_n, degrees_d, °rees); gst_util_fraction_to_double (minutes_n, minutes_d, &minutes); gst_util_fraction_to_double (seconds_n, seconds_d, &seconds); - minutes += seconds / 60; degrees += minutes / 60; degrees *= multiplier; - GST_DEBUG ("Adding %s tag: %lf", exiftag->gst_tag, degrees); + GST_DEBUG ("Adding %s tag: %lf degrees", exiftag->gst_tag, degrees); gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_REPLACE, exiftag->gst_tag, degrees, NULL); diff --git a/tests/check/libs/tag.c b/tests/check/libs/tag.c index c176531878..992b198a7b 100644 --- a/tests/check/libs/tag.c +++ b/tests/check/libs/tag.c @@ -1676,10 +1676,11 @@ GST_START_TEST (test_exif_tags_serialization_deserialization) g_value_unset (&value); g_value_init (&value, G_TYPE_DOUBLE); - g_value_set_double (&value, 30.5); + g_value_set_double (&value, 40.3456784); do_simple_exif_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_LATITUDE, &value); - g_value_set_double (&value, -12.125); + g_value_set_double (&value, -12.1250865); + do_simple_exif_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_LATITUDE, &value); g_value_set_double (&value, 0);