1use const_str::cstr;
2use strum_macros::EnumString;
3use vapoursynth4_rs::{
4 core::Core,
5 key,
6 map::{AppendMode, Value},
7 node::VideoNode,
8};
9
10use crate::errors::VapoursError;
11
12const FMTCONV_NAMESPACE: &str = "fmtc";
13
14#[derive(Clone, Copy, Debug, EnumString, Eq, PartialEq)]
16#[strum(ascii_case_insensitive, serialize_all = "snake_case")]
17pub enum DitherType {
18 Auto,
20
21 None,
23
24 Ordered,
26
27 Random,
29
30 ErrorDiffusion,
32
33 ErrorDiffusionFmtc,
36
37 #[strum(serialize = "sierra_2_4a")]
40 Sierra24a,
41
42 Stucki,
45
46 Atkinson,
49
50 Ostromoukhov,
53
54 Void,
57
58 Quasirandom,
61}
62
63pub trait VapoursCore {
65 fn depth(&self, clip: VideoNode, bit_depth: u32) -> Result<VideoNode, VapoursError>;
72}
73
74impl VapoursCore for Core {
75 fn depth(&self, clip: VideoNode, bit_depth: u32) -> Result<VideoNode, VapoursError> {
76 todo!("Needs configurable dither type, non-fmtc dithering, and probably more.");
77
78 let Some(fmtc_plugin) = self.get_plugin_by_id(cstr!(FMTCONV_NAMESPACE)) else {
79 return Err(VapoursError::DependencyNotFoundError(
80 FMTCONV_NAMESPACE.to_string(),
81 ));
82 };
83
84 let mut args = self.create_map();
85 args
86 .set(key!(c"clip"), Value::VideoNode(clip), AppendMode::Replace)
87 .map_err(|_| VapoursError::FramePropertyError("clip".to_string()))?;
88 args
89 .set(
90 key!(c"bitdepth"),
91 Value::Int(i64::from(bit_depth)),
92 AppendMode::Replace,
93 )
94 .map_err(|_| VapoursError::FramePropertyError("clip".to_string()))?;
95 let ret = fmtc_plugin.invoke(cstr!("bitdepth"), &args);
96 ret
97 .get_video_node(key!(c"clip"), 0)
98 .map_err(|_| VapoursError::FramePropertyError("clip".to_string()))
99 }
100}