mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-14 19:27:05 -04:00
Media: Targa/HDR stills keep their Exif orientation; DPX test accepts a stated transfer
#755 decoded stills of an extension-decided format with load_from_memory_with_format, bypassing #827's oriented decode: load_oriented now takes the format. The DPX ffmpeg oracle test expected the bare codec name; ffmpeg builds that write the transfer characteristic make it "DPX 8-bit RGB, linear". Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
42ef79a2fd
commit
6d4e721d2c
4 files changed
+13
-9
No files matched your search
@@ -87,7 +87,7 @@ pub(crate) fn decode(path: &str, bytes: &[u8], footage: &Footage, op: AlphaOp) -
|
||||
let inner = effectcraft_psd::Psd::parse(data.to_vec()).map_err(|e| MediaError::Decode(format!("{path} (smart object): {e}")))?;
|
||||
inner.composite().map_err(|e| MediaError::Decode(format!("{path} (smart object): {e}")))?
|
||||
} else {
|
||||
let img = crate::probe::load_oriented(data).map_err(|e| MediaError::Decode(format!("{path} (smart object): {e}")))?;
|
||||
let img = crate::probe::load_oriented(data, None).map_err(|e| MediaError::Decode(format!("{path} (smart object): {e}")))?;
|
||||
let rgba = img.to_rgba32f();
|
||||
effectcraft_psd::Pixels { width: rgba.width(), height: rgba.height(), data: rgba.pixels().map(|p| p.0).collect() }
|
||||
};
|
||||
|
||||
@@ -770,10 +770,7 @@ impl Inner {
|
||||
{
|
||||
return Err(MediaError::Decode(format!("{path}: {why}")));
|
||||
}
|
||||
let loaded = match crate::still_format(path, &bytes) {
|
||||
Some(fmt) => image::load_from_memory_with_format(&bytes, fmt),
|
||||
None => crate::probe::load_oriented(&bytes),
|
||||
};
|
||||
let loaded = crate::probe::load_oriented(&bytes, crate::still_format(path, &bytes));
|
||||
let img = match loaded {
|
||||
Ok(img) => img,
|
||||
// A multi-layer OpenEXR file without an unnamed RGB layer: its colour layer.
|
||||
|
||||
@@ -221,10 +221,15 @@ pub(crate) fn swaps_sides(o: Orientation) -> bool {
|
||||
|
||||
/// Decode a still the way it is meant to be seen: its Exif orientation (a camera held sideways, a
|
||||
/// mirrored scan) is applied to the pixels, as image viewers do. A file without
|
||||
/// the tag, or with a broken one, decodes as stored.
|
||||
pub(crate) fn load_oriented(bytes: &[u8]) -> image::ImageResult<image::DynamicImage> {
|
||||
/// the tag, or with a broken one, decodes as stored. `fmt`: the format when the file's extension
|
||||
/// decides it (Targa has no signature to guess from), else guessed from the bytes.
|
||||
pub(crate) fn load_oriented(bytes: &[u8], fmt: Option<image::ImageFormat>) -> image::ImageResult<image::DynamicImage> {
|
||||
use image::ImageDecoder;
|
||||
let mut dec = image::ImageReader::new(std::io::Cursor::new(bytes)).with_guessed_format()?.into_decoder()?;
|
||||
let reader = match fmt {
|
||||
Some(fmt) => image::ImageReader::with_format(std::io::Cursor::new(bytes), fmt),
|
||||
None => image::ImageReader::new(std::io::Cursor::new(bytes)).with_guessed_format()?,
|
||||
};
|
||||
let mut dec = reader.into_decoder()?;
|
||||
let orientation = dec.orientation().unwrap_or(Orientation::NoTransforms);
|
||||
let mut img = image::DynamicImage::from_decoder(dec)?;
|
||||
img.apply_orientation(orientation);
|
||||
|
||||
@@ -943,7 +943,9 @@ fn dpx_stills_match_ffmpeg() {
|
||||
assert!(effectcraft_media::is_importable(&p));
|
||||
let f = probe(&p).expect(pf);
|
||||
assert_eq!(f.kind, FootageKind::Still);
|
||||
assert_eq!((f.width, f.height, f.codec.as_str()), (250, 100, codec), "{pf}");
|
||||
assert_eq!((f.width, f.height), (250, 100), "{pf}");
|
||||
// Some ffmpeg builds state the transfer (", linear"), which the codec name then carries.
|
||||
assert!(f.codec == codec || f.codec.starts_with(&format!("{codec}, ")), "{pf}: {}", f.codec);
|
||||
assert_eq!(f.alpha, if alpha { AlphaMode::Straight } else { AlphaMode::Ignore }, "{pf}");
|
||||
let img = MediaPool::new().frame_at(&f, Tick::ZERO).expect(pf);
|
||||
let want = ffmpeg_rgba(&p, !codec.contains("8-bit"));
|
||||
|
||||
Reference in new issue
Block a user