Files
pixstrip/pixstrip-core/tests/encoder_tests.rs
lashman 52931daf53 Add output encoders (mozjpeg, oxipng, webp, avif) and integration tests
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.
2026-03-06 02:02:27 +02:00

89 lines
2.8 KiB
Rust

use pixstrip_core::encoder::OutputEncoder;
use pixstrip_core::types::{ImageFormat, QualityPreset};
fn create_test_rgb_image(width: u32, height: u32) -> image::DynamicImage {
let img = image::RgbImage::from_fn(width, height, |x, y| {
image::Rgb([(x % 256) as u8, (y % 256) as u8, 128])
});
image::DynamicImage::ImageRgb8(img)
}
fn create_test_rgba_image(width: u32, height: u32) -> image::DynamicImage {
let img = image::RgbaImage::from_fn(width, height, |x, y| {
image::Rgba([(x % 256) as u8, (y % 256) as u8, 100, 255])
});
image::DynamicImage::ImageRgba8(img)
}
#[test]
fn encode_jpeg() {
let img = create_test_rgb_image(200, 150);
let encoder = OutputEncoder::new();
let bytes = encoder.encode(&img, ImageFormat::Jpeg, Some(85)).unwrap();
assert!(!bytes.is_empty());
// JPEG magic bytes
assert_eq!(bytes[0], 0xFF);
assert_eq!(bytes[1], 0xD8);
}
#[test]
fn encode_jpeg_quality_affects_size() {
let img = create_test_rgb_image(200, 150);
let encoder = OutputEncoder::new();
let high = encoder.encode(&img, ImageFormat::Jpeg, Some(95)).unwrap();
let low = encoder.encode(&img, ImageFormat::Jpeg, Some(50)).unwrap();
assert!(high.len() > low.len(), "Higher quality should produce larger files");
}
#[test]
fn encode_png() {
let img = create_test_rgba_image(200, 150);
let encoder = OutputEncoder::new();
let bytes = encoder.encode(&img, ImageFormat::Png, None).unwrap();
assert!(!bytes.is_empty());
// PNG magic bytes
assert_eq!(&bytes[0..4], &[0x89, 0x50, 0x4E, 0x47]);
}
#[test]
fn encode_webp() {
let img = create_test_rgb_image(200, 150);
let encoder = OutputEncoder::new();
let bytes = encoder.encode(&img, ImageFormat::WebP, Some(80)).unwrap();
assert!(!bytes.is_empty());
// RIFF header
assert_eq!(&bytes[0..4], b"RIFF");
}
#[test]
fn encode_to_file() {
let img = create_test_rgb_image(200, 150);
let encoder = OutputEncoder::new();
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("output.jpg");
encoder.encode_to_file(&img, &path, ImageFormat::Jpeg, Some(85)).unwrap();
assert!(path.exists());
let metadata = std::fs::metadata(&path).unwrap();
assert!(metadata.len() > 0);
}
#[test]
fn quality_from_preset() {
let encoder = OutputEncoder::new();
let preset = QualityPreset::High;
let q = encoder.quality_for_format(ImageFormat::Jpeg, &preset);
assert_eq!(q, 85);
let q = encoder.quality_for_format(ImageFormat::WebP, &preset);
assert!((q as f32 - 85.0).abs() < 1.0);
}
#[test]
fn encode_gif_fallback() {
let img = create_test_rgba_image(50, 50);
let encoder = OutputEncoder::new();
let bytes = encoder.encode(&img, ImageFormat::Gif, None).unwrap();
assert!(!bytes.is_empty());
// GIF magic bytes
assert_eq!(&bytes[0..3], b"GIF");
}