grib/decoder/jpeg2000/
ext.rsuse std::{
os::raw::c_void,
ptr::{self, NonNull},
};
use openjpeg_sys as opj;
use opj::OPJ_CODEC_FORMAT;
use crate::decoder::jpeg2000::Jpeg2000CodeStreamDecodeError;
pub(crate) struct Stream(pub(crate) *mut opj::opj_stream_t);
impl Drop for Stream {
fn drop(&mut self) {
unsafe {
opj::opj_stream_destroy(self.0);
}
}
}
impl Stream {
pub(crate) fn from_bytes(buf: &[u8]) -> Result<Self, Jpeg2000CodeStreamDecodeError> {
#[derive(Debug)]
struct SliceWithOffset<'a> {
buf: &'a [u8],
offset: usize,
}
unsafe extern "C" fn opj_stream_free_user_data_fn(p_user_data: *mut c_void) {
drop(Box::from_raw(p_user_data as *mut SliceWithOffset))
}
unsafe extern "C" fn opj_stream_read_fn(
p_buffer: *mut c_void,
p_nb_bytes: usize,
p_user_data: *mut c_void,
) -> usize {
if p_buffer.is_null() {
return 0;
}
let user_data = p_user_data as *mut SliceWithOffset;
let len = (*user_data).buf.len();
let offset = (*user_data).offset;
let bytes_left = len - offset;
let bytes_read = std::cmp::min(bytes_left, p_nb_bytes);
let slice = &(*user_data).buf[offset..offset + bytes_read];
std::ptr::copy_nonoverlapping(slice.as_ptr(), p_buffer as *mut u8, bytes_read);
(*user_data).offset += bytes_read;
bytes_read
}
let buf_len = buf.len();
let user_data = Box::new(SliceWithOffset { buf, offset: 0 });
let ptr = unsafe {
let jp2_stream = opj::opj_stream_default_create(1);
opj::opj_stream_set_read_function(jp2_stream, Some(opj_stream_read_fn));
opj::opj_stream_set_user_data_length(jp2_stream, buf_len as u64);
opj::opj_stream_set_user_data(
jp2_stream,
Box::into_raw(user_data) as *mut c_void,
Some(opj_stream_free_user_data_fn),
);
jp2_stream
};
Ok(Self(ptr))
}
}
pub(crate) struct Codec(pub(crate) NonNull<opj::opj_codec_t>);
impl Drop for Codec {
fn drop(&mut self) {
unsafe {
opj::opj_destroy_codec(self.0.as_ptr());
}
}
}
impl Codec {
pub(crate) fn j2k() -> Result<Self, Jpeg2000CodeStreamDecodeError> {
Self::create(OPJ_CODEC_FORMAT::OPJ_CODEC_J2K)
}
pub(crate) fn create(format: OPJ_CODEC_FORMAT) -> Result<Self, Jpeg2000CodeStreamDecodeError> {
NonNull::new(unsafe { opj::opj_create_decompress(format) })
.map(Self)
.ok_or(Jpeg2000CodeStreamDecodeError::DecoderSetupError)
}
}
#[derive(Debug)]
pub(crate) struct Image(pub(crate) *mut opj::opj_image_t);
impl Drop for Image {
fn drop(&mut self) {
unsafe {
opj::opj_image_destroy(self.0);
}
}
}
impl Image {
pub(crate) fn new() -> Self {
Image(ptr::null_mut())
}
pub(crate) fn width(&self) -> u32 {
unsafe { (*self.0).x1 - (*self.0).x0 }
}
pub(crate) fn height(&self) -> u32 {
unsafe { (*self.0).y1 - (*self.0).y0 }
}
pub(crate) fn num_components(&self) -> u32 {
unsafe { (*self.0).numcomps }
}
pub(crate) fn components(&self) -> &[opj::opj_image_comp_t] {
let comps_len = self.num_components();
unsafe { std::slice::from_raw_parts((*self.0).comps, comps_len as usize) }
}
pub(crate) fn factor(&self) -> u32 {
unsafe { (*(*self.0).comps).factor }
}
}
pub(crate) fn value_for_discard_level(u: u32, discard_level: u32) -> u32 {
let div = 1 << discard_level;
let quot = u / div;
let rem = u % div;
if rem > 0 {
quot + 1
} else {
quot
}
}