diff --git a/src/machinevisiontoolbox/ImageIO.py b/src/machinevisiontoolbox/ImageIO.py index eef14dad..f39b8f09 100644 --- a/src/machinevisiontoolbox/ImageIO.py +++ b/src/machinevisiontoolbox/ImageIO.py @@ -267,6 +267,14 @@ def metadata(self, key: str | None = None) -> Any: # map tag number to tag name exif[TAGS[tag]] = value + # Camera-specific tags (FocalLength, ExposureTime, FNumber, + # ISOSpeedRatings, LensModel, ...) live in a separate "Exif" sub-IFD + # that Image.getexif() does not flatten into the top-level dict -- + # 0x8769 is the fixed EXIF-spec tag id for the pointer to it. + for tag, value in meta.get_ifd(0x8769).items(): + if tag in TAGS: + exif[TAGS[tag]] = value + if key is None: return exif else: diff --git a/tests/test_image_io.py b/tests/test_image_io.py index 75e30e39..6008d018 100644 --- a/tests/test_image_io.py +++ b/tests/test_image_io.py @@ -190,14 +190,23 @@ def test_disp(self): # im.disp(block=False) pass - # new test def test_metadata(self): """Test reading image metadata""" - # TODO: Test with image file that has metadata - # im = Image.Read('test_image.jpg') - # metadata = im.metadata() - # self.assertIsNotNone(metadata) - pass + im = Image.Read("walls-l.png") + metadata = im.metadata() + self.assertIsNotNone(metadata) + + # top-level IFD0 tags + self.assertEqual(metadata["Make"], "Apple") + self.assertEqual(metadata["Model"], "iPhone 5s") + self.assertEqual(im.metadata("Make"), "Apple") + + # camera-specific tags live in a separate "Exif" sub-IFD that + # Image.getexif() doesn't flatten into the top-level dict -- + # regression test for that sub-IFD merge + self.assertIn("FocalLength", metadata) + self.assertAlmostEqual(im.metadata("FocalLength"), 4.15) + self.assertAlmostEqual(metadata["FNumber"], 2.2) # new test def test_showpixels(self):