mirror of
https://github.com/storytold/filmcraft.git
synced 2026-10-14 19:26:59 -04:00
Adjustment layers: a Transform replaces the picture below instead of drawing over it (fixes #1524)
This commit is contained in:
1 parent
71438c627b
commit
4ad860cb69
2 files changed
+36
-7
No files matched your search
@@ -156,6 +156,26 @@ fn motion_and_masks_restrict_the_region() {
|
||||
assert!(near(img.get(280, 90), [1.0, 0.0, 0.0], 1e-4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_transform_replaces_the_picture_below() {
|
||||
// Premiere: Transform on an adjustment layer moves the composite below; it is not a copy
|
||||
// drawn over the untouched original (#1524).
|
||||
let mut s = scene(2);
|
||||
let red = matte(&mut s.p, &mut s.map, [1.0, 0.0, 0.0, 1.0]);
|
||||
place(&mut s.p, s.seq, 0, red);
|
||||
let adj = adjustment(&mut s.p, s.seq, 1);
|
||||
fx(&mut s, adj, "transform");
|
||||
let tf = clip(&mut s, adj).effects.iter_mut().find(|e| e.effect == "transform").unwrap();
|
||||
tf.params.get_mut("scale_height").unwrap().value = ParamValue::Float(50.0);
|
||||
let img = render(&s);
|
||||
assert!(near(img.get(160, 90), [1.0, 0.0, 0.0], 1e-4), "{:?}", img.get(160, 90));
|
||||
assert_eq!(img.get(10, 10), [0.0; 4], "the original is gone outside the scaled picture");
|
||||
// at 50 % opacity: half the original, half the (empty) transformed picture
|
||||
clip(&mut s, adj).effect_mut("opacity").unwrap().params.get_mut("opacity").unwrap().value = ParamValue::Float(50.0);
|
||||
let c = render(&s).get(10, 10);
|
||||
assert!((c[0] - 0.5).abs() < 1e-3 && (c[3] - 0.5).abs() < 1e-3, "{c:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_adjustment_layers_stay_in_their_sequence() {
|
||||
let mut s = scene(2);
|
||||
|
||||
@@ -235,18 +235,27 @@ pub(crate) fn render_seq_tracks(project: &Project, seq: &Sequence, t: Tick, opts
|
||||
mask::apply_effect(&mut adjusted, e, &cx);
|
||||
}
|
||||
let (op, bl) = opacity_blend(item, mt);
|
||||
// Adjustment layer opacity (and opacity masks, in sequence pixels) mix adjusted over original.
|
||||
let mut out = canvas.snapshot();
|
||||
let mut adj = adjusted;
|
||||
adj.scale_alpha(op);
|
||||
mask::apply_opacity_masks(&mut adj, item, mt, opts.scale);
|
||||
// Adjustment layer opacity (and opacity masks, in sequence pixels) weigh adjusted against original.
|
||||
let mut weight = Image::filled(w, h, [op; 4]);
|
||||
mask::apply_opacity_masks(&mut weight, item, mt, opts.scale);
|
||||
// Motion moves / scales the adjustment layer's frame: it only applies inside it.
|
||||
if let Some(region) = adjustment_region(seq, item, project, mt, opts.scale, w, h) {
|
||||
let cov: Vec<f32> = region.px.as_chunks::<4>().0.iter().map(|p| p[3]).collect();
|
||||
mask::scale_by(&mut weight, &cov);
|
||||
}
|
||||
let cov: Vec<f32> = weight.px.as_chunks::<4>().0.iter().map(|p| p[3]).collect();
|
||||
let mut out = canvas.snapshot();
|
||||
let mut adj = adjusted;
|
||||
if bl == Blend::Normal {
|
||||
// The adjusted picture replaces the original instead of being drawn over it: what
|
||||
// Transform or Basic 3D leave empty shows nothing of the untransformed picture (#1524).
|
||||
mask::mix(&mut adj, &out, &cov);
|
||||
canvas.set(adj);
|
||||
} else {
|
||||
mask::scale_by(&mut adj, &cov);
|
||||
blend::composite(&mut out, &adj, 1.0, bl);
|
||||
canvas.set(out);
|
||||
}
|
||||
blend::composite(&mut out, &adj, 1.0, bl);
|
||||
canvas.set(out);
|
||||
continue;
|
||||
}
|
||||
match item_layer_ex(project, seq, item, t, opts, sources, &tc, true) {
|
||||
|
||||
Reference in new issue
Block a user