use std::io::Write;
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};
use bioformats::ImageReader;
fn temp_path(name: &str) -> PathBuf {
let nanos = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
std::env::temp_dir().join(format!("bioformats_ome_bindata_{nanos}_{name}"))
}
fn base64_encode(data: &[u8]) -> String {
const CHARS: &[u8; 64] =
b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
let mut out = String::with_capacity((data.len() + 2) / 3 * 4);
for chunk in data.chunks(3) {
let b0 = chunk[0] as u32;
let b1 = chunk.get(1).copied().unwrap_or(0) as u32;
let b2 = chunk.get(2).copied().unwrap_or(0) as u32;
let triple = (b0 << 16) | (b1 << 8) | b2;
out.push(CHARS[((triple >> 18) & 0x3F) as usize] as char);
out.push(CHARS[((triple >> 12) & 0x3F) as usize] as char);
if chunk.len() > 1 {
out.push(CHARS[((triple >> 6) & 0x3F) as usize] as char);
} else {
out.push('=');
}
if chunk.len() > 2 {
out.push(CHARS[(triple & 0x3F) as usize] as char);
} else {
out.push('=');
}
}
out
}
fn zlib_compress(data: &[u8]) -> Vec<u8> {
use flate2::write::ZlibEncoder;
use flate2::Compression;
let mut enc = ZlibEncoder::new(Vec::new(), Compression::default());
enc.write_all(data).unwrap();
enc.finish().unwrap()
}
fn bzip2_compress(data: &[u8]) -> Vec<u8> {
use bzip2::write::BzEncoder;
use bzip2::Compression;
let mut enc = BzEncoder::new(Vec::new(), Compression::default());
enc.write_all(data).unwrap();
enc.finish().unwrap()
}
fn ome_xml(compression: &str, b64: &str) -> String {
format!(
r#"<?xml version="1.0" encoding="UTF-8"?>
<OME xmlns="http://www.openmicroscopy.org/Schemas/OME/2016-06">
<Image ID="Image:0" Name="bindata-test">
<Pixels ID="Pixels:0" DimensionOrder="XYZCT" Type="uint16" SizeX="4" SizeY="4" SizeZ="1" SizeC="1" SizeT="1" BigEndian="false">
<Channel ID="Channel:0:0" SamplesPerPixel="1"/>
<BinData Compression="{compression}" BigEndian="false">{b64}</BinData>
</Pixels>
</Image>
</OME>"#
)
}
fn original_plane() -> Vec<u8> {
let mut bytes = Vec::with_capacity(32);
for px in 0u16..16u16 {
let value = px.wrapping_mul(4099); bytes.extend_from_slice(&value.to_le_bytes());
}
bytes
}
fn assert_roundtrip(label: &str, xml: &str, expected: &[u8]) {
let path = temp_path(&format!("{label}.ome.xml"));
std::fs::write(&path, xml).unwrap();
let mut reader = ImageReader::open(&path).expect("ImageReader::open failed");
let meta = reader.metadata();
assert_eq!(meta.size_x, 4, "{label}: size_x");
assert_eq!(meta.size_y, 4, "{label}: size_y");
assert_eq!(meta.image_count, 1, "{label}: image_count");
assert!(meta.is_little_endian, "{label}: expected little-endian");
let got = reader.open_bytes(0).expect("open_bytes(0) failed");
assert_eq!(got, expected, "{label}: decoded plane bytes mismatch");
let _ = std::fs::remove_file(&path);
}
#[test]
fn ome_bindata_compression_none() {
let plane = original_plane();
let b64 = base64_encode(&plane);
let xml = ome_xml("none", &b64);
assert_roundtrip("none", &xml, &plane);
}
#[test]
fn ome_bindata_compression_zlib() {
let plane = original_plane();
let b64 = base64_encode(&zlib_compress(&plane));
let xml = ome_xml("zlib", &b64);
assert_roundtrip("zlib", &xml, &plane);
}
#[test]
fn ome_bindata_compression_bzip2() {
let plane = original_plane();
let b64 = base64_encode(&bzip2_compress(&plane));
let xml = ome_xml("bzip2", &b64);
assert_roundtrip("bzip2", &xml, &plane);
}