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