OutputEncoder dispatches to specialized encoders per format. JPEG: mozjpeg with quality control. PNG: oxipng lossless optimization. WebP: libwebp encoding. AVIF: ravif via image crate. GIF/TIFF: fallback via image crate. Phase 3 complete - 59 tests passing, zero clippy warnings.
86 lines
2.7 KiB
Rust
86 lines
2.7 KiB
Rust
use pixstrip_core::encoder::OutputEncoder;
|
|
use pixstrip_core::loader::ImageLoader;
|
|
use pixstrip_core::operations::resize::resize_image;
|
|
use pixstrip_core::operations::ResizeConfig;
|
|
use pixstrip_core::types::ImageFormat;
|
|
use std::path::Path;
|
|
|
|
fn create_test_jpeg(path: &Path) {
|
|
let img = image::RgbImage::from_fn(400, 300, |x, y| {
|
|
image::Rgb([(x % 256) as u8, (y % 256) as u8, 128])
|
|
});
|
|
img.save_with_format(path, image::ImageFormat::Jpeg).unwrap();
|
|
}
|
|
|
|
fn create_test_png(path: &Path) {
|
|
let img = image::RgbaImage::from_fn(400, 300, |x, y| {
|
|
image::Rgba([(x % 256) as u8, (y % 256) as u8, 100, 255])
|
|
});
|
|
img.save_with_format(path, image::ImageFormat::Png).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn load_resize_save_as_webp() {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
let input = dir.path().join("input.jpg");
|
|
let output = dir.path().join("output.webp");
|
|
create_test_jpeg(&input);
|
|
|
|
let loader = ImageLoader::new();
|
|
let img = loader.load_pixels(&input).unwrap();
|
|
|
|
let config = ResizeConfig::ByWidth(200);
|
|
let resized = resize_image(&img, &config).unwrap();
|
|
assert_eq!(resized.width(), 200);
|
|
assert_eq!(resized.height(), 150);
|
|
|
|
let encoder = OutputEncoder::new();
|
|
encoder.encode_to_file(&resized, &output, ImageFormat::WebP, Some(80)).unwrap();
|
|
assert!(output.exists());
|
|
|
|
let info = loader.load_info(&output).unwrap();
|
|
assert_eq!(info.dimensions.width, 200);
|
|
assert_eq!(info.dimensions.height, 150);
|
|
}
|
|
|
|
#[test]
|
|
fn load_png_compress_smaller() {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
let input = dir.path().join("input.png");
|
|
let output = dir.path().join("output.png");
|
|
create_test_png(&input);
|
|
|
|
let loader = ImageLoader::new();
|
|
let img = loader.load_pixels(&input).unwrap();
|
|
|
|
let encoder = OutputEncoder::new();
|
|
encoder.encode_to_file(&img, &output, ImageFormat::Png, None).unwrap();
|
|
|
|
let original_size = std::fs::metadata(&input).unwrap().len();
|
|
let optimized_size = std::fs::metadata(&output).unwrap().len();
|
|
assert!(
|
|
optimized_size <= original_size,
|
|
"Optimized PNG ({}) should be <= original ({})",
|
|
optimized_size,
|
|
original_size
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn load_jpeg_convert_to_png() {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
let input = dir.path().join("input.jpg");
|
|
let output = dir.path().join("output.png");
|
|
create_test_jpeg(&input);
|
|
|
|
let loader = ImageLoader::new();
|
|
let img = loader.load_pixels(&input).unwrap();
|
|
|
|
let encoder = OutputEncoder::new();
|
|
encoder.encode_to_file(&img, &output, ImageFormat::Png, None).unwrap();
|
|
assert!(output.exists());
|
|
|
|
let info = loader.load_info(&output).unwrap();
|
|
assert_eq!(info.format, Some(ImageFormat::Png));
|
|
}
|