aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Tilloy <olivier@tilloy.net>2011-08-22 08:31:19 +0200
committerOlivier Tilloy <olivier@tilloy.net>2011-08-22 08:31:19 +0200
commit34f55f38b2bbb18843b53c6804f4410d9a3f1dc1 (patch)
tree1a3438d7dd8cbc31139a67ec228027dc474bfdb6
parent39ce84eb5a85f32a2f2521a7ba7d3451a1244584 (diff)
parent0d90a8a6a7339543b01f8548d330e279a2067ea6 (diff)
downloadpyexiv2-34f55f38b2bbb18843b53c6804f4410d9a3f1dc1.tar.gz
Correctly extract the type of an EXIF tag when read from an image.
-rw-r--r--src/exiv2wrapper.cpp16
-rw-r--r--test/data/MD5SUMS1
-rw-r--r--test/data/pentax-makernote.jpgbin0 -> 47549 bytes
-rw-r--r--test/exif.py28
-rw-r--r--test/usercomment.py8
5 files changed, 52 insertions, 1 deletions
diff --git a/src/exiv2wrapper.cpp b/src/exiv2wrapper.cpp
index ad37f57..332b78f 100644
--- a/src/exiv2wrapper.cpp
+++ b/src/exiv2wrapper.cpp
@@ -1,6 +1,6 @@
// *****************************************************************************
/*
- * Copyright (C) 2006-2010 Olivier Tilloy <olivier@tilloy.net>
+ * Copyright (C) 2006-2011 Olivier Tilloy <olivier@tilloy.net>
*
* This file is part of the pyexiv2 distribution.
*
@@ -554,6 +554,13 @@ ExifTag::ExifTag(const std::string& key,
#if EXIV2_TEST_VERSION(0,21,0)
Exiv2::ExifKey exifKey(key);
_type = Exiv2::TypeInfo::typeName(exifKey.defaultTypeId());
+ // Where available, extract the type from the metadata, it is more reliable
+ // than static type information. The exception is for user comments, for
+ // which we’d rather keep the 'Comment' type instead of 'Undefined'.
+ if ((_data != 0) && (_type != "Comment"))
+ {
+ _type = _datum->typeName();
+ }
_name = exifKey.tagName();
_label = exifKey.tagLabel();
_description = exifKey.tagDesc();
@@ -566,6 +573,13 @@ ExifTag::ExifTag(const std::string& key,
const uint16_t tag = _datum->tag();
const Exiv2::IfdId ifd = _datum->ifdId();
_type = Exiv2::TypeInfo::typeName(Exiv2::ExifTags::tagType(tag, ifd));
+ // Where available, extract the type from the metadata, it is more reliable
+ // than static type information. The exception is for user comments, for
+ // which we’d rather keep the 'Comment' type instead of 'Undefined'.
+ if ((_data != 0) && (_type != "Comment"))
+ {
+ _type = _datum->typeName();
+ }
_name = Exiv2::ExifTags::tagName(tag, ifd);
_label = Exiv2::ExifTags::tagLabel(tag, ifd);
_description = Exiv2::ExifTags::tagDesc(tag, ifd);
diff --git a/test/data/MD5SUMS b/test/data/MD5SUMS
index c664932..c692790 100644
--- a/test/data/MD5SUMS
+++ b/test/data/MD5SUMS
@@ -1,5 +1,6 @@
e8525211f62a0944db9072f73750258c empty.jpg
64d4b7eab1e78f1f6bfb3c966e99eef2 exiv2-bug540.jpg
+646804b309a4a2d31feafe9bffc5d7f0 pentax-makernote.jpg
c066958457c685853293058f9bf129c1 smiley1.jpg
ad29ac65fb6f63c8361aaed6cb02f8c7 usercomment-ascii.jpg
13b7cc09129a8677f2cf18634f5abd3c usercomment-unicode-ii.jpg
diff --git a/test/data/pentax-makernote.jpg b/test/data/pentax-makernote.jpg
new file mode 100644
index 0000000..67638ab
--- /dev/null
+++ b/test/data/pentax-makernote.jpg
Binary files differ
diff --git a/test/exif.py b/test/exif.py
index c9cc609..2bfbc67 100644
--- a/test/exif.py
+++ b/test/exif.py
@@ -27,8 +27,11 @@
import unittest
from pyexiv2.exif import ExifTag, ExifValueError
+from pyexiv2.metadata import ImageMetadata
from pyexiv2.utils import make_fraction
+from testutils import CheckFileSum
+
import datetime
@@ -334,3 +337,28 @@ class TestExifTag(unittest.TestCase):
value = '2 0 0 foo'
self.failUnlessRaises(ValueError, setattr, tag, 'raw_value', value)
+ def test_makernote_types(self):
+ # Makernote tags not attached to an image have an Undefined type by
+ # default. When read from an existing image though, their type should be
+ # correctly set (see https://bugs.launchpad.net/pyexiv2/+bug/781464).
+ tag1 = ExifTag('Exif.Pentax.PreviewResolution')
+ tag1.raw_value = '640 480'
+ self.assertEqual(tag1.type, 'Undefined')
+ self.failUnlessRaises(ValueError, getattr, tag1, 'value')
+ tag2 = ExifTag('Exif.Pentax.CameraInfo')
+ tag2.raw_value = '76830 20070527 2 1 4228109'
+ self.assertEqual(tag2.type, 'Undefined')
+ self.failUnlessRaises(ValueError, getattr, tag2, 'value')
+
+ filename = 'test/data/pentax-makernote.jpg'
+ checksum = '646804b309a4a2d31feafe9bffc5d7f0'
+ self.assert_(CheckFileSum(filename, checksum))
+ metadata = ImageMetadata('test/data/pentax-makernote.jpg')
+ metadata.read()
+ tag1 = metadata[tag1.key]
+ self.assertEqual(tag1.type, 'Short')
+ self.assertEqual(tag1.value, [640, 480])
+ tag2 = metadata[tag2.key]
+ self.assertEqual(tag2.type, 'Long')
+ self.assertEqual(tag2.value, [76830L, 20070527L, 2L, 1L, 4228109L])
+
diff --git a/test/usercomment.py b/test/usercomment.py
index cc8ff1a..a9b4774 100644
--- a/test/usercomment.py
+++ b/test/usercomment.py
@@ -59,24 +59,28 @@ class TestUserCommentReadWrite(unittest.TestCase):
def test_read_ascii(self):
m = self._read_image('usercomment-ascii.jpg')
tag = m['Exif.Photo.UserComment']
+ self.assertEqual(tag.type, 'Comment')
self.assertEqual(tag.raw_value, 'charset="Ascii" deja vu')
self.assertEqual(tag.value, u'deja vu')
def test_read_unicode_little_endian(self):
m = self._read_image('usercomment-unicode-ii.jpg')
tag = m['Exif.Photo.UserComment']
+ self.assertEqual(tag.type, 'Comment')
self.assertEqual(tag.raw_value, 'charset="Unicode" %s' % self._expected_raw_value('ii', 'déjà vu'))
self.assertEqual(tag.value, u'déjà vu')
def test_read_unicode_big_endian(self):
m = self._read_image('usercomment-unicode-mm.jpg')
tag = m['Exif.Photo.UserComment']
+ self.assertEqual(tag.type, 'Comment')
self.assertEqual(tag.raw_value, 'charset="Unicode" %s' % self._expected_raw_value('mm', 'déjà vu'))
self.assertEqual(tag.value, u'déjà vu')
def test_write_ascii(self):
m = self._read_image('usercomment-ascii.jpg')
tag = m['Exif.Photo.UserComment']
+ self.assertEqual(tag.type, 'Comment')
tag.value = 'foo bar'
self.assertEqual(tag.raw_value, 'charset="Ascii" foo bar')
self.assertEqual(tag.value, u'foo bar')
@@ -84,6 +88,7 @@ class TestUserCommentReadWrite(unittest.TestCase):
def test_write_unicode_over_ascii(self):
m = self._read_image('usercomment-ascii.jpg')
tag = m['Exif.Photo.UserComment']
+ self.assertEqual(tag.type, 'Comment')
tag.value = u'déjà vu'
self.assertEqual(tag.raw_value, 'déjà vu')
self.assertEqual(tag.value, u'déjà vu')
@@ -91,6 +96,7 @@ class TestUserCommentReadWrite(unittest.TestCase):
def test_write_unicode_little_endian(self):
m = self._read_image('usercomment-unicode-ii.jpg')
tag = m['Exif.Photo.UserComment']
+ self.assertEqual(tag.type, 'Comment')
tag.value = u'DÉJÀ VU'
self.assertEqual(tag.raw_value, 'charset="Unicode" %s' % self._expected_raw_value('ii', 'DÉJÀ VU'))
self.assertEqual(tag.value, u'DÉJÀ VU')
@@ -98,6 +104,7 @@ class TestUserCommentReadWrite(unittest.TestCase):
def test_write_unicode_big_endian(self):
m = self._read_image('usercomment-unicode-mm.jpg')
tag = m['Exif.Photo.UserComment']
+ self.assertEqual(tag.type, 'Comment')
tag.value = u'DÉJÀ VU'
self.assertEqual(tag.raw_value, 'charset="Unicode" %s' % self._expected_raw_value('mm', 'DÉJÀ VU'))
self.assertEqual(tag.value, u'DÉJÀ VU')
@@ -125,6 +132,7 @@ class TestUserCommentAdd(unittest.TestCase):
metadata.read()
self.assert_(key in metadata.exif_keys)
tag = metadata[key]
+ self.assertEqual(tag.type, 'Comment')
self.assertEqual(tag.value, value)
def test_add_comment_ascii(self):