use std::io;
#[cfg(feature = "jpeg")]
mod jpeg;
#[cfg(feature = "png")]
mod png;
#[cfg(feature = "tiff")]
mod tiff;
#[cfg(feature = "webp")]
mod webp;
#[cfg(feature = "jpeg")]
#[cfg_attr(docsrs, doc(cfg(feature = "jpeg")))]
pub use jpeg::{encode_jpeg, write_jpeg, write_jpeg_to};
#[cfg(feature = "png")]
#[cfg_attr(docsrs, doc(cfg(feature = "png")))]
pub use png::{encode_png, write_png, write_png_to};
#[cfg(feature = "tiff")]
#[cfg_attr(docsrs, doc(cfg(feature = "tiff")))]
pub use tiff::{encode_tiff, write_tiff, write_tiff_to, TiffCompression};
#[cfg(feature = "webp")]
#[cfg_attr(docsrs, doc(cfg(feature = "webp")))]
pub use webp::{encode_webp, write_webp, write_webp_to};
pub(crate) fn check_pixels(width: u32, height: u32, pixels: &[u8]) -> io::Result<()> {
if width == 0 || height == 0 {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("image dimensions must be non-zero; got {width}x{height}"),
));
}
let expected = u128::from(width) * u128::from(height) * 4;
if pixels.len() as u128 != expected {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"pixel buffer is {} bytes; expected {} for {}x{}",
pixels.len(),
expected,
width,
height
),
));
}
Ok(())
}
#[cfg(any(feature = "jpeg", feature = "webp"))]
pub(crate) fn check_dimension_limit(
format: &str,
limit: u32,
width: u32,
height: u32,
) -> io::Result<()> {
if width > limit || height > limit {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("{width}x{height} exceeds the {limit}x{limit} {format} maximum"),
));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn zero_dimensions_are_rejected() {
for (w, h) in [(0, 4), (4, 0), (0, 0)] {
let err = check_pixels(w, h, &[]).expect_err("zero area must fail");
assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
}
}
#[test]
fn buffer_must_hold_exactly_one_rgba8_pixel_per_pixel() {
assert!(check_pixels(4, 3, &[0u8; 4 * 3 * 4]).is_ok());
for len in [4 * 3 * 4 - 1, 4 * 3 * 4 + 1] {
let err = check_pixels(4, 3, &vec![0u8; len]).expect_err("wrong length must fail");
assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
}
}
#[test]
fn oversized_dimensions_do_not_wrap() {
let err = check_pixels(u32::MAX, u32::MAX, &[0u8; 16]).expect_err("must fail");
assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
}
}