diff --git a/crates/engine/src/files.rs b/crates/engine/src/files.rs index db762f009..f143fd429 100644 --- a/crates/engine/src/files.rs +++ b/crates/engine/src/files.rs @@ -1166,6 +1166,30 @@ mod tests { assert!(e.contains("without an embedded preview"), "{e}"); } + /// A GoPro GPR (DNG with VC-5 coded data, no preview anywhere) still imports, described from its + /// headers; loading it says what is wrong instead of naming a bare TIFF compression number. + #[test] + fn gopro_vc5_dng_imports_and_fails_to_load_with_a_clear_reason() { + use lightcraft_tiff::{IfdBuilder, ImageData, TiffWriter, Value, tags as t}; + let mut ifd = IfdBuilder::new(); + ifd.set(t::NEW_SUBFILE_TYPE, Value::Long(vec![0])); + ifd.set(t::IMAGE_WIDTH, Value::Long(vec![32])); + ifd.set(t::IMAGE_LENGTH, Value::Long(vec![16])); + ifd.set(t::BITS_PER_SAMPLE, Value::Short(vec![16])); + ifd.set(t::SAMPLES_PER_PIXEL, Value::Short(vec![1])); + ifd.set(t::PHOTOMETRIC, Value::Short(vec![32803])); + ifd.set(t::COMPRESSION, Value::Short(vec![9])); + ifd.set(t::DNG_VERSION, Value::Byte(vec![1, 4, 0, 0])); + ifd.set(t::CFA_REPEAT_PATTERN_DIM, Value::Short(vec![2, 2])); + ifd.set(t::CFA_PATTERN_EP, Value::Byte(vec![0, 1, 1, 2])); + ifd.set_image(ImageData::Tiles { tile_width: 32, tile_height: 16, tiles: vec![vec![0x5au8; 400]] }); + let f = TiffWriter::default().write(&[ifd]).unwrap(); + let p = probe_bytes("GOPR0001.GPR", &f).unwrap(); + assert_eq!((p.kind, p.preview_only, p.width, p.height), (MediaKind::Raw, None, 32, 16)); + let e = load_bytes(&f, 16).unwrap_err(); + assert!(e.contains("GoPro VC-5") && e.contains("not decoded yet"), "{e}"); + } + /// Any failure of a recognised raw (not only an unsupported variant) can fall back to its preview; /// CR3 keeps its own wording. #[test] diff --git a/crates/raw/src/dng.rs b/crates/raw/src/dng.rs index fedc033b5..a7374f603 100644 --- a/crates/raw/src/dng.rs +++ b/crates/raw/src/dng.rs @@ -125,6 +125,15 @@ pub(crate) fn decode_as(bytes: &[u8], mode: Mode, format: RawFormat) -> Result