j2k-native 0.7.2

Pure-Rust JPEG 2000 and HTJ2K codec engine for j2k
Documentation
//! The channel definition box (cdef), defined in I.5.3.6.

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),
        }
    }
}