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
This commit is contained in:
Paulo Neves 2016-06-11 17:11:30 +02:00 committed by Sebastian Dröge
parent d423406e0a
commit 5dd720e064
2 changed files with 17 additions and 14 deletions

View file

@ -2090,9 +2090,9 @@ serialize_geo_coordinate (GstExifWriter * writer, const GstTagList * taglist,
{ {
gboolean latitude; gboolean latitude;
gdouble value; gdouble value;
gint degrees; guint32 degrees;
gint minutes; guint32 minutes;
gint seconds; guint32 seconds_numerator, seconds_denominator;
guint32 offset; guint32 offset;
latitude = exiftag->exif_tag == EXIF_TAG_GPS_LATITUDE; /* exif tag for latitude */ 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 */ /* now write the degrees stuff */
GST_LOG ("Converting geo location %lf to degrees", value); GST_DEBUG ("Converting %lf degrees geo location to HMS", value);
degrees = (gint) value; degrees = (guint32) value;
value -= degrees; value -= degrees;
minutes = (gint) (value * 60); minutes = (guint32) (value * 60);
value = (value * 60) - minutes; value = (value * 60) - minutes;
seconds = (gint) (value * 60); seconds_denominator = 10000000UL;
GST_LOG ("Converted geo location to %d.%d'%d'' degrees", degrees, seconds_numerator = (guint32) (value * 60 * seconds_denominator);
minutes, seconds);
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); offset = gst_byte_writer_get_size (&writer->datawriter);
gst_exif_writer_write_tag_header (writer, exiftag->exif_tag, gst_exif_writer_write_tag_header (writer, exiftag->exif_tag,
EXIF_TYPE_RATIONAL, 3, offset, NULL); EXIF_TYPE_RATIONAL, 3, offset, NULL);
gst_exif_writer_write_rational_data (writer, degrees, 1); 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, minutes, 1);
gst_exif_writer_write_rational_data (writer, seconds, 1); gst_exif_writer_write_rational_data (writer, seconds_numerator,
seconds_denominator);
} }
static gint static gint
@ -2251,12 +2254,11 @@ deserialize_geo_coordinate (GstExifReader * exif_reader,
gst_util_fraction_to_double (degrees_n, degrees_d, &degrees); gst_util_fraction_to_double (degrees_n, degrees_d, &degrees);
gst_util_fraction_to_double (minutes_n, minutes_d, &minutes); gst_util_fraction_to_double (minutes_n, minutes_d, &minutes);
gst_util_fraction_to_double (seconds_n, seconds_d, &seconds); gst_util_fraction_to_double (seconds_n, seconds_d, &seconds);
minutes += seconds / 60; minutes += seconds / 60;
degrees += minutes / 60; degrees += minutes / 60;
degrees *= multiplier; 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, gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_REPLACE,
exiftag->gst_tag, degrees, NULL); exiftag->gst_tag, degrees, NULL);

View file

@ -1676,10 +1676,11 @@ GST_START_TEST (test_exif_tags_serialization_deserialization)
g_value_unset (&value); g_value_unset (&value);
g_value_init (&value, G_TYPE_DOUBLE); 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 do_simple_exif_tag_serialization_deserialization
(GST_TAG_GEO_LOCATION_LATITUDE, &value); (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 do_simple_exif_tag_serialization_deserialization
(GST_TAG_GEO_LOCATION_LATITUDE, &value); (GST_TAG_GEO_LOCATION_LATITUDE, &value);
g_value_set_double (&value, 0); g_value_set_double (&value, 0);