zoomvtools 2.0.0

Video motion vector analysis utilities in pure Rust
Documentation
use std::num::NonZeroUsize;

use crate::util::Pixel;
use semisafe::option::unwrap as semisafe_opt_unwrap;
use semisafe::slice::get as semisafe_get;
use semisafe::slice::get_mut as semisafe_get_mut;

// PERF: Benchmarked to be faster than C SIMD implementation.
pub(super) fn average2<T: Pixel>(
    dest: &mut [T],
    src1: &[T],
    src2: &[T],
    pitch: NonZeroUsize,
    width: NonZeroUsize,
    height: NonZeroUsize,
) {
    let mut offset = 0;
    for _j in 0..height.get() {
        for i in 0..width.get() {
            match size_of::<T>() {
                1 => {
                    // Smaller types for faster 8-bit path
                    let a: u16 = semisafe_get(src1, offset + i).as_();
                    let b: u16 = semisafe_get(src2, offset + i).as_();
                    // SAFETY: (255+255+1)/2 = 255, so this will always fit in the target type
                    *semisafe_get_mut(dest, offset + i) =
                        semisafe_opt_unwrap(T::from((a + b + 1) / 2));
                }
                2 => {
                    let a: u32 = semisafe_get(src1, offset + i).as_();
                    let b: u32 = semisafe_get(src2, offset + i).as_();
                    *semisafe_get_mut(dest, offset + i) =
                        semisafe_opt_unwrap(T::from((a + b + 1) / 2));
                }
                _ => unreachable!(),
            }
        }
        offset += pitch.get();
    }
}