diff --git a/gst-libs/gst/tag/gstexiftag.c b/gst-libs/gst/tag/gstexiftag.c index 2af7e86f9f..14f0ce8783 100644 --- a/gst-libs/gst/tag/gstexiftag.c +++ b/gst-libs/gst/tag/gstexiftag.c @@ -242,6 +242,7 @@ EXIF_SERIALIZATION_DESERIALIZATION_FUNC (shutter_speed); EXIF_SERIALIZATION_DESERIALIZATION_FUNC (speed); EXIF_SERIALIZATION_DESERIALIZATION_FUNC (white_balance); +EXIF_DESERIALIZATION_FUNC (resolution); EXIF_DESERIALIZATION_FUNC (add_to_pending_tags); /* FIXME copyright tag has a weird "artist\0editor\0" format that is @@ -264,6 +265,9 @@ EXIF_DESERIALIZATION_FUNC (add_to_pending_tags); #define EXIF_TAG_MAKE 0x10F #define EXIF_TAG_MODEL 0x110 #define EXIF_TAG_ORIENTATION 0x112 +#define EXIF_TAG_XRESOLUTION 0x11A +#define EXIF_TAG_YRESOLUTION 0x11B +#define EXIF_TAG_RESOLUTION_UNIT 0x128 #define EXIF_TAG_SOFTWARE 0x131 #define EXIF_TAG_DATE_TIME 0x132 #define EXIF_TAG_ARTIST 0x13B @@ -310,6 +314,12 @@ EXIF_DESERIALIZATION_FUNC (add_to_pending_tags); * deserialization-func} */ static const GstExifTagMatch tag_map_ifd0[] = { + {GST_TAG_IMAGE_HORIZONTAL_PPI, EXIF_TAG_XRESOLUTION, EXIF_TYPE_RATIONAL, + 0, NULL, deserialize_add_to_pending_tags}, + {GST_TAG_IMAGE_VERTICAL_PPI, EXIF_TAG_YRESOLUTION, EXIF_TYPE_RATIONAL, + 0, NULL, deserialize_add_to_pending_tags}, + {NULL, EXIF_TAG_RESOLUTION_UNIT, EXIF_TYPE_SHORT, 0, NULL, + deserialize_resolution}, {GST_TAG_DESCRIPTION, EXIF_TAG_IMAGE_DESCRIPTION, EXIF_TYPE_ASCII, 0, NULL, NULL}, {GST_TAG_DEVICE_MANUFACTURER, EXIF_TAG_MAKE, EXIF_TYPE_ASCII, 0, NULL, NULL}, @@ -1523,6 +1533,30 @@ parse_exif_ifd (GstExifReader * exif_reader, gint buf_offset, } } + /* check if the pending tags have something that can still be added */ + { + GSList *walker; + GstExifTagData *data; + + for (walker = exif_reader->pending_tags; walker; + walker = g_slist_next (walker)) { + data = (GstExifTagData *) walker->data; + switch (data->tag) { + case EXIF_TAG_XRESOLUTION: + parse_exif_rational_tag (exif_reader, GST_TAG_IMAGE_HORIZONTAL_PPI, + data->count, data->offset, 1, FALSE); + break; + case EXIF_TAG_YRESOLUTION: + parse_exif_rational_tag (exif_reader, GST_TAG_IMAGE_VERTICAL_PPI, + data->count, data->offset, 1, FALSE); + break; + default: + /* NOP */ + break; + } + } + } + return TRUE; read_error: @@ -2419,6 +2453,55 @@ deserialize_flash (GstExifReader * exif_reader, return 0; } +static gint +deserialize_resolution (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + GstExifTagData *xres = NULL; + GstExifTagData *yres = NULL; + guint16 unit; + gdouble multiplier; + + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + unit = GST_READ_UINT16_LE (tagdata->offset_as_data); + } else { + unit = GST_READ_UINT16_BE (tagdata->offset_as_data); + } + + if (unit != 2 && unit != 3) { + GST_WARNING ("Invalid resolution unit, ignoring PPI tags"); + return 0; + } + + xres = gst_exif_reader_get_pending_tag (exif_reader, EXIF_TAG_XRESOLUTION); + yres = gst_exif_reader_get_pending_tag (exif_reader, EXIF_TAG_YRESOLUTION); + + switch (unit) { + case 2: /* inch */ + multiplier = 1; + break; + case 3: /* cm */ + multiplier = 1 / 2.54; + break; + default: + multiplier = 1; + g_assert_not_reached (); + break; + } + + if (xres) { + parse_exif_rational_tag (exif_reader, GST_TAG_IMAGE_HORIZONTAL_PPI, + xres->count, xres->offset, multiplier, FALSE); + } + if (yres) { + parse_exif_rational_tag (exif_reader, GST_TAG_IMAGE_VERTICAL_PPI, + yres->count, yres->offset, multiplier, FALSE); + } + + return 0; +} + static gint deserialize_add_to_pending_tags (GstExifReader * exif_reader, GstByteReader * reader, const GstExifTagMatch * exiftag, diff --git a/tests/check/libs/tag.c b/tests/check/libs/tag.c index 7e347eb98b..2a399f7dc0 100644 --- a/tests/check/libs/tag.c +++ b/tests/check/libs/tag.c @@ -1220,10 +1220,14 @@ GST_START_TEST (test_exif_multiple_tags) GstDateTime *datetime; GValue value = { 0 }; + gst_tag_register_musicbrainz_tags (); + taglist = gst_tag_list_new_full (GST_TAG_ARTIST, "artist", GST_TAG_DEVICE_MANUFACTURER, "make", GST_TAG_DEVICE_MODEL, "model", GST_TAG_GEO_LOCATION_LATITUDE, 45.5, - GST_TAG_GEO_LOCATION_LONGITUDE, -10.25, NULL); + GST_TAG_GEO_LOCATION_LONGITUDE, -10.25, + GST_TAG_IMAGE_HORIZONTAL_PPI, 300.0, + GST_TAG_IMAGE_VERTICAL_PPI, 300.0, NULL); g_value_init (&value, GST_TYPE_DATE_TIME); datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10, 0); @@ -1372,14 +1376,14 @@ GST_START_TEST (test_exif_tags_serialization_deserialization) &value); g_value_set_static_string (&value, "normal"); - do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SATURATION, - &value); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SATURATION, &value); g_value_set_static_string (&value, "low-saturation"); - do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SATURATION, - &value); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SATURATION, &value); g_value_set_static_string (&value, "high-saturation"); - do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SATURATION, - &value); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SATURATION, &value); g_value_unset (&value); g_value_init (&value, G_TYPE_DOUBLE); @@ -1452,6 +1456,19 @@ GST_START_TEST (test_exif_tags_serialization_deserialization) g_value_set_double (&value, 2.7); do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_FOCAL_LENGTH, &value); + + g_value_set_double (&value, 96.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_IMAGE_HORIZONTAL_PPI, &value); + g_value_set_double (&value, 300.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_IMAGE_HORIZONTAL_PPI, &value); + g_value_set_double (&value, 87.5); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_IMAGE_VERTICAL_PPI, &value); + g_value_set_double (&value, 600.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_IMAGE_VERTICAL_PPI, &value); g_value_unset (&value); g_value_init (&value, G_TYPE_INT);