use std::ptr::NonNull;
use openjpeg_sys as opj;
use crate::DecodeError;
#[derive(Debug)]
pub(crate) struct Image(NonNull<opj::opj_image_t>);
impl Drop for Image {
fn drop(&mut self) {
unsafe {
opj::opj_image_destroy(self.0.as_ptr());
}
}
}
impl Image {
pub(crate) fn new(ptr: *mut opj::opj_image_t) -> Result<Self, DecodeError> {
let img = NonNull::new(ptr)
.ok_or_else(|| DecodeError::from("initialization of the JPEG 2000 image failed"))?;
Ok(Self(img))
}
fn inner(&self) -> &opj::opj_image_t {
unsafe { &(*self.0.as_ptr()) }
}
pub(crate) fn components(&self) -> &[ImageComponent] {
let img = self.inner();
let numcomps = img.numcomps;
unsafe { std::slice::from_raw_parts(img.comps as *mut ImageComponent, numcomps as usize) }
}
pub(crate) fn try_into_iter(self) -> Result<ImageIntoIter, DecodeError> {
let slice = if let [comp_gray] = self.components() {
comp_gray.data()
} else {
return Err(DecodeError::from(
"unexpected non-gray-scale image components",
));
};
let data = slice.as_ptr();
let len = slice.len();
Ok(ImageIntoIter {
inner: self,
data,
len,
index: 0,
})
}
pub(crate) fn as_ptr(&self) -> *mut opj::opj_image_t {
self.0.as_ptr()
}
}
pub(crate) struct ImageComponent(opj::opj_image_comp_t);
impl ImageComponent {
pub(crate) fn data(&self) -> &[i32] {
let len = (self.0.w * self.0.h) as usize;
unsafe { std::slice::from_raw_parts(self.0.data, len) }
}
}
pub(crate) struct ImageIntoIter {
#[allow(dead_code)]
inner: Image,
data: *const i32,
len: usize,
index: usize,
}
impl Iterator for ImageIntoIter {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.len {
let value = unsafe { *self.data.add(self.index) };
self.index += 1;
Some(value)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.len - self.index;
(remaining, Some(remaining))
}
}