numcodecs_jpeg2000/ffi/
image.rs
1use std::ptr::NonNull;
6
7use super::{codec::Decoder, stream::DecodeStream, Jpeg2000Element, Jpeg2000Error};
8
9pub struct Image {
10 image: NonNull<openjpeg_sys::opj_image_t>,
11}
12
13impl Drop for Image {
14 fn drop(&mut self) {
15 unsafe {
16 openjpeg_sys::opj_image_destroy(self.image.as_ptr());
17 }
18 }
19}
20
21impl Image {
22 pub fn from_header(
23 stream: &mut DecodeStream,
24 decoder: &mut Decoder,
25 ) -> Result<Self, Jpeg2000Error> {
26 let mut image = std::ptr::null_mut();
27
28 if unsafe { openjpeg_sys::opj_read_header(stream.as_raw(), decoder.as_raw(), &mut image) }
29 != 1
30 {
31 return Err(Jpeg2000Error::InvalidMainHeader);
32 }
33
34 let image = NonNull::new(image).ok_or(Jpeg2000Error::InvalidMainHeader)?;
35
36 Ok(Self { image })
37 }
38
39 pub fn from_gray_data<T: Jpeg2000Element>(
40 data: impl IntoIterator<Item = T>,
41 width: u32,
42 height: u32,
43 ) -> Result<Self, Jpeg2000Error> {
44 let mut image_params = openjpeg_sys::opj_image_cmptparm_t {
45 dx: 1,
46 dy: 1,
47 w: width,
48 h: height,
49 x0: 0,
50 y0: 0,
51 prec: T::NBITS,
52 bpp: T::NBITS,
53 sgnd: u32::from(T::SIGNED),
54 };
55
56 let image = NonNull::new(unsafe {
57 openjpeg_sys::opj_image_create(
58 1,
59 &mut image_params,
60 openjpeg_sys::OPJ_COLOR_SPACE::OPJ_CLRSPC_GRAY,
61 )
62 })
63 .ok_or(Jpeg2000Error::ImageCreateError)?;
64
65 unsafe {
66 (*image.as_ptr()).x0 = 0;
67 (*image.as_ptr()).y0 = 0;
68 (*image.as_ptr()).x1 = width;
69 (*image.as_ptr()).y1 = height;
70 }
71
72 unsafe {
73 let mut idata = (*(*image.as_ptr()).comps).data;
74 for d in data {
75 *idata = d.into_i32().map_err(|_| Jpeg2000Error::DataOutOfRange)?;
76 idata = idata.add(1);
77 }
78 }
79
80 Ok(Self { image })
81 }
82
83 #[allow(clippy::needless_pass_by_ref_mut)]
84 pub fn as_raw(&mut self) -> *mut openjpeg_sys::opj_image_t {
85 self.image.as_ptr()
86 }
87
88 pub fn width(&self) -> u32 {
89 unsafe { (*self.image.as_ptr()).x1 - (*self.image.as_ptr()).x0 }
90 }
91
92 pub fn height(&self) -> u32 {
93 unsafe { (*self.image.as_ptr()).y1 - (*self.image.as_ptr()).y0 }
94 }
95
96 pub fn components(&self) -> &[openjpeg_sys::opj_image_comp_t] {
97 let comps_len = unsafe { (*self.image.as_ptr()).numcomps };
98 unsafe { std::slice::from_raw_parts((*self.image.as_ptr()).comps, comps_len as usize) }
99 }
100}