pub(crate) mod data;
mod jbrd;
mod writer;
pub use jbrd::decode_jbrd;
pub use writer::write_jpeg;
const ICC_CHUNK_PAYLOAD: usize = 65519;
pub(crate) fn fill_metadata(
jpeg: &mut data::JpegData,
exif: Option<Vec<u8>>,
xmp: Option<Vec<u8>>,
icc: Option<&[u8]>,
) {
use data::AppMarkerType;
let icc_total = jpeg
.app_marker_type
.iter()
.zip(jpeg.app_data.iter())
.filter(|(t, d)| **t == AppMarkerType::Icc && d.is_empty())
.count();
let mut exif = exif;
let mut xmp = xmp;
let mut icc_chunk = 0usize;
for i in 0..jpeg.app_data.len() {
if !jpeg.app_data[i].is_empty() {
continue;
}
match jpeg.app_marker_type[i] {
AppMarkerType::Exif => {
if let Some(tiff) = exif.take() {
let mut v = b"Exif\0\0".to_vec();
v.extend_from_slice(&tiff);
jpeg.app_data[i] = v;
}
}
AppMarkerType::Xmp => {
if let Some(xml) = xmp.take() {
let mut v = b"http://ns.adobe.com/xap/1.0/\0".to_vec();
v.extend_from_slice(&xml);
jpeg.app_data[i] = v;
}
}
AppMarkerType::Icc => {
if let Some(icc) = icc {
let start = icc_chunk * ICC_CHUNK_PAYLOAD;
if start < icc.len() && icc_total <= u8::MAX as usize {
let end = (start + ICC_CHUNK_PAYLOAD).min(icc.len());
let mut v = b"ICC_PROFILE\0".to_vec();
v.push((icc_chunk + 1) as u8);
v.push(icc_total as u8);
v.extend_from_slice(&icc[start..end]);
jpeg.app_data[i] = v;
}
}
icc_chunk += 1;
}
_ => {}
}
}
}