use alloc::vec::Vec;
use crate::error::{bail, FormatError, Result};
use crate::jp2::{allocation::Jp2AllocationBudget, ImageBoxes};
use crate::reader::BitReader;
pub(super) fn parse(
boxes: &mut ImageBoxes,
data: &[u8],
budget: &mut Jp2AllocationBudget,
) -> Result<()> {
let mut reader = BitReader::new(data);
let count = usize::from(reader.read_u16().ok_or(FormatError::InvalidBox)?);
if count == 0 {
bail!(FormatError::InvalidBox);
}
let mut definitions = budget.try_vec(count, "JP2 channel definitions")?;
for _ in 0..count {
let channel_index = reader.read_u16().ok_or(FormatError::InvalidBox)?;
let channel_type = reader.read_u16().ok_or(FormatError::InvalidBox)?;
let association = reader.read_u16().ok_or(FormatError::InvalidBox)?;
definitions.push(ChannelDefinition {
channel_index,
channel_type: ChannelType::from_raw(channel_type),
association: ChannelAssociation::from_raw(association),
});
}
let replaced = boxes.channel_definition.replace(ChannelDefinitionBox {
channel_definitions: definitions,
});
if let Some(replaced) = replaced {
budget.release_vec(&replaced.channel_definitions)?;
}
Ok(())
}
#[derive(Debug)]
pub(crate) struct ChannelDefinitionBox {
pub(crate) channel_definitions: Vec<ChannelDefinition>,
}
#[derive(Debug, Clone)]
pub(crate) struct ChannelDefinition {
pub(crate) channel_index: u16,
pub(crate) channel_type: ChannelType,
pub(crate) association: ChannelAssociation,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum ChannelType {
Colour,
Opacity,
PremultipliedOpacity,
Unspecified,
Unknown(u16),
}
impl ChannelType {
fn from_raw(value: u16) -> Self {
match value {
0 => Self::Colour,
1 => Self::Opacity,
2 => Self::PremultipliedOpacity,
u16::MAX => Self::Unspecified,
value => Self::Unknown(value),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum ChannelAssociation {
WholeImage,
Colour(u16),
Unspecified,
}
impl ChannelAssociation {
fn from_raw(value: u16) -> Self {
match value {
0 => Self::WholeImage,
u16::MAX => Self::Unspecified,
v => Self::Colour(v),
}
}
}