use std::io::Read;
use ::BayerResult;
use bayer::*;
pub struct BorderReplicate8(usize, usize, usize);
pub struct BorderReplicate16BE(usize, usize, usize);
pub struct BorderReplicate16LE(usize, usize, usize);
macro_rules! fill_row {
($dst:ident, $x1:expr, $x2:expr, $x3:expr) => {{
let mut i;
let r0 = $dst[$x1 + 0];
let g0 = $dst[$x1 + 1];
i = 0;
if $x1 % 2 == 1 {
$dst[0] = g0;
i = 1;
}
while i < $x1 {
$dst[i + 0] = r0;
$dst[i + 1] = g0;
i = i + 2;
}
let r0 = $dst[$x2 - 2];
let g0 = $dst[$x2 - 1];
i = $x2;
while i + 1 < $x3 {
$dst[i + 0] = r0;
$dst[i + 1] = g0;
i = i + 2;
}
if i == $x3 - 1 {
$dst[i] = r0;
}
}}
}
impl BorderReplicate8 {
pub fn new(width: usize, padding: usize) -> Self {
let x1 = padding;
let x2 = x1.checked_add(width).expect("overflow");
let x3 = x2.checked_add(padding).expect("overflow");
assert!(width >= 2);
BorderReplicate8(x1, x2, x3)
}
}
impl BayerRead8 for BorderReplicate8 {
fn read_line(&self, r: &mut Read, dst: &mut [u8])
-> BayerResult<()> {
let BorderReplicate8(x1, x2, x3) = *self;
read_exact_u8(r, &mut dst[x1..x2])?;
fill_row!(dst, x1, x2, x3);
Ok(())
}
}
impl BorderReplicate16BE {
pub fn new(width: usize, padding: usize) -> Self {
let x1 = padding;
let x2 = x1.checked_add(width).expect("overflow");
let x3 = x2.checked_add(padding).expect("overflow");
assert!(width >= 2);
BorderReplicate16BE(x1, x2, x3)
}
}
impl BayerRead16 for BorderReplicate16BE {
fn read_line(&self, r: &mut Read, dst: &mut [u16])
-> BayerResult<()> {
let BorderReplicate16BE(x1, x2, x3) = *self;
read_exact_u16be(r, &mut dst[x1..x2])?;
fill_row!(dst, x1, x2, x3);
Ok(())
}
}
impl BorderReplicate16LE {
pub fn new(width: usize, padding: usize) -> Self {
let x1 = padding;
let x2 = x1.checked_add(width).expect("overflow");
let x3 = x2.checked_add(padding).expect("overflow");
assert!(width >= 2);
BorderReplicate16LE(x1, x2, x3)
}
}
impl BayerRead16 for BorderReplicate16LE {
fn read_line(&self, r: &mut Read, dst: &mut [u16])
-> BayerResult<()> {
let BorderReplicate16LE(x1, x2, x3) = *self;
read_exact_u16le(r, &mut dst[x1..x2])?;
fill_row!(dst, x1, x2, x3);
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::io::Cursor;
use bayer::BayerRead8;
use super::BorderReplicate8;
#[test]
fn test_replicate_even() {
let src = [
1,2, 3,4, 5,6 ];
let expected = [
1,2, 1,2,
1,2, 3,4, 5,6,
5,6, 5,6 ];
let rdr = BorderReplicate8::new(6, 4);
let mut buf = [0u8; 4 + 6 + 4];
let res = rdr.read_line(&mut Cursor::new(&src[..]), &mut buf);
assert!(res.is_ok());
assert_eq!(&buf[..], &expected[..]);
}
#[test]
fn test_replicate_odd() {
let src = [
1,2, 3,4, 5, ];
let expected = [
2, 1,2,
1,2, 3,4, 5,
4, 5,4 ];
let rdr = BorderReplicate8::new(5, 3);
let mut buf = [0u8; 3 + 5 + 3];
let res = rdr.read_line(&mut Cursor::new(&src[..]), &mut buf);
assert!(res.is_ok());
assert_eq!(&buf[..], &expected[..]);
}
}