Files
effectcraft/crates/host/tests/it/exr_layers.rs
T
aiongg 0173abde8c CI: dev-profile gate, one test binary per crate, nextest, line tables only (#2235)
* Dev profile: line tables only for workspace crates, no debug info for dependencies

* xtask ci: dev-profile gate, nextest, tests without examples, wasm --keep-going

* One integration-test binary per crate

* xtask ci: run effectcraft-gpu's shared-device tests in one cargo test process

* xtask ci: run every stage and report all failures

* xtask ci: name the stage type (clippy type_complexity)

* xtask ci: run every test pass and report all failures

* cargo fmt
2026-10-23 12:59:51 -04:00

68 lines
3.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Multi-layer OpenEXR footage and EXtractoR in a full session (#295): a file whose colour is
//! only in named layers (as Blender and Nuke write them) imports, `layer.channels` lists its
//! layers and channels, and EXtractoR shows the chosen ones.
use effectcraft_engine::Session;
use effectcraft_engine::time::Tick;
use serde_json::{Value, json};
/// An 8×4 EXR with layers `diffuse` (orange), `spec` (blue) and `depth` (Z = 0.25), and no
/// unnamed RGB layer.
fn layered_exr() -> String {
use exr::prelude::*;
let (w, h) = (8usize, 4usize);
let ch = |n: &str, v: f32| AnyChannel::new(n, FlatSamples::F32(vec![v; w * h]));
let channels = AnyChannels::sort(
vec![ch("diffuse.R", 1.0), ch("diffuse.G", 0.5), ch("diffuse.B", 0.0), ch("spec.R", 0.0), ch("spec.G", 0.0), ch("spec.B", 1.0), ch("depth.Z", 0.25)]
.into(),
);
let image = Image::from_layer(Layer::new((w, h), LayerAttributes::default(), Encoding::FAST_LOSSLESS, channels));
let path = std::env::temp_dir().join(format!("ec-exr-layers-{}.exr", std::process::id()));
image.write().to_file(&path).unwrap();
path.to_string_lossy().to_string()
}
fn px(s: &Session) -> [f32; 4] {
let cid = s.active_comp_id().unwrap();
s.render(cid, Tick::ZERO, Default::default()).get(4, 2)
}
fn near(a: [f32; 4], b: [f32; 3]) -> bool {
(0..3).all(|k| (a[k] - b[k]).abs() < 0.02)
}
#[test]
fn extractor_shows_the_chosen_layer_and_channels_of_a_layered_exr() {
let path = layered_exr();
let mut s = effectcraft_host::session();
let r = s.execute("file.import", json!({"paths": [path]})).unwrap();
assert_eq!(r["errors"], json!([]), "the file imports: {r}");
s.execute("comp.new", json!({"name": "EXR", "width": 8, "height": 4, "frameRate": 24, "duration": 1})).unwrap();
let layer = s.execute("layer.addItem", json!({"item": r["items"][0]})).unwrap()["layer"].clone();
// The picture is the colour layer (diffuse: orange).
assert!(near(px(&s), [1.0, 0.735, 0.0]), "{:?}", px(&s));
let ch = s.execute("layer.channels", json!({"layer": layer})).unwrap();
let names: Vec<&str> = ch["layers"].as_array().unwrap().iter().filter_map(|l| l["name"].as_str()).collect();
assert_eq!(names, ["depth", "diffuse", "spec"], "{ch}");
assert_eq!(ch["layers"][2]["rgba"], json!(["spec.R", "spec.G", "spec.B", ""]));
assert_eq!(ch["layers"][0]["rgba"], json!(["depth.Z", "depth.Z", "depth.Z", ""]), "one channel fills red, green and blue");
assert!(ch["channels"].as_array().unwrap().contains(&Value::from("depth.Z")));
// EXtractoR on the spec layer: blue.
s.execute("effect.apply", json!({"layers": [layer], "effect": "EXtractoR"})).unwrap();
for (param, v) in ["red", "green", "blue", "alpha"].iter().zip(["spec.R", "spec.G", "spec.B", ""]) {
s.execute("prop.set", json!({"layer": layer, "path": format!("effects/#1/{param}"), "value": v})).unwrap();
}
assert!(near(px(&s), [0.0, 0.0, 1.0]), "{:?}", px(&s));
// Depth in all three: grey at its value.
for param in ["red", "green", "blue"] {
s.execute("prop.set", json!({"layer": layer, "path": format!("effects/#1/{param}"), "value": "depth.Z"})).unwrap();
}
assert!(near(px(&s), [0.25, 0.25, 0.25]), "{:?}", px(&s));
// A layer that isn't OpenEXR has no channels.
let solid = s.execute("layer.newSolid", json!({"color": "#808080"})).unwrap()["layer"].clone();
assert_eq!(s.execute("layer.channels", json!({"layer": solid})).unwrap()["layers"], json!([]));
let _ = std::fs::remove_file(path);
}