fix(raw): PIL fallback for iPhone Apple ProRAW / Linear DNG

LibRaw (rawpy 0.26.1, libraw 0.22.0) rejects Apple ProRAW Linear DNG with
'Unsupported file format or not RAW file'. These files aren't Bayer-pattern
RAW — they're TIFF containers holding an already-developed RGB image, so
PIL opens them directly. iPhone Linear DNG also has no embedded preview
exiftool can extract, so the existing fallback chain ran out of options.

Added PIL Image.open(src_path) as the last fallback in both code paths
(_generate_proxy_webp for /photos/{id}/proxy, and tasks.thumbs.process_raw_image
for thumbnail generation). Covers ~1,300 iPhone DNG files in the library
that were 415-ing on every detail view.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claudio
2026-05-10 21:20:53 +02:00
parent 0eee0cecde
commit 758fda619e
2 changed files with 23 additions and 5 deletions

View File

@@ -745,8 +745,16 @@ def _generate_proxy_webp(src_path: str, dst_path: str) -> None:
from io import BytesIO
img = Image.open(BytesIO(thumb.data))
except Exception as e2:
logger.error(f"RAW preview extraction also failed for {src_path}: {e2}")
raise HTTPException(status_code=415, detail="Unable to decode RAW file")
# Last-resort: iPhone "Apple ProRAW" / Linear DNG isn't a
# Bayer-pattern RAW — LibRaw rejects it. The file IS a TIFF
# container with a developed RGB image inside, so PIL opens
# it directly. Same fallback covers misnamed TIFFs.
logger.warning(f"RAW preview extraction failed for {src_path}: {e2}; trying PIL TIFF fallback")
try:
img = Image.open(src_path)
except Exception as e3:
logger.error(f"PIL fallback also failed for {src_path}: {e3}")
raise HTTPException(status_code=415, detail="Unable to decode RAW file")
# HEIC/HEIF — pillow-heif registers a PIL plugin
elif ext in {'.heic', '.heif'}:

View File

@@ -74,9 +74,19 @@ def process_raw_image(filepath: str) -> Image.Image:
# Convert numpy array to PIL Image
return Image.fromarray(rgb, 'RGB')
except Exception as e:
logger.error(f"Error processing RAW file {filepath}: {e}")
# Try to extract embedded JPEG preview
return extract_raw_preview(filepath)
logger.warning(f"rawpy failed for {filepath}: {e}; trying embedded preview")
preview = extract_raw_preview(filepath)
if preview is not None:
return preview
# iPhone "Apple ProRAW" / Linear DNG has no embedded preview and
# LibRaw rejects it as not-a-RAW. It IS a TIFF container with a
# developed RGB image inside, so PIL opens it directly.
try:
logger.warning(f"embedded preview missing for {filepath}; trying PIL TIFF fallback")
return Image.open(filepath)
except Exception as e2:
logger.error(f"PIL fallback also failed for {filepath}: {e2}")
raise
else:
# Use exiftool to extract embedded preview
return extract_raw_preview(filepath)