zoomvtools 2.0.0

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

use crate::util::Pixel;
use semisafe::option::unwrap as semisafe_opt_unwrap;

pub unsafe fn limit_changes<T: Pixel>(
    dest: *mut u8,
    dest_stride_bytes: NonZeroUsize,
    src: *const u8,
    src_stride_bytes: NonZeroUsize,
    width: NonZeroUsize,
    height: NonZeroUsize,
    limit: u16,
) {
    let dest: *mut T = dest.cast();
    let src: *const T = src.cast();
    let limit = semisafe_opt_unwrap(T::from(limit));
    // SAFETY: size of T is non-zero and byte stride must be divisible by it
    let dest_stride_pixels =
        unsafe { NonZeroUsize::new_unchecked(dest_stride_bytes.get() / size_of::<T>()) };
    // SAFETY: size of T is non-zero and byte stride must be divisible by it
    let src_stride_pixels =
        unsafe { NonZeroUsize::new_unchecked(src_stride_bytes.get() / size_of::<T>()) };

    for h in 0..height.get() {
        let dest_row_offset = h * dest_stride_pixels.get();
        let src_row_offset = h * src_stride_pixels.get();
        for i in 0..width.get() {
            let dest = dest.add(dest_row_offset + i);
            let src = src.add(src_row_offset + i);
            *dest = min(
                max(*dest, (*src).saturating_sub(limit)),
                (*src).saturating_add(limit),
            );
        }
    }
}