mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-12 13:32:04 +00:00
fix(engine): draw vector footage thumbnails at the thumbnail's size
This commit is contained in:
@@ -96,7 +96,11 @@ impl Session {
|
||||
effectcraft_project::ItemKind::Footage(f) if f.has_video => {
|
||||
let f = f.clone();
|
||||
Some(Box::new(move || {
|
||||
let img = effectcraft_render::cineon_frame(footage.frame(item, &f, Tick(0))?, &f);
|
||||
// Vector footage is drawn at the thumbnail's size: its declared size can be a
|
||||
// 16384² canvas, gigabytes of pixels to point-sample down to a few dozen.
|
||||
let scale = (max_side.max(1) as f64 / f.width.max(f.height).max(1) as f64).min(1.0);
|
||||
let src = footage.vector_frame(item, &f, scale).or_else(|| footage.frame(item, &f, Tick(0)))?;
|
||||
let img = effectcraft_render::cineon_frame(src, &f);
|
||||
// Point-sample down to at most `max_side` on the long side.
|
||||
let step = (img.width.max(img.height) as f32 / max_side.max(1) as f32).ceil().max(1.0) as u32;
|
||||
let (w, h) = (img.width.div_ceil(step), img.height.div_ceil(step));
|
||||
|
||||
@@ -383,3 +383,31 @@ fn psd_with_damaged_layer_section_imports_the_flattened_image() {
|
||||
let ItemKind::Footage(f) = &s.project.item(item).unwrap().kind else { panic!() };
|
||||
assert!(f.layer.is_none(), "the merged image, not a Photoshop layer");
|
||||
}
|
||||
|
||||
/// A vector footage thumbnail is drawn at the thumbnail's size, never at its declared size.
|
||||
#[test]
|
||||
fn vector_footage_thumbnails_are_drawn_at_thumbnail_size() {
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use effectcraft_project::{Footage, ItemId};
|
||||
use effectcraft_raster::Image;
|
||||
use effectcraft_time::Tick;
|
||||
|
||||
struct Vector(Mutex<Vec<f64>>);
|
||||
impl crate::render::FootageSource for Vector {
|
||||
fn frame(&self, _: ItemId, _: &Footage, _: Tick) -> Option<Arc<Image>> {
|
||||
panic!("the full-size frame was decoded");
|
||||
}
|
||||
fn vector_frame(&self, _: ItemId, f: &Footage, scale: f64) -> Option<Arc<Image>> {
|
||||
self.0.lock().unwrap().push(scale);
|
||||
Some(Arc::new(Image::new((f.width as f64 * scale).ceil() as u32, (f.height as f64 * scale).ceil() as u32)))
|
||||
}
|
||||
}
|
||||
let source = Arc::new(Vector(Mutex::new(vec![])));
|
||||
let mut s = Session { footage: source.clone(), ..Default::default() };
|
||||
let f = Footage { path: "/m/huge.svg".into(), codec: "SVG".into(), width: 16_000, height: 8_000, has_video: true, ..Default::default() };
|
||||
let item = std::sync::Arc::make_mut(&mut s.project).add_item("huge.svg", effectcraft_color::Label::Sandstone, None, ItemKind::Footage(f));
|
||||
let (w, h, _) = (s.thumbnail_job(item, Tick::ZERO, 64).unwrap())().unwrap();
|
||||
assert_eq!((w, h), (64, 32));
|
||||
assert_eq!(*source.0.lock().unwrap(), [64.0 / 16_000.0]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user