Support all common formats
This commit is contained in:
parent
9236534dab
commit
cacc762810
|
@ -6,7 +6,7 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
faster = { git = "https://github.com/AdamNiederer/faster.git" }
|
#faster = { git = "https://github.com/AdamNiederer/faster.git" }
|
||||||
lazy_static = "1.3.0"
|
lazy_static = "1.3.0"
|
||||||
num = "0.2"
|
num = "0.2"
|
||||||
rand = "0.6"
|
rand = "0.6"
|
||||||
|
@ -17,6 +17,3 @@ vapoursynth-sys = "0.2"
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
debug = true
|
|
||||||
|
|
||||||
|
|
|
@ -111,14 +111,16 @@ make_filter_function! {
|
||||||
None => 10.0
|
None => 10.0
|
||||||
};
|
};
|
||||||
if let Property::Constant(format) = clip.info().format {
|
if let Property::Constant(format) = clip.info().format {
|
||||||
if format.bits_per_sample() == 32 && format.sample_type() == SampleType::Float {
|
if !(format.sample_type() == SampleType::Float && format.bits_per_sample() != 32) {
|
||||||
return Ok(Some(Box::new(Mask {
|
return Ok(Some(Box::new(Mask {
|
||||||
source: clip,
|
source: clip,
|
||||||
luma_scaling
|
luma_scaling
|
||||||
})));
|
})));
|
||||||
|
} else {
|
||||||
|
bail!("Half precision float input is not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bail!("Currently, only constant 32bit float input is supported" )
|
bail!("Variable format input is not supported")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
103
src/mask.rs
103
src/mask.rs
|
@ -1,14 +1,13 @@
|
||||||
use super::PLUGIN_NAME;
|
use super::PLUGIN_NAME;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use num::{NumCast, ToPrimitive};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use vapoursynth::api::API;
|
use std::ops::Shl;
|
||||||
use vapoursynth::core::CoreRef;
|
use vapoursynth::core::CoreRef;
|
||||||
use vapoursynth::format::ColorFamily;
|
use vapoursynth::format::ColorFamily;
|
||||||
use vapoursynth::frame::{FrameRef, FrameRefMut};
|
|
||||||
use vapoursynth::node::Node;
|
|
||||||
use vapoursynth::plugins::{Filter, FrameContext};
|
use vapoursynth::plugins::{Filter, FrameContext};
|
||||||
|
use vapoursynth::prelude::*;
|
||||||
use vapoursynth::video_info::{Property, VideoInfo};
|
use vapoursynth::video_info::{Property, VideoInfo};
|
||||||
use std::hint::unreachable_unchecked;
|
|
||||||
|
|
||||||
pub struct Mask<'core> {
|
pub struct Mask<'core> {
|
||||||
pub source: Node<'core>,
|
pub source: Node<'core>,
|
||||||
|
@ -17,10 +16,10 @@ pub struct Mask<'core> {
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref FLOAT_RANGE: Vec<f32> = {
|
static ref FLOAT_RANGE: Vec<f32> = {
|
||||||
[0f32; 1000]
|
[0f32; 256]
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, _f)| (i as f32) * 0.001)
|
.map(|(i, _f)| (i as f32) * (1.0 / 256.0))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -41,6 +40,51 @@ fn from_property<T: Debug + Clone + Copy + Eq + PartialEq>(prop: Property<T>) ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn filter_for_int<T>(
|
||||||
|
frame: &mut FrameRefMut,
|
||||||
|
src_frame: FrameRef,
|
||||||
|
depth: u8,
|
||||||
|
average: f32,
|
||||||
|
luma_scaling: f32,
|
||||||
|
) where
|
||||||
|
T: Component + NumCast + Clone + Shl<u8> + Debug,
|
||||||
|
<T as Shl<u8>>::Output: ToPrimitive,
|
||||||
|
{
|
||||||
|
let max = ((1 << depth) - 1) as f32;
|
||||||
|
let lut: Vec<T> = FLOAT_RANGE
|
||||||
|
.iter()
|
||||||
|
.map(|x| {
|
||||||
|
T::from(get_mask_value(*x, average, luma_scaling) * max).unwrap()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
for row in 0..frame.height(0) {
|
||||||
|
for (pixel, src_pixel) in frame
|
||||||
|
.plane_row_mut::<T>(0, row)
|
||||||
|
.iter_mut()
|
||||||
|
.zip(src_frame.plane_row::<T>(0, row).iter())
|
||||||
|
{
|
||||||
|
let i = <usize as NumCast>::from(src_pixel.clone()).unwrap() >> (depth - 8);
|
||||||
|
*pixel = lut[i].clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn filter_for_float(frame: &mut FrameRefMut, src_frame: FrameRef, average: f32, luma_scaling: f32) {
|
||||||
|
let lut: Vec<f32> = FLOAT_RANGE
|
||||||
|
.iter()
|
||||||
|
.map(|x| get_mask_value(*x, average, luma_scaling))
|
||||||
|
.collect();
|
||||||
|
for row in 0..frame.height(0) {
|
||||||
|
for (pixel, src_pixel) in frame
|
||||||
|
.plane_row_mut::<f32>(0, row)
|
||||||
|
.iter_mut()
|
||||||
|
.zip(src_frame.plane_row::<f32>(0, row).iter())
|
||||||
|
{
|
||||||
|
*pixel = lut[(src_pixel * 255f32) as usize];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'core> Filter<'core> for Mask<'core> {
|
impl<'core> Filter<'core> for Mask<'core> {
|
||||||
fn video_info(&self, _api: API, _core: CoreRef<'core>) -> Vec<VideoInfo<'core>> {
|
fn video_info(&self, _api: API, _core: CoreRef<'core>) -> Vec<VideoInfo<'core>> {
|
||||||
let info = self.source.info();
|
let info = self.source.info();
|
||||||
|
@ -99,24 +143,45 @@ impl<'core> Filter<'core> for Mask<'core> {
|
||||||
})?;
|
})?;
|
||||||
let average = match src_frame.props().get::<f64>("PlaneStatsAverage") {
|
let average = match src_frame.props().get::<f64>("PlaneStatsAverage") {
|
||||||
Ok(average) => average as f32,
|
Ok(average) => average as f32,
|
||||||
Err(_) => panic!(format!(
|
Err(_) => bail!(format!(
|
||||||
"{}: you need to run std.PlaneStats on the clip before calling this function.",
|
"{}: you need to run std.PlaneStats on the clip before calling this function.",
|
||||||
PLUGIN_NAME
|
PLUGIN_NAME
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let lut: Vec<f32> = FLOAT_RANGE
|
match from_property(self.source.info().format).sample_type() {
|
||||||
.iter()
|
SampleType::Integer => {
|
||||||
.map(|x| get_mask_value(*x, average, self.luma_scaling))
|
let depth = from_property(self.source.info().format).bits_per_sample();
|
||||||
.collect();
|
match depth {
|
||||||
|
_ if depth <= 8 => filter_for_int::<u8>(
|
||||||
for row in 0..frame.height(0) {
|
&mut frame,
|
||||||
for (pixel, src_pixel) in frame
|
src_frame,
|
||||||
.plane_row_mut::<f32>(0, row)
|
depth,
|
||||||
.iter_mut()
|
average,
|
||||||
.zip(src_frame.plane_row::<f32>(0, row).iter())
|
self.luma_scaling,
|
||||||
{
|
),
|
||||||
*pixel = lut[(src_pixel * 1000f32) as usize];
|
_ if 8 < depth && depth <= 16 => filter_for_int::<u16>(
|
||||||
|
&mut frame,
|
||||||
|
src_frame,
|
||||||
|
depth,
|
||||||
|
average,
|
||||||
|
self.luma_scaling,
|
||||||
|
),
|
||||||
|
_ if 16 < depth && depth <= 32 => filter_for_int::<u32>(
|
||||||
|
&mut frame,
|
||||||
|
src_frame,
|
||||||
|
depth,
|
||||||
|
average,
|
||||||
|
self.luma_scaling,
|
||||||
|
),
|
||||||
|
_ => bail!(format!(
|
||||||
|
"{}: input depth {} not supported",
|
||||||
|
PLUGIN_NAME, depth
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SampleType::Float => {
|
||||||
|
filter_for_float(&mut frame, src_frame, average, self.luma_scaling);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(frame.into())
|
Ok(frame.into())
|
||||||
|
|
Loading…
Reference in New Issue
Block a user