#![allow(unsafe_code)]
use std::path::Path;
use crate::FilterError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AnalyzeOptions {
pub shakiness: u8,
pub accuracy: u8,
pub stepsize: u8,
}
impl Default for AnalyzeOptions {
fn default() -> Self {
Self {
shakiness: 5,
accuracy: 15,
stepsize: 6,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Interpolation {
Bilinear,
Bicubic,
}
#[derive(Debug, Clone, PartialEq)]
pub struct StabilizeOptions {
pub smoothing: u16,
pub crop_black: bool,
pub zoom: f32,
pub optzoom: u8,
pub interpol: Interpolation,
}
impl Default for StabilizeOptions {
fn default() -> Self {
Self {
smoothing: 10,
crop_black: true,
zoom: 0.0,
optzoom: 0,
interpol: Interpolation::Bilinear,
}
}
}
impl StabilizeOptions {
#[must_use]
pub fn zoom(mut self, z: f32) -> Self {
self.zoom = z;
self
}
#[must_use]
pub fn optzoom(mut self, mode: u8) -> Self {
self.optzoom = mode.clamp(0, 2);
self
}
#[must_use]
pub fn interpol(mut self, i: Interpolation) -> Self {
self.interpol = i;
self
}
}
pub struct Stabilizer;
impl Stabilizer {
pub fn analyze(
input: &Path,
output_trf: &Path,
opts: &AnalyzeOptions,
) -> Result<(), FilterError> {
unsafe { super::effects_inner::analyze_vidstab_unsafe(input, output_trf, opts) }
}
pub fn transform(
input: &Path,
trf_path: &Path,
output: &Path,
opts: &StabilizeOptions,
) -> Result<(), FilterError> {
unsafe { super::effects_inner::transform_vidstab_unsafe(input, trf_path, output, opts) }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn analyze_options_default_should_have_expected_values() {
let opts = AnalyzeOptions::default();
assert_eq!(opts.shakiness, 5);
assert_eq!(opts.accuracy, 15);
assert_eq!(opts.stepsize, 6);
}
#[test]
fn stabilize_options_default_should_have_expected_values() {
let opts = StabilizeOptions::default();
assert_eq!(opts.smoothing, 10);
assert!(opts.crop_black);
assert!((opts.zoom - 0.0_f32).abs() < f32::EPSILON);
assert_eq!(opts.optzoom, 0);
assert_eq!(opts.interpol, Interpolation::Bilinear);
}
#[test]
fn zoom_builder_should_set_zoom_field() {
let opts = StabilizeOptions::default().zoom(1.5);
assert!((opts.zoom - 1.5_f32).abs() < f32::EPSILON);
}
#[test]
fn optzoom_builder_should_set_optzoom_field() {
let opts = StabilizeOptions::default().optzoom(1);
assert_eq!(opts.optzoom, 1);
}
#[test]
fn optzoom_builder_should_clamp_above_maximum_to_two() {
let opts = StabilizeOptions::default().optzoom(5);
assert_eq!(opts.optzoom, 2);
}
#[test]
fn interpol_builder_should_set_interpol_field() {
let opts = StabilizeOptions::default().interpol(Interpolation::Bicubic);
assert_eq!(opts.interpol, Interpolation::Bicubic);
}
}