zoomvtools 1.1.0

Video motion vector analysis utilities in pure Rust
Documentation
use std::num::{NonZeroU8, NonZeroUsize};

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

pub(super) fn refine_horizontal_bilinear<T: Pixel>(
    dest: &mut [T],
    src: &[T],
    pitch: NonZeroUsize,
    width: NonZeroUsize,
    height: NonZeroUsize,
    _bits_per_sample: NonZeroU8,
) {
    let mut offset = 0;
    for _j in 0..height.get() {
        let src_row = semisafe_get(semisafe_get(src, offset..), ..width.get());
        let dest_row = semisafe_get_mut(semisafe_get_mut(dest, offset..), ..width.get());

        for i in 0..width.get() - 1 {
            let a: u32 = semisafe_get(src_row, i).as_();
            let b: u32 = semisafe_get(src_row, i + 1).as_();
            *semisafe_get_mut(dest_row, i) = T::from_u32_or_max_value((a + b + 1) / 2);
        }
        // last column
        *semisafe_get_mut(dest_row, width.get() - 1) = *semisafe_get(src_row, width.get() - 1);

        offset += pitch.get();
    }
}

pub(super) fn refine_vertical_bilinear<T: Pixel>(
    dest: &mut [T],
    src: &[T],
    pitch: NonZeroUsize,
    width: NonZeroUsize,
    height: NonZeroUsize,
    _bits_per_sample: NonZeroU8,
) {
    let mut offset = 0;
    for _j in 0..height.get() - 1 {
        for i in 0..width.get() {
            let a: u32 = semisafe_get(src, offset + i).as_();
            let b: u32 = semisafe_get(src, offset + i + pitch.get()).as_();
            *semisafe_get_mut(dest, offset + i) = T::from_u32_or_max_value((a + b + 1) / 2);
        }
        offset += pitch.get();
    }

    // last row
    let dest_row = semisafe_get_mut(semisafe_get_mut(dest, offset..), ..width.get());
    let src_row = semisafe_get(semisafe_get(src, offset..), ..width.get());
    dest_row.copy_from_slice(src_row);
}

pub(super) fn refine_diagonal_bilinear<T: Pixel>(
    dest: &mut [T],
    src: &[T],
    pitch: NonZeroUsize,
    width: NonZeroUsize,
    height: NonZeroUsize,
    _bits_per_sample: NonZeroU8,
) {
    let mut offset = 0;

    for _j in 0..height.get() {
        for i in 0..width.get() {
            let a: u32 = semisafe_get(src, offset + i).as_();
            let b: u32 = semisafe_get(src, offset + i + 1).as_();
            let c: u32 = semisafe_get(src, offset + i + pitch.get()).as_();
            let d: u32 = semisafe_get(src, offset + i + pitch.get() + 1).as_();

            *semisafe_get_mut(dest, offset + i) = T::from_u32_or_max_value((a + b + c + d + 2) / 4);
        }
        // last column
        let a: u32 = semisafe_get(src, offset + width.get() - 1).as_();
        let b: u32 = semisafe_get(src, offset + width.get() - 1 + pitch.get()).as_();
        *semisafe_get_mut(dest, offset + width.get() - 1) =
            T::from_u32_or_max_value((a + b + 1) / 2);

        offset += pitch.get();
    }

    // last row
    for i in 0..width.get() - 1 {
        let a: u32 = semisafe_get(src, offset + i).as_();
        let b: u32 = semisafe_get(src, offset + i + 1).as_();
        *semisafe_get_mut(dest, offset + i) = T::from_u32_or_max_value((a + b + 1) / 2);
    }
    // last pixel
    *semisafe_get_mut(dest, offset + width.get() - 1) =
        *semisafe_get(src, offset + width.get() - 1);
}