use std::cmp;
use image:: {
SubImage,
GenericImage,
};
use buffer::Pixel;
pub use self::sample::FilterType;
pub use self::sample::FilterType:: {
Triangle,
Nearest,
CatmullRom,
Gaussian,
Lanczos3
};
pub use self::affine:: {
rotate90,
rotate180,
rotate270,
flip_horizontal,
flip_vertical,
};
pub use self::sample:: {
filter3x3,
resize,
thumbnail,
blur,
unsharpen,
};
pub use self::colorops:: {
grayscale,
invert,
contrast,
brighten,
huerotate,
ColorMap,
BiLevel,
dither,
index_colors,
};
mod affine;
pub mod colorops;
mod sample;
pub fn crop<I: GenericImage + 'static>(image: &mut I, x: u32, y: u32,
width: u32, height: u32)
-> SubImage<I>
where I::Pixel: 'static,
<I::Pixel as Pixel>::Subpixel: 'static {
let (iwidth, iheight) = image.dimensions();
let x = cmp::min(x, iwidth);
let y = cmp::min(y, iheight);
let height = cmp::min(height, iheight - y);
let width = cmp::min(width, iwidth - x);
SubImage::new(image, x, y, width, height)
}
pub fn overlay<I: GenericImage>(bottom: &mut I, top: &I, x: u32, y:u32) {
let (top_width, top_height) = top.dimensions();
let (bottom_width, bottom_height) = bottom.dimensions();
let range_width = if x + top_width > bottom_width {
bottom_width - x
} else {
top_width
};
let range_height = if y + top_height > bottom_height {
bottom_height - y
} else {
top_height
};
for top_y in 0..range_height {
for top_x in 0..range_width {
let p = top.get_pixel(top_x, top_y);
let mut bottom_pixel = bottom.get_pixel(x + top_x, y + top_y);
bottom_pixel.blend(&p);
bottom.put_pixel(x + top_x, y + top_y, bottom_pixel);
}
}
}
pub fn replace<I: GenericImage>(bottom: &mut I, top: &I, x: u32, y:u32) {
let (top_width, top_height) = top.dimensions();
let (bottom_width, bottom_height) = bottom.dimensions();
let range_width = if x + top_width > bottom_width {
bottom_width - x
} else {
top_width
};
let range_height = if y + top_height > bottom_height {
bottom_height - y
} else {
top_height
};
for top_y in 0..range_height {
for top_x in 0..range_width {
let p = top.get_pixel(top_x, top_y);
bottom.put_pixel(x + top_x, y + top_y, p);
}
}
}
#[cfg(test)]
mod tests {
use buffer::ImageBuffer;
use color::{Rgb};
use super::overlay;
#[test]
fn test_image_in_image() {
let mut target = ImageBuffer::new(32, 32);
let source = ImageBuffer::from_pixel(16, 16, Rgb([255u8, 0, 0]));
overlay(&mut target, &source, 0, 0);
assert!(*target.get_pixel(0, 0) == Rgb([255u8, 0, 0]));
assert!(*target.get_pixel(15, 0) == Rgb([255u8, 0, 0]));
assert!(*target.get_pixel(16, 0) == Rgb([0u8, 0, 0]));
assert!(*target.get_pixel(0, 15) == Rgb([255u8, 0, 0]));
assert!(*target.get_pixel(0, 16) == Rgb([0u8, 0, 0]));
}
#[test]
fn test_image_in_image_outside_of_bounds() {
let mut target = ImageBuffer::new(32, 32);
let source = ImageBuffer::from_pixel(32, 32, Rgb([255u8, 0, 0]));
overlay(&mut target, &source, 1, 1);
assert!(*target.get_pixel(0, 0) == Rgb([0, 0, 0]));
assert!(*target.get_pixel(1, 1) == Rgb([255u8, 0, 0]));
assert!(*target.get_pixel(31, 31) == Rgb([255u8, 0, 0]));
}
}