#![cfg(not(target_arch = "wasm32"))]
#![cfg(feature = "_test-helpers")]
mod common;
use common::{create_hdr_gradient, create_hdr_solid, create_sdr_gradient, create_sdr_solid};
fn decode_jpeg(data: &[u8]) -> (u32, u32, usize, Vec<u8>) {
let result = zenjpeg::decoder::Decoder::new()
.decode(data, enough::Unstoppable)
.expect("zenjpeg should decode JPEG");
let w = result.width();
let h = result.height();
let pixels = result.pixels_u8().expect("expected u8 output").to_vec();
(w, h, 3, pixels)
}
#[test]
fn test_decoder_decodes_ultrahdr_base() {
let hdr = create_hdr_gradient(128, 128, 4.0);
let sdr = create_sdr_gradient(128, 128);
let mut encoder = ultrahdr_rs::Encoder::new();
encoder
.set_hdr_image(hdr)
.set_sdr_image(sdr)
.set_quality(90, 85);
let encoded = encoder.encode().unwrap();
let (w, h, _components, pixels) = decode_jpeg(&encoded);
assert!(!pixels.is_empty(), "Decoded pixels should not be empty");
assert_eq!(w, 128);
assert_eq!(h, 128);
}
#[test]
fn test_decoder_sdr_pixel_preservation() {
let hdr = create_hdr_solid(64, 64, 0.5, 0.5, 0.5);
let sdr = create_sdr_solid(64, 64, 186, 186, 186);
let mut encoder = ultrahdr_rs::Encoder::new();
encoder
.set_hdr_image(hdr)
.set_sdr_image(sdr)
.set_quality(95, 90);
let encoded = encoder.encode().unwrap();
let (_w, _h, components, pixels) = decode_jpeg(&encoded);
for i in 0..64 {
let offset = i * components;
if offset + 2 < pixels.len() {
let r = pixels[offset];
let g = pixels[offset + 1];
let b = pixels[offset + 2];
let max_diff = (r as i16 - 186)
.abs()
.max((g as i16 - 186).abs())
.max((b as i16 - 186).abs());
assert!(
max_diff < 20,
"Pixel {} color diff {} too high: RGB({},{},{})",
i,
max_diff,
r,
g,
b
);
}
}
}
#[test]
fn test_decoder_various_sizes() {
let sizes = [(32, 32), (64, 48), (100, 75), (128, 128), (200, 150)];
for (w, h) in sizes {
let hdr = create_hdr_gradient(w, h, 2.0);
let sdr = create_sdr_gradient(w, h);
let mut encoder = ultrahdr_rs::Encoder::new();
encoder.set_hdr_image(hdr).set_sdr_image(sdr);
let encoded = encoder.encode().unwrap();
let (dw, dh, _components, _pixels) = decode_jpeg(&encoded);
assert_eq!(dw, w, "Width mismatch for {}x{}", w, h);
assert_eq!(dh, h, "Height mismatch for {}x{}", w, h);
}
}
#[test]
fn test_decoder_handles_metadata_markers() {
let hdr = create_hdr_gradient(64, 64, 4.0);
let sdr = create_sdr_gradient(64, 64);
let mut encoder = ultrahdr_rs::Encoder::new();
encoder
.set_hdr_image(hdr)
.set_sdr_image(sdr)
.set_use_iso_metadata(true);
let encoded = encoder.encode().unwrap();
let has_xmp = encoded.windows(4).any(|w| w == b"http");
let has_mpf = encoded.windows(4).any(|w| w == b"MPF\0");
assert!(has_xmp, "Should contain XMP marker");
assert!(has_mpf, "Should contain MPF marker");
let (_w, _h, _components, pixels) = decode_jpeg(&encoded);
assert!(!pixels.is_empty());
}
#[test]
fn test_roundtrip_with_decoder() {
let hdr = create_hdr_gradient(80, 80, 2.0);
let sdr = create_sdr_gradient(80, 80);
let mut encoder = ultrahdr_rs::Encoder::new();
encoder
.set_hdr_image(hdr)
.set_sdr_image(sdr)
.set_quality(95, 90);
let encoded = encoder.encode().unwrap();
let (_w, _h, zen_channels, zen_pixels) = decode_jpeg(&encoded);
let our_decoder = ultrahdr_rs::Decoder::new(&encoded).unwrap();
let our_sdr = our_decoder.decode_sdr().unwrap();
assert_eq!(_w, our_sdr.width);
assert_eq!(_h, our_sdr.height);
let mut max_diff = 0i16;
let pixel_count = (80 * 80) as usize;
for i in 0..pixel_count.min(zen_pixels.len() / zen_channels) {
let zen_r = zen_pixels[i * zen_channels] as i16;
let our_r = our_sdr.data[i * 4] as i16;
let diff = (zen_r - our_r).abs();
max_diff = max_diff.max(diff);
}
assert!(
max_diff < 60,
"Pixel difference between zenjpeg and our decoder: {}",
max_diff
);
}
#[test]
fn test_decoder_decodes_gainmap() {
let hdr = create_hdr_gradient(128, 128, 4.0);
let sdr = create_sdr_gradient(128, 128);
let mut encoder = ultrahdr_rs::Encoder::new();
encoder
.set_hdr_image(hdr)
.set_sdr_image(sdr)
.set_gainmap_scale(4);
let encoded = encoder.encode().unwrap();
let our_decoder = ultrahdr_rs::Decoder::new(&encoded).unwrap();
let gm_jpeg = our_decoder.gainmap_jpeg().expect("Should have gain map");
let (gw, gh, _components, pixels) = decode_jpeg(gm_jpeg);
assert!(!pixels.is_empty());
assert_eq!(gw, 32, "Gain map width");
assert_eq!(gh, 32, "Gain map height");
}