use crate::{
J2kPacketizationProgressionOrder, MAX_JPEG2000_PART1_COMPONENTS,
MAX_JPEG2000_PART1_SAMPLE_BIT_DEPTH,
};
mod input_error;
pub use self::input_error::J2kResidentEncodeInputError;
#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct J2kResidentEncodeInput {
width: u32,
height: u32,
num_components: u16,
bit_depth: u8,
signed: bool,
}
impl J2kResidentEncodeInput {
pub fn new(
width: u32,
height: u32,
num_components: u16,
bit_depth: u8,
signed: bool,
) -> Result<Self, J2kResidentEncodeInputError> {
if width == 0 || height == 0 {
return Err(J2kResidentEncodeInputError::EmptyGeometry { width, height });
}
if num_components == 0 || num_components > MAX_JPEG2000_PART1_COMPONENTS {
return Err(J2kResidentEncodeInputError::ComponentCountOutOfRange { num_components });
}
if bit_depth == 0 || bit_depth > MAX_JPEG2000_PART1_SAMPLE_BIT_DEPTH {
return Err(J2kResidentEncodeInputError::PrecisionOutOfRange { bit_depth });
}
let width_usize = usize::try_from(width)
.map_err(|_| J2kResidentEncodeInputError::AddressSpaceOverflow)?;
let height_usize = usize::try_from(height)
.map_err(|_| J2kResidentEncodeInputError::AddressSpaceOverflow)?;
let bytes_per_sample = usize::from(bit_depth).div_ceil(8);
width_usize
.checked_mul(height_usize)
.and_then(|pixels| pixels.checked_mul(usize::from(num_components)))
.and_then(|samples| samples.checked_mul(bytes_per_sample))
.ok_or(J2kResidentEncodeInputError::AddressSpaceOverflow)?;
Ok(Self {
width,
height,
num_components,
bit_depth,
signed,
})
}
#[must_use]
pub const fn width(self) -> u32 {
self.width
}
#[must_use]
pub const fn height(self) -> u32 {
self.height
}
#[must_use]
pub const fn num_components(self) -> u16 {
self.num_components
}
#[must_use]
pub const fn bit_depth(self) -> u8 {
self.bit_depth
}
#[must_use]
pub const fn signed(self) -> bool {
self.signed
}
}
#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct J2kResidentHtj2kTileEncodeJob<'a> {
pub input: J2kResidentEncodeInput,
pub num_decomposition_levels: u8,
pub reversible: bool,
pub use_mct: bool,
pub guard_bits: u8,
pub code_block_width: u32,
pub code_block_height: u32,
pub progression_order: J2kPacketizationProgressionOrder,
pub component_sampling: &'a [(u8, u8)],
pub quantization_steps: &'a [(u16, u16)],
}
impl J2kResidentHtj2kTileEncodeJob<'_> {
#[must_use]
pub const fn width(self) -> u32 {
self.input.width()
}
#[must_use]
pub const fn height(self) -> u32 {
self.input.height()
}
#[must_use]
pub const fn num_components(self) -> u16 {
self.input.num_components()
}
#[must_use]
pub const fn bit_depth(self) -> u8 {
self.input.bit_depth()
}
#[must_use]
pub const fn signed(self) -> bool {
self.input.signed()
}
}
#[cfg(test)]
mod tests;