lclevy / canon_cr3

Describing the Canon CR3 fileformat from Canon M50 / EOS R / SX70 HS / EOS RP...
GNU General Public License v3.0
276 stars 34 forks source link

`parse_cr3.py` support for R7 #29

Open AGFeldman opened 1 year ago

AGFeldman commented 1 year ago

I tried several example files from an R7 camera (firmware version 1.3.0), all using lossless RAW. They all fail here:

Traceback (most recent call last):
  File "/Users/agf/Desktop/canon_cr3/parse_cr3.py", line 379, in <module>
    if TiffIfd.TIFF_CANON_VIGNETTING_CORR2 in ctmd_makernote7.ifd:
                                              ^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'ifd'

Full output is https://gist.github.com/AGFeldman/c484bad40cf1fbe79c6c7ac88c42f836

To download an example file and reproduce:

wget https://aaron.na31.org/EYA_0236.CR3 && python3 parse_cr3.py EYA_0236.CR3

Thanks in advance if you can take a look! As an aside, I'm interested in this tool because I'm interested in automating raw burst extraction (https://github.com/lclevy/canon_cr3/issues/14#issuecomment-668002688) although my understanding is that would take more work.

cytrinox commented 1 year ago

FYI, https://github.com/dnglab/dnglab has full support for CR3 Raw Burst Frame extraction inluding metadata and CTMD.

koenkooi commented 3 months ago

I did this to get me far enough with my R8 CR3s:

Mac-Studio:canon_cr3 koen$ git diff
diff --git a/CRaw3/TiffIfd.py b/CRaw3/TiffIfd.py
index 8d2f71e..136b27b 100644
--- a/CRaw3/TiffIfd.py
+++ b/CRaw3/TiffIfd.py
@@ -4,7 +4,10 @@ from collections import namedtuple, OrderedDict
 from binascii import hexlify

 def getShortLE(d, a):
- return unpack('<H',(d)[a:a+2])[0]
+  if len(d) >1:
+    return unpack('<H',(d)[a:a+2])[0]
+  else:
+      return 0

 def getLongLE(d, a):
  return unpack('<L',(d)[a:a+4])[0]
diff --git a/parse_cr3.py b/parse_cr3.py
old mode 100644
new mode 100755
index f4041e3..bf3b722
--- a/parse_cr3.py
+++ b/parse_cr3.py
@@ -376,20 +376,23 @@ elif cr3[b'CNCV'].find(b'CanonCR3')>=0:

   #now we want raw data of TIFF entry 0x4016 (TIFF_CANON_VIGNETTING_CORR2), in subdir TIFF_MAKERNOTE, in CTMD record #7. We know it is type=4=long, little endian 32 bits
   ctmd_makernote7 = getIfd( b'CTMD', { 'type':7, 'tag':TiffIfd.TIFF_MAKERNOTE } ) #picture 0 by default
-  if TiffIfd.TIFF_CANON_VIGNETTING_CORR2 in ctmd_makernote7.ifd:
-    vignetting_corr2 = ctmd_makernote7.ifd[ TiffIfd.TIFF_CANON_VIGNETTING_CORR2 ]
-    r = Struct('<%dL' % vignetting_corr2.length).unpack_from( data, ctmd_makernote7.base+vignetting_corr2.value )
-  if options.verbose>1:
-    print(r)
+  if ctmd_makernote7:
+    if TiffIfd.TIFF_CANON_VIGNETTING_CORR2 in ctmd_makernote7.ifd:
+      vignetting_corr2 = ctmd_makernote7.ifd[ TiffIfd.TIFF_CANON_VIGNETTING_CORR2 ]
+      r = Struct('<%dL' % vignetting_corr2.length).unpack_from( data, ctmd_makernote7.base+vignetting_corr2.value )
+    if options.verbose>1:
+      print(r)

   cmt3 = getIfd( b'CMT3', None )
-  if TiffIfd.TIFF_MAKERNOTE_ROLLINFO in cmt3.ifd: # only in CSI_* files (raw burst mode)
-    rollInfoTag = cmt3.ifd[ TiffIfd.TIFF_MAKERNOTE_ROLLINFO ]
-    #print( rollInfoTag )
-    length, current, total = Struct('<%d%s' % (rollInfoTag.length, TiffIfd.tiffTypeStr[rollInfoTag.type-1])).unpack_from( data, cmt3.base+rollInfoTag.value )
-    #exif IFD for current picture in the roll
-    ifd = getIfd( b'CTMD', { 'picture':current, 'type':7, 'tag':TiffIfd.TIFF_MAKERNOTE } )
-    ifd.display()
+  if cmt3:
+    if TiffIfd.TIFF_MAKERNOTE_ROLLINFO in cmt3.ifd: # only in CSI_* files (raw burst mode)
+      rollInfoTag = cmt3.ifd[ TiffIfd.TIFF_MAKERNOTE_ROLLINFO ]
+      #print( rollInfoTag )
+      length, current, total = Struct('<%d%s' % (rollInfoTag.length, TiffIfd.tiffTypeStr[rollInfoTag.type-1])).unpack_from( data, cmt3.base+rollInfoTag.value )
+      #exif IFD for current picture in the roll
+      ifd = getIfd( b'CTMD', { 'picture':current, 'type':7, 'tag':TiffIfd.TIFF_MAKERNOTE } )
+      if ifd:
+          ifd.display()

   NT_SENSOR_INFO = namedtuple('sensorInfo','w h lb tb rb bb')
   sensorInfo = cmt3.ifd[ TiffIfd.TIFF_MAKERNOTE_SENSORINFO ]