use gamut_ifd::{ByteOrder, Ifd, TiffFile, Value, Variant, write};
fn even(n: usize) -> usize {
n + (n & 1)
}
fn offset_value(variant: Variant, offsets: Vec<u64>) -> Value {
match variant {
Variant::Classic => Value::Long(offsets.iter().map(|&o| o as u32).collect()),
Variant::Big => Value::Long8(offsets),
}
}
#[must_use]
pub fn write_image(order: ByteOrder, variant: Variant, ifd: &Ifd, strips: &[Vec<u8>]) -> Vec<u8> {
write_blocks(
order,
variant,
ifd,
strips,
crate::tags::STRIP_OFFSETS,
crate::tags::STRIP_BYTE_COUNTS,
)
}
#[must_use]
pub fn write_image_tiled(
order: ByteOrder,
variant: Variant,
ifd: &Ifd,
tiles: &[Vec<u8>],
) -> Vec<u8> {
write_blocks(
order,
variant,
ifd,
tiles,
crate::tags::TILE_OFFSETS,
crate::tags::TILE_BYTE_COUNTS,
)
}
#[must_use]
pub fn write_multipage(
order: ByteOrder,
variant: Variant,
pages: &[(Ifd, Vec<Vec<u8>>)],
) -> Vec<u8> {
use crate::tags;
let mut ifds: Vec<Ifd> = pages
.iter()
.map(|(ifd, strips)| {
let mut ifd = ifd.clone();
let counts: Vec<u32> = strips.iter().map(|s| s.len() as u32).collect();
ifd.set(tags::STRIP_BYTE_COUNTS, Value::Long(counts));
ifd.set(
tags::STRIP_OFFSETS,
offset_value(variant, vec![0; strips.len()]),
);
ifd
})
.collect();
let base = even(
write(&TiffFile {
order,
variant,
ifds: ifds.clone(),
})
.len(),
);
let mut cursor = base;
for ((_, strips), ifd) in pages.iter().zip(ifds.iter_mut()) {
let mut offsets = Vec::with_capacity(strips.len());
for s in strips {
offsets.push(cursor as u64);
cursor += s.len();
}
ifd.set(tags::STRIP_OFFSETS, offset_value(variant, offsets));
}
let mut out = write(&TiffFile {
order,
variant,
ifds,
});
out.resize(base, 0);
for (_, strips) in pages {
for s in strips {
out.extend_from_slice(s);
}
}
out
}
fn write_blocks(
order: ByteOrder,
variant: Variant,
ifd: &Ifd,
blocks: &[Vec<u8>],
offset_tag: u16,
bytecount_tag: u16,
) -> Vec<u8> {
let counts: Vec<u32> = blocks.iter().map(|s| s.len() as u32).collect();
let mut ifd = ifd.clone();
ifd.set(bytecount_tag, Value::Long(counts));
ifd.set(offset_tag, offset_value(variant, vec![0; blocks.len()]));
let base = even(
write(&TiffFile {
order,
variant,
ifds: vec![ifd.clone()],
})
.len(),
);
let mut offsets = Vec::with_capacity(blocks.len());
let mut cursor = base;
for s in blocks {
offsets.push(cursor as u64);
cursor += s.len();
}
ifd.set(offset_tag, offset_value(variant, offsets));
let mut out = write(&TiffFile {
order,
variant,
ifds: vec![ifd],
});
out.resize(base, 0); for s in blocks {
out.extend_from_slice(s);
}
out
}