use oxideav_webp::{
decode_webp, encode_vp8l_argb, encode_vp8l_argb_with, encode_vp8l_argb_with_metadata,
extract_metadata, WebpError, WebpMetadata,
};
fn make_argb(width: u32, height: u32, opaque: bool) -> Vec<u32> {
let mut buf = Vec::with_capacity((width * height) as usize);
for y in 0..height {
for x in 0..width {
let r = x.wrapping_mul(37).wrapping_add(y) & 0xff;
let g = y.wrapping_mul(53).wrapping_add(x) & 0xff;
let b = (x ^ y).wrapping_mul(101) & 0xff;
let a = if opaque {
0xff
} else {
255 - ((x.wrapping_add(y)) & 0xff)
};
buf.push((a << 24) | (r << 16) | (g << 8) | b);
}
}
buf
}
fn argb_to_rgba(argb: &[u32]) -> Vec<u8> {
let mut out = Vec::with_capacity(argb.len() * 4);
for &p in argb {
out.push((p >> 16) as u8); out.push((p >> 8) as u8); out.push(p as u8); out.push((p >> 24) as u8); }
out
}
#[test]
fn encode_vp8l_argb_is_bare_bitstream_no_riff() {
let (w, h) = (5u32, 4u32);
let argb = make_argb(w, h, true);
let bare = encode_vp8l_argb(&argb, w, h).expect("bare VP8L encode");
assert_ne!(&bare[0..4], b"RIFF");
assert_eq!(bare[0], 0x2F, "VP8L image-header signature byte");
}
#[test]
fn encode_vp8l_argb_with_metadata_simple_round_trips() {
let (w, h) = (7u32, 3u32);
let argb = make_argb(w, h, true);
let file = encode_vp8l_argb_with_metadata(w, h, &argb, false, &WebpMetadata::default())
.expect("simple VP8L .webp");
let img = decode_webp(&file).expect("decode");
assert_eq!(img.frames.len(), 1);
assert_eq!(img.frames[0].width, w);
assert_eq!(img.frames[0].height, h);
assert_eq!(img.frames[0].rgba, argb_to_rgba(&argb));
assert_eq!(img.metadata.icc, None);
assert_eq!(img.metadata.exif, None);
assert_eq!(img.metadata.xmp, None);
}
#[test]
fn encode_vp8l_argb_with_metadata_alpha_promotes_to_extended() {
let (w, h) = (4u32, 4u32);
let argb = make_argb(w, h, false);
let file = encode_vp8l_argb_with_metadata(w, h, &argb, true, &WebpMetadata::default())
.expect("alpha VP8L .webp");
let img = decode_webp(&file).expect("decode");
assert_eq!(img.frames[0].rgba, argb_to_rgba(&argb));
}
#[test]
fn encode_vp8l_argb_with_metadata_embeds_and_reads_back() {
let (w, h) = (3u32, 3u32);
let argb = make_argb(w, h, true);
let icc = b"fake-icc-profile-bytes".to_vec();
let exif = b"Exif\x00\x00MM\x00*".to_vec();
let xmp = b"<?xpacket begin?>".to_vec();
let meta = WebpMetadata {
icc: Some(&icc),
exif: Some(&exif),
xmp: Some(&xmp),
};
let file = encode_vp8l_argb_with_metadata(w, h, &argb, false, &meta).expect("metadata .webp");
let read = extract_metadata(&file).expect("extract_metadata");
assert_eq!(read.icc.as_deref(), Some(&icc[..]));
assert_eq!(read.exif.as_deref(), Some(&exif[..]));
assert_eq!(read.xmp.as_deref(), Some(&xmp[..]));
let img = decode_webp(&file).expect("decode");
assert_eq!(img.frames[0].rgba, argb_to_rgba(&argb));
assert_eq!(img.metadata.icc.as_deref(), Some(&icc[..]));
}
#[test]
fn encode_vp8l_argb_with_forces_alpha_bit_but_round_trips() {
let (w, h) = (2u32, 2u32);
let argb = make_argb(w, h, true);
let bare = encode_vp8l_argb_with(&argb, w, h, true).expect("forced-alpha bare bitstream");
let file = encode_vp8l_argb_with_metadata(w, h, &argb, true, &WebpMetadata::default())
.expect("alpha-flagged .webp");
let _ = bare; let img = decode_webp(&file).expect("decode");
assert_eq!(img.frames[0].rgba, argb_to_rgba(&argb));
}
#[test]
fn encode_vp8l_argb_rejects_dimension_mismatch() {
let argb = vec![0xff00_0000u32];
let err = encode_vp8l_argb(&argb, 2, 2).expect_err("mismatch rejected");
assert_eq!(err, WebpError::InvalidData);
}