use std::io::Cursor;
use image::imageops::FilterType;
use image::{DynamicImage, ImageFormat, ImageReader, Limits};
use crate::error::Error;
pub fn load_image(data: &[u8], max_alloc: u64, max_dimension: u32) -> Result<DynamicImage, Error> {
let mut reader = ImageReader::new(Cursor::new(data))
.with_guessed_format()
.map_err(|e| Error::ImageProcessing(format!("Failed to guess image format: {e}")))?;
let mut limits = Limits::default();
limits.max_alloc = Some(max_alloc);
limits.max_image_width = Some(max_dimension);
limits.max_image_height = Some(max_dimension);
reader.limits(limits);
reader
.decode()
.map_err(|e| Error::ImageProcessing(format!("Failed to decode image: {e}")))
}
pub fn resize_image(
img: &DynamicImage,
width: u32,
height: u32,
maintain_aspect: bool,
) -> DynamicImage {
if maintain_aspect {
img.resize(width, height, FilterType::Lanczos3)
} else {
img.resize_exact(width, height, FilterType::Lanczos3)
}
}
pub fn encode_image(img: &DynamicImage, format: ImageFormat) -> Result<Vec<u8>, Error> {
let mut buffer = Vec::new();
let mut cursor = Cursor::new(&mut buffer);
img.write_to(&mut cursor, format)
.map_err(|e| Error::ImageProcessing(format!("Failed to encode image: {e}")))?;
Ok(buffer)
}
pub fn format_from_content_type(content_type: &str) -> ImageFormat {
match content_type {
"image/png" => ImageFormat::Png,
"image/gif" => ImageFormat::Gif,
"image/webp" => ImageFormat::WebP,
_ => ImageFormat::Jpeg,
}
}
pub fn extension_from_content_type(content_type: &str) -> &str {
match content_type {
"image/png" => "png",
"image/gif" => "gif",
"image/webp" => "webp",
_ => "jpg",
}
}