#[derive(Copy, Clone)]
pub enum PadMethod {
Constant,
Replicate
}
pub fn pad<T: Copy + Default>(
pixels: &[T], width: usize, height: usize, pad_x: usize, pad_y: usize, method: PadMethod
) -> Vec<T> {
match method {
PadMethod::Constant => no_fill(pixels, width, height, pad_x, pad_y),
PadMethod::Replicate => replicate(pixels, width, height, pad_x, pad_y)
}
}
fn no_fill<T: Copy + Default>(
pixels: &[T], width: usize, height: usize, pad_x: usize, pad_y: usize
) -> Vec<T> {
let padded_w = width + pad_x * 2;
let padded_h = height + pad_y * 2;
let mut out_pixels = vec![T::default(); padded_h * padded_w];
let start = pad_x;
let end = padded_w - pad_x;
for (out, in_pix) in out_pixels
.chunks_exact_mut(padded_w)
.skip(pad_y)
.take(height)
.zip(pixels.chunks_exact(width))
{
out[start..end].copy_from_slice(in_pix);
}
out_pixels
}
fn replicate<T: Copy + Default>(
pixels: &[T], width: usize, height: usize, pad_x: usize, pad_y: usize
) -> Vec<T> {
let padded_w = width + pad_x * 2;
let padded_h = height + pad_y * 2;
let mut out_pixels = vec![T::default(); padded_h * padded_w];
let start = pad_x;
let end = padded_w - pad_x;
let first_row = &pixels[0..width];
for out in out_pixels.chunks_exact_mut(padded_w).take(pad_y) {
out[0..start].fill(first_row[0]);
out[start..end].copy_from_slice(first_row);
out[end..].fill(*first_row.last().unwrap_or(&T::default()));
}
for (out, in_pix) in out_pixels
.chunks_exact_mut(padded_w)
.skip(pad_y)
.take(height)
.zip(pixels.chunks_exact(width))
{
out[0..start].fill(in_pix[0]);
out[start..end].copy_from_slice(in_pix);
out[end..].fill(*in_pix.last().unwrap_or(&T::default()));
}
let last_row = pixels.rchunks_exact(width).next().unwrap();
for out in out_pixels.rchunks_exact_mut(padded_w).take(pad_y) {
out[0..start].fill(last_row[0]);
out[start..end].copy_from_slice(last_row);
out[end..].fill(*last_row.last().unwrap_or(&T::default()));
}
out_pixels
}
#[cfg(feature = "benchmarks")]
#[cfg(test)]
mod benchmarks {
extern crate test;
use crate::pad::{pad, PadMethod};
#[bench]
fn bench_pad_replicate(b: &mut test::Bencher) {
let width = 800;
let height = 800;
let pixels = vec![0_u8; width * height];
let new_width = 960;
let new_height = 1000;
b.iter(|| {
pad(
&pixels,
width,
height,
new_width,
new_height,
PadMethod::Replicate
)
});
}
#[bench]
fn bench_pad_constant(b: &mut test::Bencher) {
let width = 800;
let height = 800;
let pixels = vec![0_u8; width * height];
let new_width = 960;
let new_height = 1000;
b.iter(|| {
pad(
&pixels,
width,
height,
new_width,
new_height,
PadMethod::Constant
)
});
}
}