summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Vinnicombe <william.vinnicombe@raspberrypi.com>2022-08-03 09:25:39 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2022-08-03 14:32:19 +0300
commit23b6965a9330cf1cab51e9e77b99aad4a90ae89a (patch)
tree6a3a09d614e2b111bb2bee7b9bf6eb5b4a1ba78d
parent79b4c1c51ed82f115a3df02279f252d0cc37a620 (diff)
utils: raspberrypi: ctt: dng_load_image: Work with DNG files from Picamera2
The DNG specification is based on the TIFF file format and recommends storing the raw image data in a SubIFD and the Exif tags in an Exif IFD. Other options are allowed, even if not recommended, such as storing both the raw image data and the Exif data in IFD0, as done by the TIFF/EP specification. libcamera-apps use pyexiv2 to produce DNG files, following the DNG recommendation, while applications based on picamera2 use PiDNG, which adopts the TIFF/EP structure. Why it does so is not currently clear (see https://github.com/schoolpost/PiDNG/issues/65 for discussions on this topic), but as files based on the DNG and TIFF/EP variants exist in the wild, both need to be supported by ctt. Add code to identify which tags are being used, and then load the metadata from the correct tags. Signed-off-by: William Vinnicombe <william.vinnicombe@raspberrypi.com> Reviewed-by: David Plowman <david.plowman@raspberrypi.com> Reviewed-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--utils/raspberrypi/ctt/ctt_image_load.py32
1 files changed, 25 insertions, 7 deletions
diff --git a/utils/raspberrypi/ctt/ctt_image_load.py b/utils/raspberrypi/ctt/ctt_image_load.py
index c3d444cd..310c5e88 100644
--- a/utils/raspberrypi/ctt/ctt_image_load.py
+++ b/utils/raspberrypi/ctt/ctt_image_load.py
@@ -301,17 +301,35 @@ def dng_load_image(Cam, im_str):
metadata.read()
Img.ver = 100 # random value
- Img.w = metadata['Exif.SubImage1.ImageWidth'].value
+ """
+ The DNG and TIFF/EP specifications use different IFDs to store the raw
+ image data and the Exif tags. DNG stores them in a SubIFD and in an Exif
+ IFD respectively (named "SubImage1" and "Photo" by pyexiv2), while
+ TIFF/EP stores them both in IFD0 (name "Image"). Both are used in "DNG"
+ files, with libcamera-apps following the DNG recommendation and
+ applications based on picamera2 following TIFF/EP.
+
+ This code detects which tags are being used, and therefore extracts the
+ correct values.
+ """
+ try:
+ Img.w = metadata['Exif.SubImage1.ImageWidth'].value
+ subimage = "SubImage1"
+ photo = "Photo"
+ except KeyError:
+ Img.w = metadata['Exif.Image.ImageWidth'].value
+ subimage = "Image"
+ photo = "Image"
Img.pad = 0
- Img.h = metadata['Exif.SubImage1.ImageLength'].value
- white = metadata['Exif.SubImage1.WhiteLevel'].value
+ Img.h = metadata[f'Exif.{subimage}.ImageLength'].value
+ white = metadata[f'Exif.{subimage}.WhiteLevel'].value
Img.sigbits = int(white).bit_length()
Img.fmt = (Img.sigbits - 4) // 2
- Img.exposure = int(metadata['Exif.Photo.ExposureTime'].value*1000000)
- Img.againQ8 = metadata['Exif.Photo.ISOSpeedRatings'].value*256/100
+ Img.exposure = int(metadata[f'Exif.{photo}.ExposureTime'].value * 1000000)
+ Img.againQ8 = metadata[f'Exif.{photo}.ISOSpeedRatings'].value * 256 / 100
Img.againQ8_norm = Img.againQ8 / 256
Img.camName = metadata['Exif.Image.Model'].value
- Img.blacklevel = int(metadata['Exif.SubImage1.BlackLevel'].value[0])
+ Img.blacklevel = int(metadata[f'Exif.{subimage}.BlackLevel'].value[0])
Img.blacklevel_16 = Img.blacklevel << (16 - Img.sigbits)
bayer_case = {
'0 1 1 2': (0, (0, 1, 2, 3)),
@@ -319,7 +337,7 @@ def dng_load_image(Cam, im_str):
'2 1 1 0': (2, (3, 2, 1, 0)),
'1 0 2 1': (3, (1, 0, 3, 2))
}
- cfa_pattern = metadata['Exif.SubImage1.CFAPattern'].value
+ cfa_pattern = metadata[f'Exif.{subimage}.CFAPattern'].value
Img.pattern = bayer_case[cfa_pattern][0]
Img.order = bayer_case[cfa_pattern][1]