fix: try all 3 EXIF date tags + raw bytes scan in _read_cr2_exif
This commit is contained in:
1 parent
1bc1150fa8
commit
6a0fe3c163
1 file changed
+27
-11
+27
-11
@@ -176,18 +176,24 @@ def _read_other_exif_pil(path: Path) -> str | None:
|
||||
|
||||
|
||||
def _read_cr2_exif(path: Path) -> str | None:
|
||||
"""CR2/CR3 (Canon Raw): try piexif first, then PIL embedded JPEG."""
|
||||
# Tier 1: piexif on CR2 (TIFF-based EXIF)
|
||||
"""CR2/CR3 (Canon Raw): try piexif, then PIL, then raw bytes scan."""
|
||||
# ── Tier 1: piexif (TIFF-based EXIF) ──────────────────────
|
||||
if HAS_PIEXIF:
|
||||
try:
|
||||
exif_dict = piexif.load(str(path))
|
||||
raw_val = exif_dict.get('Exif', {}).get(piexif.ExifIFD.DateTimeOriginal)
|
||||
if raw_val:
|
||||
return raw_val.decode('utf-8')
|
||||
# All possible date tag locations in EXIF
|
||||
for ifd_name, tag_id in (
|
||||
('Exif', piexif.ExifIFD.DateTimeOriginal), # 36867
|
||||
('Exif', piexif.ExifIFD.DateTimeDigitized), # 36868
|
||||
('Image', piexif.ImageIFD.DateTime), # 306
|
||||
):
|
||||
raw_val = exif_dict.get(ifd_name, {}).get(tag_id)
|
||||
if raw_val:
|
||||
return raw_val.decode('utf-8')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Tier 2: PIL can read EXIF from CR2's embedded JPEG preview
|
||||
# ── Tier 2: PIL (embedded JPEG preview) ───────────────────
|
||||
try:
|
||||
from PIL import Image
|
||||
from PIL.ExifTags import TAGS
|
||||
@@ -195,11 +201,21 @@ def _read_cr2_exif(path: Path) -> str | None:
|
||||
raw = img._getexif()
|
||||
img.close()
|
||||
if raw:
|
||||
tag_map = {v: k for k, v in TAGS.items()}
|
||||
for tag_name in ('DateTimeOriginal', 'DateTime'):
|
||||
tag_code = tag_map.get(tag_name)
|
||||
if tag_code and tag_code in raw:
|
||||
return raw[tag_code]
|
||||
for tag_code in (36867, 36868, 306): # DateTimeOriginal, Digitized, DateTime
|
||||
val = raw.get(tag_code)
|
||||
if val:
|
||||
return val
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# ── Tier 3: raw bytes scan (last resort) ──────────────────
|
||||
try:
|
||||
data = path.read_bytes()
|
||||
# CR2 stores dates as ASCII 'YYYY:MM:DD HH:MM:SS'
|
||||
import re
|
||||
m = re.search(rb'(\d{4}:\d{2}:\d{2} \d{2}:\d{2}:\d{2})', data)
|
||||
if m:
|
||||
return m.group(1).decode('ascii')
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
Reference in new issue
Block a user