use num_iter;
use std::io;
use std::io::Write;
use std::path::Path;
use std::u32;
#[cfg(feature = "bmp")]
use bmp;
#[cfg(feature = "gif_codec")]
use gif;
#[cfg(feature = "ico")]
use ico;
#[cfg(feature = "jpeg")]
use jpeg;
#[cfg(feature = "png_codec")]
use png;
#[cfg(feature = "pnm")]
use pnm;
use buffer::{
BgrImage, BgraImage, ConvertBuffer, GrayAlphaImage, GrayImage, ImageBuffer, Pixel, RgbImage,
RgbaImage,
};
use color;
use flat::FlatSamples;
use image;
use image::{
GenericImage, GenericImageView, ImageDecoder, ImageFormat, ImageOutputFormat, ImageResult,
};
use io::free_functions;
use imageops;
#[derive(Clone)]
pub enum DynamicImage {
ImageLuma8(GrayImage),
ImageLumaA8(GrayAlphaImage),
ImageRgb8(RgbImage),
ImageRgba8(RgbaImage),
ImageBgr8(BgrImage),
ImageBgra8(BgraImage),
}
macro_rules! dynamic_map(
($dynimage: expr, ref $image: ident => $action: expr) => (
match $dynimage {
DynamicImage::ImageLuma8(ref $image) => DynamicImage::ImageLuma8($action),
DynamicImage::ImageLumaA8(ref $image) => DynamicImage::ImageLumaA8($action),
DynamicImage::ImageRgb8(ref $image) => DynamicImage::ImageRgb8($action),
DynamicImage::ImageRgba8(ref $image) => DynamicImage::ImageRgba8($action),
DynamicImage::ImageBgr8(ref $image) => DynamicImage::ImageBgr8($action),
DynamicImage::ImageBgra8(ref $image) => DynamicImage::ImageBgra8($action),
}
);
($dynimage: expr, ref mut $image: ident => $action: expr) => (
match $dynimage {
DynamicImage::ImageLuma8(ref mut $image) => DynamicImage::ImageLuma8($action),
DynamicImage::ImageLumaA8(ref mut $image) => DynamicImage::ImageLumaA8($action),
DynamicImage::ImageRgb8(ref mut $image) => DynamicImage::ImageRgb8($action),
DynamicImage::ImageRgba8(ref mut $image) => DynamicImage::ImageRgba8($action),
DynamicImage::ImageBgr8(ref mut $image) => DynamicImage::ImageBgr8($action),
DynamicImage::ImageBgra8(ref mut $image) => DynamicImage::ImageBgra8($action),
}
);
($dynimage: expr, ref $image: ident -> $action: expr) => (
match $dynimage {
DynamicImage::ImageLuma8(ref $image) => $action,
DynamicImage::ImageLumaA8(ref $image) => $action,
DynamicImage::ImageRgb8(ref $image) => $action,
DynamicImage::ImageRgba8(ref $image) => $action,
DynamicImage::ImageBgr8(ref $image) => $action,
DynamicImage::ImageBgra8(ref $image) => $action,
}
);
($dynimage: expr, ref mut $image: ident -> $action: expr) => (
match $dynimage {
DynamicImage::ImageLuma8(ref mut $image) => $action,
DynamicImage::ImageLumaA8(ref mut $image) => $action,
DynamicImage::ImageRgb8(ref mut $image) => $action,
DynamicImage::ImageRgba8(ref mut $image) => $action,
DynamicImage::ImageBgr8(ref mut $image) => $action,
DynamicImage::ImageBgra8(ref mut $image) => $action,
}
);
);
impl DynamicImage {
pub fn new_luma8(w: u32, h: u32) -> DynamicImage {
DynamicImage::ImageLuma8(ImageBuffer::new(w, h))
}
pub fn new_luma_a8(w: u32, h: u32) -> DynamicImage {
DynamicImage::ImageLumaA8(ImageBuffer::new(w, h))
}
pub fn new_rgb8(w: u32, h: u32) -> DynamicImage {
DynamicImage::ImageRgb8(ImageBuffer::new(w, h))
}
pub fn new_rgba8(w: u32, h: u32) -> DynamicImage {
DynamicImage::ImageRgba8(ImageBuffer::new(w, h))
}
pub fn new_bgra8(w: u32, h: u32) -> DynamicImage {
DynamicImage::ImageBgra8(ImageBuffer::new(w, h))
}
pub fn new_bgr8(w: u32, h: u32) -> DynamicImage {
DynamicImage::ImageBgr8(ImageBuffer::new(w, h))
}
pub fn from_decoder<'a>(decoder: impl ImageDecoder<'a>)
-> ImageResult<Self>
{
decoder_to_image(decoder)
}
pub fn to_rgb(&self) -> RgbImage {
dynamic_map!(*self, ref p -> {
p.convert()
})
}
pub fn to_rgba(&self) -> RgbaImage {
dynamic_map!(*self, ref p -> {
p.convert()
})
}
pub fn to_bgr(&self) -> BgrImage {
dynamic_map!(*self, ref p -> {
p.convert()
})
}
pub fn to_bgra(&self) -> BgraImage {
dynamic_map!(*self, ref p -> {
p.convert()
})
}
pub fn to_luma(&self) -> GrayImage {
dynamic_map!(*self, ref p -> {
p.convert()
})
}
pub fn to_luma_alpha(&self) -> GrayAlphaImage {
dynamic_map!(*self, ref p -> {
p.convert()
})
}
pub fn into_rgb(self) -> RgbImage {
match self {
DynamicImage::ImageRgb8(x) => x,
x => x.to_rgb(),
}
}
pub fn into_rgba(self) -> RgbaImage {
match self {
DynamicImage::ImageRgba8(x) => x,
x => x.to_rgba(),
}
}
pub fn into_bgr(self) -> BgrImage {
match self {
DynamicImage::ImageBgr8(x) => x,
x => x.to_bgr(),
}
}
pub fn into_bgra(self) -> BgraImage {
match self {
DynamicImage::ImageBgra8(x) => x,
x => x.to_bgra(),
}
}
pub fn into_luma(self) -> GrayImage {
match self {
DynamicImage::ImageLuma8(x) => x,
x => x.to_luma(),
}
}
pub fn into_luma_alpha(self) -> GrayAlphaImage {
match self {
DynamicImage::ImageLumaA8(x) => x,
x => x.to_luma_alpha(),
}
}
pub fn crop(&mut self, x: u32, y: u32, width: u32, height: u32) -> DynamicImage {
dynamic_map!(*self, ref mut p => imageops::crop(p, x, y, width, height).to_image())
}
pub fn as_rgb8(&self) -> Option<&RgbImage> {
match *self {
DynamicImage::ImageRgb8(ref p) => Some(p),
_ => None,
}
}
pub fn as_mut_rgb8(&mut self) -> Option<&mut RgbImage> {
match *self {
DynamicImage::ImageRgb8(ref mut p) => Some(p),
_ => None,
}
}
pub fn as_bgr8(&self) -> Option<&BgrImage> {
match *self {
DynamicImage::ImageBgr8(ref p) => Some(p),
_ => None,
}
}
pub fn as_mut_bgr8(&mut self) -> Option<&mut BgrImage> {
match *self {
DynamicImage::ImageBgr8(ref mut p) => Some(p),
_ => None,
}
}
pub fn as_rgba8(&self) -> Option<&RgbaImage> {
match *self {
DynamicImage::ImageRgba8(ref p) => Some(p),
_ => None,
}
}
pub fn as_mut_rgba8(&mut self) -> Option<&mut RgbaImage> {
match *self {
DynamicImage::ImageRgba8(ref mut p) => Some(p),
_ => None,
}
}
pub fn as_bgra8(&self) -> Option<&BgraImage> {
match *self {
DynamicImage::ImageBgra8(ref p) => Some(p),
_ => None,
}
}
pub fn as_mut_bgra8(&mut self) -> Option<&mut BgraImage> {
match *self {
DynamicImage::ImageBgra8(ref mut p) => Some(p),
_ => None,
}
}
pub fn as_luma8(&self) -> Option<&GrayImage> {
match *self {
DynamicImage::ImageLuma8(ref p) => Some(p),
_ => None,
}
}
pub fn as_mut_luma8(&mut self) -> Option<&mut GrayImage> {
match *self {
DynamicImage::ImageLuma8(ref mut p) => Some(p),
_ => None,
}
}
pub fn as_luma_alpha8(&self) -> Option<&GrayAlphaImage> {
match *self {
DynamicImage::ImageLumaA8(ref p) => Some(p),
_ => None,
}
}
pub fn as_mut_luma_alpha8(&mut self) -> Option<&mut GrayAlphaImage> {
match *self {
DynamicImage::ImageLumaA8(ref mut p) => Some(p),
_ => None,
}
}
pub fn raw_pixels(&self) -> Vec<u8> {
image_to_bytes(self)
}
pub fn as_flat_samples(&self) -> FlatSamples<&[u8]> {
dynamic_map!(*self, ref p -> p.as_flat_samples())
}
pub fn color(&self) -> color::ColorType {
match *self {
DynamicImage::ImageLuma8(_) => color::ColorType::Gray(8),
DynamicImage::ImageLumaA8(_) => color::ColorType::GrayA(8),
DynamicImage::ImageRgb8(_) => color::ColorType::RGB(8),
DynamicImage::ImageRgba8(_) => color::ColorType::RGBA(8),
DynamicImage::ImageBgra8(_) => color::ColorType::BGRA(8),
DynamicImage::ImageBgr8(_) => color::ColorType::BGR(8),
}
}
pub fn grayscale(&self) -> DynamicImage {
match *self {
DynamicImage::ImageLuma8(ref p) => DynamicImage::ImageLuma8(p.clone()),
DynamicImage::ImageLumaA8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)),
DynamicImage::ImageRgb8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)),
DynamicImage::ImageRgba8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)),
DynamicImage::ImageBgr8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)),
DynamicImage::ImageBgra8(ref p) => DynamicImage::ImageLuma8(imageops::grayscale(p)),
}
}
pub fn invert(&mut self) {
dynamic_map!(*self, ref mut p -> imageops::invert(p))
}
pub fn resize(&self, nwidth: u32, nheight: u32, filter: imageops::FilterType) -> DynamicImage {
let (width2, height2) =
resize_dimensions(self.width(), self.height(), nwidth, nheight, false);
self.resize_exact(width2, height2, filter)
}
pub fn resize_exact(
&self,
nwidth: u32,
nheight: u32,
filter: imageops::FilterType,
) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::resize(p, nwidth, nheight, filter))
}
pub fn thumbnail(&self, nwidth: u32, nheight: u32) -> DynamicImage {
let (width2, height2) =
resize_dimensions(self.width(), self.height(), nwidth, nheight, false);
self.thumbnail_exact(width2, height2)
}
pub fn thumbnail_exact(&self, nwidth: u32, nheight: u32) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::thumbnail(p, nwidth, nheight))
}
pub fn resize_to_fill(
&self,
nwidth: u32,
nheight: u32,
filter: imageops::FilterType,
) -> DynamicImage {
let (width2, height2) =
resize_dimensions(self.width(), self.height(), nwidth, nheight, true);
let mut intermediate = self.resize_exact(width2, height2, filter);
let (iwidth, iheight) = intermediate.dimensions();
let ratio = u64::from(iwidth) * u64::from(nheight);
let nratio = u64::from(nwidth) * u64::from(iheight);
if nratio > ratio {
intermediate.crop(0, (iheight - nheight) / 2, nwidth, nheight)
} else {
intermediate.crop((iwidth - nwidth) / 2, 0, nwidth, nheight)
}
}
pub fn blur(&self, sigma: f32) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::blur(p, sigma))
}
pub fn unsharpen(&self, sigma: f32, threshold: i32) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::unsharpen(p, sigma, threshold))
}
pub fn filter3x3(&self, kernel: &[f32]) -> DynamicImage {
if kernel.len() != 9 {
panic!("filter must be 3 x 3")
}
dynamic_map!(*self, ref p => imageops::filter3x3(p, kernel))
}
pub fn adjust_contrast(&self, c: f32) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::contrast(p, c))
}
pub fn brighten(&self, value: i32) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::brighten(p, value))
}
pub fn huerotate(&self, value: i32) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::huerotate(p, value))
}
pub fn flipv(&self) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::flip_vertical(p))
}
pub fn fliph(&self) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::flip_horizontal(p))
}
pub fn rotate90(&self) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::rotate90(p))
}
pub fn rotate180(&self) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::rotate180(p))
}
pub fn rotate270(&self) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::rotate270(p))
}
pub fn write_to<W: Write, F: Into<ImageOutputFormat>>(
&self,
w: &mut W,
format: F,
) -> ImageResult<()> {
let mut bytes = self.raw_pixels();
let (width, height) = self.dimensions();
let mut color = self.color();
let format = format.into();
#[allow(deprecated)]
match format {
#[cfg(feature = "png_codec")]
image::ImageOutputFormat::PNG => {
let p = png::PNGEncoder::new(w);
match *self {
DynamicImage::ImageBgra8(_) => {
bytes = self.to_rgba().iter().cloned().collect();
color = color::ColorType::RGBA(8);
}
DynamicImage::ImageBgr8(_) => {
bytes = self.to_rgb().iter().cloned().collect();
color = color::ColorType::RGB(8);
}
_ => {}
}
p.encode(&bytes, width, height, color)?;
Ok(())
}
#[cfg(feature = "pnm")]
image::ImageOutputFormat::PNM(subtype) => {
let mut p = pnm::PNMEncoder::new(w).with_subtype(subtype);
match *self {
DynamicImage::ImageBgra8(_) => {
bytes = self.to_rgba().iter().cloned().collect();
color = color::ColorType::RGBA(8);
}
DynamicImage::ImageBgr8(_) => {
bytes = self.to_rgb().iter().cloned().collect();
color = color::ColorType::RGB(8);
}
_ => {}
}
p.encode(&bytes[..], width, height, color)?;
Ok(())
}
#[cfg(feature = "jpeg")]
image::ImageOutputFormat::JPEG(quality) => {
let mut j = jpeg::JPEGEncoder::new_with_quality(w, quality);
j.encode(&bytes, width, height, color)?;
Ok(())
}
#[cfg(feature = "gif_codec")]
image::ImageOutputFormat::GIF => {
let mut g = gif::Encoder::new(w);
g.encode(&gif::Frame::from_rgba(
width as u16,
height as u16,
&mut *self.to_rgba().iter().cloned().collect::<Vec<u8>>(),
))?;
Ok(())
}
#[cfg(feature = "ico")]
image::ImageOutputFormat::ICO => {
let i = ico::ICOEncoder::new(w);
i.encode(&bytes, width, height, color)?;
Ok(())
}
#[cfg(feature = "bmp")]
image::ImageOutputFormat::BMP => {
let mut b = bmp::BMPEncoder::new(w);
b.encode(&bytes, width, height, color)?;
Ok(())
}
image::ImageOutputFormat::Unsupported(msg) => {
Err(image::ImageError::UnsupportedError(msg))
}
}
}
pub fn save<Q>(&self, path: Q) -> io::Result<()>
where
Q: AsRef<Path>,
{
dynamic_map!(*self, ref p -> {
p.save(path)
})
}
pub fn save_with_format<Q>(&self, path: Q, format: ImageFormat) -> io::Result<()>
where
Q: AsRef<Path>,
{
dynamic_map!(*self, ref p -> {
p.save_with_format(path, format)
})
}
}
#[allow(deprecated)]
impl GenericImageView for DynamicImage {
type Pixel = color::Rgba<u8>;
type InnerImageView = Self;
fn dimensions(&self) -> (u32, u32) {
dynamic_map!(*self, ref p -> p.dimensions())
}
fn bounds(&self) -> (u32, u32, u32, u32) {
dynamic_map!(*self, ref p -> p.bounds())
}
fn get_pixel(&self, x: u32, y: u32) -> color::Rgba<u8> {
dynamic_map!(*self, ref p -> p.get_pixel(x, y).to_rgba())
}
fn inner(&self) -> &Self::InnerImageView {
self
}
}
#[allow(deprecated)]
impl GenericImage for DynamicImage {
type InnerImage = DynamicImage;
fn put_pixel(&mut self, x: u32, y: u32, pixel: color::Rgba<u8>) {
match *self {
DynamicImage::ImageLuma8(ref mut p) => p.put_pixel(x, y, pixel.to_luma()),
DynamicImage::ImageLumaA8(ref mut p) => p.put_pixel(x, y, pixel.to_luma_alpha()),
DynamicImage::ImageRgb8(ref mut p) => p.put_pixel(x, y, pixel.to_rgb()),
DynamicImage::ImageRgba8(ref mut p) => p.put_pixel(x, y, pixel),
DynamicImage::ImageBgr8(ref mut p) => p.put_pixel(x, y, pixel.to_bgr()),
DynamicImage::ImageBgra8(ref mut p) => p.put_pixel(x, y, pixel.to_bgra()),
}
}
fn blend_pixel(&mut self, x: u32, y: u32, pixel: color::Rgba<u8>) {
match *self {
DynamicImage::ImageLuma8(ref mut p) => p.blend_pixel(x, y, pixel.to_luma()),
DynamicImage::ImageLumaA8(ref mut p) => p.blend_pixel(x, y, pixel.to_luma_alpha()),
DynamicImage::ImageRgb8(ref mut p) => p.blend_pixel(x, y, pixel.to_rgb()),
DynamicImage::ImageRgba8(ref mut p) => p.blend_pixel(x, y, pixel),
DynamicImage::ImageBgr8(ref mut p) => p.blend_pixel(x, y, pixel.to_bgr()),
DynamicImage::ImageBgra8(ref mut p) => p.blend_pixel(x, y, pixel.to_bgra()),
}
}
fn get_pixel_mut(&mut self, _: u32, _: u32) -> &mut color::Rgba<u8> {
unimplemented!()
}
fn inner_mut(&mut self) -> &mut Self::InnerImage {
self
}
}
fn decoder_to_image<'a, I: ImageDecoder<'a>>(codec: I) -> ImageResult<DynamicImage> {
let color = codec.colortype();
let (w, h) = codec.dimensions();
let buf = codec.read_image()?;
assert!(w <= u64::from(u32::max_value()));
assert!(h <= u64::from(u32::max_value()));
let (w, h) = (w as u32, h as u32);
let image = match color {
color::ColorType::RGB(8) => ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgb8),
color::ColorType::RGBA(8) => ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageRgba8),
color::ColorType::BGR(8) => ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageBgr8),
color::ColorType::BGRA(8) => ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageBgra8),
color::ColorType::Gray(8) => ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLuma8),
color::ColorType::GrayA(8) => {
ImageBuffer::from_raw(w, h, buf).map(DynamicImage::ImageLumaA8)
}
color::ColorType::Gray(bit_depth) if bit_depth == 1 || bit_depth == 2 || bit_depth == 4 => {
gray_to_luma8(bit_depth, w, h, &buf).map(DynamicImage::ImageLuma8)
}
_ => return Err(image::ImageError::UnsupportedColor(color)),
};
match image {
Some(image) => Ok(image),
None => Err(image::ImageError::DimensionError),
}
}
fn gray_to_luma8(bit_depth: u8, w: u32, h: u32, buf: &[u8]) -> Option<GrayImage> {
let mask = (1u8 << bit_depth as usize) - 1;
let scaling_factor = 255 / ((1 << bit_depth as usize) - 1);
let bit_width = w * u32::from(bit_depth);
let skip = if bit_width % 8 == 0 {
0
} else {
(8 - bit_width % 8) / u32::from(bit_depth)
};
let row_len = w + skip;
let mut p = Vec::new();
let mut i = 0;
for v in buf {
for shift in num_iter::range_step_inclusive(8i8 - (bit_depth as i8), 0, -(bit_depth as i8))
{
if i % (row_len as usize) < (w as usize) {
let pixel = (v & mask << shift as usize) >> shift as usize;
p.push(pixel * scaling_factor);
}
i += 1;
}
}
ImageBuffer::from_raw(w, h, p)
}
#[allow(deprecated)]
fn image_to_bytes(image: &DynamicImage) -> Vec<u8> {
match *image {
DynamicImage::ImageLuma8(ref a) => a.iter().cloned().collect(),
DynamicImage::ImageLumaA8(ref a) => a.iter().cloned().collect(),
DynamicImage::ImageRgb8(ref a) => a.iter().cloned().collect(),
DynamicImage::ImageRgba8(ref a) => a.iter().cloned().collect(),
DynamicImage::ImageBgr8(ref a) => a.iter().cloned().collect(),
DynamicImage::ImageBgra8(ref a) => a.iter().cloned().collect(),
}
}
pub fn open<P>(path: P) -> ImageResult<DynamicImage>
where
P: AsRef<Path>,
{
free_functions::open_impl(path.as_ref())
}
pub fn image_dimensions<P>(path: P) -> ImageResult<(u32, u32)>
where
P: AsRef<Path>,
{
free_functions::image_dimensions_impl(path.as_ref())
}
pub fn save_buffer<P>(
path: P,
buf: &[u8],
width: u32,
height: u32,
color: color::ColorType,
) -> io::Result<()>
where
P: AsRef<Path>,
{
free_functions::save_buffer_impl(path.as_ref(), buf, width, height, color)
}
pub fn save_buffer_with_format<P>(
path: P,
buf: &[u8],
width: u32,
height: u32,
color: color::ColorType,
format: ImageFormat,
) -> io::Result<()>
where
P: AsRef<Path>,
{
free_functions::save_buffer_with_format_impl(path.as_ref(), buf, width, height, color, format)
}
pub fn load_from_memory(buffer: &[u8]) -> ImageResult<DynamicImage> {
let format = free_functions::guess_format(buffer)?;
load_from_memory_with_format(buffer, format)
}
#[inline(always)]
pub fn load_from_memory_with_format(buf: &[u8], format: ImageFormat) -> ImageResult<DynamicImage> {
let b = io::Cursor::new(buf);
free_functions::load(b, format)
}
fn resize_dimensions(width: u32, height: u32, nwidth: u32, nheight: u32, fill: bool) -> (u32, u32) {
let ratio = u64::from(width) * u64::from(nheight);
let nratio = u64::from(nwidth) * u64::from(height);
let use_width = if fill {
nratio > ratio
} else {
nratio <= ratio
};
let intermediate = if use_width {
u64::from(height) * u64::from(nwidth) / u64::from(width)
} else {
u64::from(width) * u64::from(nheight) / u64::from(height)
};
if use_width {
if intermediate <= u64::from(::std::u32::MAX) {
(nwidth, intermediate as u32)
} else {
(
(u64::from(nwidth) * u64::from(::std::u32::MAX) / intermediate) as u32,
::std::u32::MAX,
)
}
} else if intermediate <= u64::from(::std::u32::MAX) {
(intermediate as u32, nheight)
} else {
(
::std::u32::MAX,
(u64::from(nheight) * u64::from(::std::u32::MAX) / intermediate) as u32,
)
}
}
#[cfg(test)]
mod bench {
#[cfg(feature = "benchmarks")]
use test;
#[bench]
#[cfg(feature = "benchmarks")]
fn bench_conversion(b: &mut test::Bencher) {
let a = super::DynamicImage::ImageRgb8(::ImageBuffer::new(1000, 1000));
b.iter(|| a.to_luma());
b.bytes = 1000 * 1000 * 3
}
}
#[cfg(test)]
mod test {
#[test]
fn test_empty_file() {
assert!(super::load_from_memory(b"").is_err());
}
quickcheck! {
fn resize_bounds_correctly_width(old_w: u32, new_w: u32) -> bool {
if old_w == 0 || new_w == 0 { return true; }
let result = super::resize_dimensions(old_w, 400, new_w, ::std::u32::MAX, false);
result.0 == new_w && result.1 == (400 as f64 * new_w as f64 / old_w as f64) as u32
}
}
quickcheck! {
fn resize_bounds_correctly_height(old_h: u32, new_h: u32) -> bool {
if old_h == 0 || new_h == 0 { return true; }
let result = super::resize_dimensions(400, old_h, ::std::u32::MAX, new_h, false);
result.1 == new_h && result.0 == (400 as f64 * new_h as f64 / old_h as f64) as u32
}
}
#[test]
fn resize_handles_fill() {
let result = super::resize_dimensions(100, 200, 200, 500, true);
assert!(result.0 == 250);
assert!(result.1 == 500);
let result = super::resize_dimensions(200, 100, 500, 200, true);
assert!(result.0 == 500);
assert!(result.1 == 250);
}
#[test]
fn resize_handles_overflow() {
let result = super::resize_dimensions(100, ::std::u32::MAX, 200, ::std::u32::MAX, true);
assert!(result.0 == 100);
assert!(result.1 == ::std::u32::MAX);
let result = super::resize_dimensions(::std::u32::MAX, 100, ::std::u32::MAX, 200, true);
assert!(result.0 == ::std::u32::MAX);
assert!(result.1 == 100);
}
#[test]
#[rustfmt::skip]
fn gray_to_luma8_skip() {
let check = |bit_depth, w, h, from, to| {
assert_eq!(
super::gray_to_luma8(bit_depth, w, h, from).map(super::GrayImage::into_raw),
Some(to)
);
};
check(
1,
10,
2,
&[0b11110000, 0b11000000, 0b00001111, 0b11000000],
vec![
255, 255, 255, 255, 0,
0, 0, 0, 255, 255,
0, 0, 0, 0, 255,
255, 255, 255, 255, 255,
],
);
check(
2,
5,
2,
&[0b11110000, 0b11000000, 0b00001111, 0b11000000],
vec![255, 255, 0, 0, 255, 0, 0, 255, 255, 255],
);
check(
2,
4,
2,
&[0b11110000, 0b00001111],
vec![255, 255, 0, 0, 0, 0, 255, 255],
);
check(4, 1, 2, &[0b11110011, 0b00001100], vec![255, 0]);
}
#[cfg(feature = "jpeg")]
#[test]
fn image_dimensions() {
let im_path = "./tests/images/jpg/progressive/cat.jpg";
let dims = super::image_dimensions(im_path).unwrap();
assert_eq!(dims, (320, 240));
}
}