use divan as _;
use ithmb_core::enc::*;
use ithmb_core::pipeline::decode_with_profile;
use ithmb_core::profile::{Encoding, Profile};
use jpeg_decoder as _;
#[cfg(feature = "cache")]
use lru as _;
use std::sync::atomic::AtomicBool;
use thiserror as _;
mod util;
fn bgra_2x2_3colors() -> Vec<u8> {
vec![
0, 0, 255, 255, 0, 255, 0, 255, 255, 0, 0, 255, 255, 255, 255, 255, ]
}
fn bgra_4x2_4colors() -> Vec<u8> {
vec![
0, 0, 255, 255, 0, 0, 255, 255, 0, 255, 0, 255, 0, 255, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 128, 128, 128, 255, 128, 128, 128, 255, ]
}
fn roundtrip_once(profile: &Profile, encoded: &[u8]) -> ithmb_core::error::DecodedImage {
let mut with_prefix = profile.prefix.to_be_bytes().to_vec();
with_prefix.extend(encoded);
let canceled = AtomicBool::new(false);
decode_with_profile(&with_prefix, profile, &canceled).expect("decode_with_profile should succeed")
}
#[test]
fn roundtrip_rgb565() {
let bgra = bgra_2x2_3colors();
let w = 2;
let h = 2;
let profile = Profile {
prefix: 0x1000_0001,
width: w,
height: h,
encoding: Encoding::Rgb565,
frame_byte_length: w * h * 2,
little_endian: true,
..Default::default()
};
let encoded = encode_rgb565(&bgra, w, h, false); let decoded = roundtrip_once(&profile, &encoded);
assert_eq!(decoded.width, u32::try_from(w).unwrap());
assert_eq!(decoded.height, u32::try_from(h).unwrap());
assert_eq!(decoded.data, bgra);
}
#[test]
fn roundtrip_rgb555() {
let bgra = bgra_2x2_3colors();
let w = 2;
let h = 2;
let profile = Profile {
prefix: 0x1000_0001,
width: w,
height: h,
encoding: Encoding::Rgb555,
frame_byte_length: w * h * 2,
little_endian: true,
..Default::default()
};
let encoded = encode_rgb555(&bgra, w, h, false, false); let decoded = roundtrip_once(&profile, &encoded);
assert_eq!(decoded.width, u32::try_from(w).unwrap());
assert_eq!(decoded.height, u32::try_from(h).unwrap());
assert_eq!(decoded.data, bgra);
}
#[test]
fn roundtrip_reordered_rgb555_1x1() {
let bgra = vec![0, 0, 255, 255]; let w = 1;
let h = 1;
let profile = Profile {
prefix: 0x1000_0001,
width: w,
height: h,
encoding: Encoding::ReorderedRgb555,
frame_byte_length: w * h * 2,
little_endian: false, ..Default::default()
};
let encoded = encode_reordered_rgb555(&bgra, w, h, true); let decoded = roundtrip_once(&profile, &encoded);
assert_eq!(i32::try_from(decoded.width).unwrap(), w);
assert_eq!(i32::try_from(decoded.height).unwrap(), h);
assert_eq!(decoded.data, bgra);
}
#[test]
fn roundtrip_reordered_rgb555_2x2_uniform() {
let bgra = vec![255u8; 2 * 2 * 4]; let w = 2;
let h = 2;
let profile = Profile {
prefix: 0x1000_0001,
width: w,
height: h,
encoding: Encoding::ReorderedRgb555,
frame_byte_length: w * h * 2,
little_endian: false,
..Default::default()
};
let encoded = encode_reordered_rgb555(&bgra, w, h, true);
let decoded = roundtrip_once(&profile, &encoded);
assert_eq!(i32::try_from(decoded.width).unwrap(), w);
assert_eq!(i32::try_from(decoded.height).unwrap(), h);
assert_eq!(decoded.data, bgra);
}
#[test]
fn roundtrip_uyvy() {
let bgra = bgra_4x2_4colors();
let w = 4;
let h = 2;
let profile = Profile {
prefix: 0x1000_0001,
width: w,
height: h,
encoding: Encoding::Yuv422,
frame_byte_length: w * h * 2,
..Default::default()
};
let encoded = encode_uyvy(&bgra, w, h);
let decoded = roundtrip_once(&profile, &encoded);
assert_eq!(i32::try_from(decoded.width).unwrap(), w);
assert_eq!(i32::try_from(decoded.height).unwrap(), h);
util::assert_bgra_tolerant(&decoded.data, &bgra, 2);
}
#[test]
fn roundtrip_ycbcr420() {
let bgra = vec![255u8; 2 * 2 * 4]; let w = 2;
let h = 2;
let uv_w = usize::try_from(w).unwrap().div_ceil(2);
let uv_h = usize::try_from(h).unwrap().div_ceil(2);
let frame_len = i32::try_from(usize::try_from(w * h).unwrap() + uv_w * uv_h * 2).unwrap();
let profile = Profile {
prefix: 0x1000_0001,
width: w,
height: h,
encoding: Encoding::Ycbcr420,
frame_byte_length: frame_len,
..Default::default()
};
let encoded = encode_ycbcr420(&bgra, w, h, false); let decoded = roundtrip_once(&profile, &encoded);
assert_eq!(i32::try_from(decoded.width).unwrap(), w);
assert_eq!(decoded.data, bgra);
}
#[test]
fn roundtrip_clcl() {
let bgra = bgra_2x2_3colors();
let w = 2;
let h = 2;
let n = usize::try_from(w * h).unwrap();
let chroma_len = n.div_ceil(2);
let profile = Profile {
prefix: 0x1000_0001,
width: w,
height: h,
encoding: Encoding::Yuv422,
frame_byte_length: i32::try_from(n + chroma_len + chroma_len).unwrap(),
clcl_chroma: true,
..Default::default()
};
let encoded = encode_clcl(&bgra, w, h);
let decoded = roundtrip_once(&profile, &encoded);
assert_eq!(i32::try_from(decoded.width).unwrap(), w);
assert_eq!(i32::try_from(decoded.height).unwrap(), h);
util::assert_bgra_tolerant(&decoded.data, &bgra, 32);
}
#[test]
fn roundtrip_cl() {
let bgra = bgra_2x2_3colors();
let w = 2;
let h = 2;
let n = usize::try_from(w * h).unwrap();
let profile = Profile {
prefix: 0x1000_0001,
width: w,
height: h,
encoding: Encoding::Yuv422,
frame_byte_length: i32::try_from(n * 2).unwrap(),
cl_chroma: true,
..Default::default()
};
let encoded = encode_cl(&bgra, w, h);
let decoded = roundtrip_once(&profile, &encoded);
assert_eq!(i32::try_from(decoded.width).unwrap(), w);
assert_eq!(i32::try_from(decoded.height).unwrap(), h);
util::assert_bgra_tolerant(&decoded.data, &bgra, 32);
}