use alloc::borrow::Cow;
use enough::Stop;
use zenpixels::PixelDescriptor;
use crate::cost::OutputInfo;
use crate::sink::SinkError;
use crate::traits::{AnimationFrameDecoder, Decode, DecodeJob};
mod exif;
mod icc;
pub use exif::parse_exif_orientation;
pub use icc::descriptor_for_decoded_pixels_v2;
#[allow(deprecated)]
pub use icc::{
IccMatchTolerance, descriptor_for_decoded_pixels, icc_profile_is_srgb, identify_well_known_icc,
};
pub fn copy_decode_to_sink<'a, J>(
job: J,
data: Cow<'a, [u8]>,
sink: &mut dyn crate::DecodeRowSink,
preferred: &[PixelDescriptor],
wrap_sink_error: fn(SinkError) -> J::Error,
) -> Result<OutputInfo, J::Error>
where
J: DecodeJob<'a>,
{
let dec = job.decoder(data, preferred)?;
let output = dec.decode()?;
let ps = output.pixels();
let desc = ps.descriptor();
let w = ps.width();
let h = ps.rows();
sink.begin(w, h, desc).map_err(wrap_sink_error)?;
let mut dst = sink
.provide_next_buffer(0, h, w, desc)
.map_err(wrap_sink_error)?;
for row in 0..h {
dst.row_mut(row).copy_from_slice(ps.row(row));
}
drop(dst);
sink.finish().map_err(wrap_sink_error)?;
let info = output.info();
Ok(OutputInfo::full_decode(info.width, info.height, desc))
}
pub fn copy_frame_to_sink<D: AnimationFrameDecoder>(
decoder: &mut D,
stop: Option<&dyn Stop>,
sink: &mut dyn crate::DecodeRowSink,
) -> Result<Option<OutputInfo>, D::Error> {
let frame = match decoder.render_next_frame(stop)? {
Some(f) => f,
None => return Ok(None),
};
let ps = frame.pixels();
let desc = ps.descriptor();
let w = ps.width();
let h = ps.rows();
sink.begin(w, h, desc).map_err(D::wrap_sink_error)?;
let mut dst = sink
.provide_next_buffer(0, h, w, desc)
.map_err(D::wrap_sink_error)?;
for row in 0..h {
dst.row_mut(row).copy_from_slice(ps.row(row));
}
drop(dst);
sink.finish().map_err(D::wrap_sink_error)?;
Ok(Some(OutputInfo::full_decode(w, h, desc)))
}