tag: exif: Adds mappings for new image ppi tags
authorThiago Santos <thiago.sousa.santos@collabora.co.uk>
Tue, 7 Sep 2010 11:46:15 +0000 (08:46 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.co.uk>
Tue, 7 Sep 2010 13:07:29 +0000 (10:07 -0300)
Adds mappings for GST_TAG_IMAGE_HORIZONTAL/VERTICAL_PPI into
our exif lib

Tests included.

Fixes #626570

gst-libs/gst/tag/gstexiftag.c
tests/check/libs/tag.c

index 2af7e86..14f0ce8 100644 (file)
@@ -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:
@@ -2420,6 +2454,55 @@ deserialize_flash (GstExifReader * exif_reader,
 }
 
 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,
     GstExifTagData * tagdata)
index 7e347eb..2a399f7 100644 (file)
@@ -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);