use std::sync::Arc;
use jxr_core::{ImageInfo, JxrError};
use jxr_native::{ParsedCodestream, image_info, parse_codestream};
use crate::{JxrDecoder, map_native_error};
#[derive(Clone, Debug)]
pub struct PreparedJxr {
inner: Arc<PreparedJxrInner>,
}
#[derive(Debug)]
struct PreparedJxrInner {
bytes: Arc<[u8]>,
parsed: ParsedCodestream,
info: ImageInfo,
}
impl PreparedJxr {
pub fn from_arc(bytes: Arc<[u8]>) -> Result<Self, JxrError> {
let parsed = parse_codestream(&bytes).map_err(map_native_error)?;
let info = image_info(&parsed).map_err(map_native_error)?;
Ok(Self {
inner: Arc::new(PreparedJxrInner {
bytes,
parsed,
info,
}),
})
}
#[must_use]
pub fn info(&self) -> &ImageInfo {
&self.inner.info
}
#[must_use]
pub fn bytes(&self) -> &Arc<[u8]> {
&self.inner.bytes
}
#[must_use]
pub fn codestream(&self) -> &[u8] {
&self.inner.bytes[self.inner.parsed.codestream_range.clone()]
}
#[must_use]
pub fn separate_alpha_codestream(&self) -> Option<&[u8]> {
self.inner
.parsed
.annex_a
.as_ref()?
.alpha_range
.clone()
.map(|range| &self.inner.bytes[range])
}
#[must_use]
pub fn icc_profile(&self) -> Option<&[u8]> {
let range = self.inner.info.metadata.icc_profile?;
range
.end()
.and_then(|end| self.inner.bytes.get(range.offset..end))
}
#[must_use]
pub fn decoder(&self) -> JxrDecoder<'_> {
JxrDecoder::new(&self.inner.bytes, &self.inner.parsed, &self.inner.info)
}
}