mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-14 11:17:12 -04:00
Import: test that an animated GIF imported from disk plays (#651)
Animated GIFs came in as one still frame in 0.7.0; bfbdadd3 (after that
release) probes them as movies. This end-to-end test imports a GIF file
through the wired session into a comp and checks the layer shows each of
its frames at its time, the path the viewer and exports share.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
This commit is contained in:
3 files changed
+34
No files matched your search
Generated
+1
@@ -1350,6 +1350,7 @@ dependencies = [
|
||||
"effectcraft-svg",
|
||||
"effectcraft-time",
|
||||
"exr",
|
||||
"gif",
|
||||
"image",
|
||||
"rayon",
|
||||
"serde_json",
|
||||
|
||||
@@ -31,5 +31,6 @@ effectcraft-raster = { workspace = true }
|
||||
effectcraft-time = { workspace = true }
|
||||
effectcraft-interchange = { workspace = true }
|
||||
image = { workspace = true }
|
||||
gif = { workspace = true }
|
||||
exr = { workspace = true }
|
||||
rayon = { workspace = true }
|
||||
@@ -257,6 +257,38 @@ mod tests {
|
||||
assert!(red * 20 > img.data.len(), "red cube pixels: {red} of {}", img.data.len());
|
||||
}
|
||||
|
||||
/// #651: an animated GIF imported from disk plays: the layer shows each frame at its time,
|
||||
/// in the viewer's renders and in exports alike.
|
||||
#[test]
|
||||
fn an_imported_animated_gif_plays() {
|
||||
let dir = std::env::temp_dir().join(format!("ec-gif-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let path = dir.join("anim.gif");
|
||||
let mut bytes = Vec::new();
|
||||
{
|
||||
let mut enc = gif::Encoder::new(&mut bytes, 4, 4, &[]).unwrap();
|
||||
for rgb in [[255u8, 0, 0], [0, 255, 0], [0, 0, 255]] {
|
||||
let mut f = gif::Frame::from_rgb(4, 4, &rgb.repeat(16));
|
||||
f.delay = 10;
|
||||
enc.write_frame(&f).unwrap();
|
||||
}
|
||||
}
|
||||
std::fs::write(&path, bytes).unwrap();
|
||||
let mut s = super::session();
|
||||
s.execute("comp.new", json!({"name": "G", "width": 4, "height": 4, "frameRate": 30, "duration": 1})).unwrap();
|
||||
s.execute("file.import", json!({"paths": [path.to_string_lossy()], "addToComp": true})).unwrap();
|
||||
let cid = s.active_comp_id().unwrap();
|
||||
let rgb = |t: f64| {
|
||||
let img = s.render(cid, effectcraft_time::Tick::from_seconds_f64(t), effectcraft_engine::render::RenderOpts::default());
|
||||
let p = img.data[5];
|
||||
[p[0].round(), p[1].round(), p[2].round()]
|
||||
};
|
||||
assert_eq!(rgb(0.05), [1.0, 0.0, 0.0]);
|
||||
assert_eq!(rgb(0.15), [0.0, 1.0, 0.0]);
|
||||
assert_eq!(rgb(0.25), [0.0, 0.0, 1.0]);
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
/// The web app's path: outputs go to a sink (downloads), never to the file system.
|
||||
#[test]
|
||||
fn render_queue_exports_to_a_sink() {
|
||||
|
||||
Reference in new issue
Block a user