use bon::Builder;
use crate::error::SeiError;
#[derive(Debug, Clone, Copy, Builder, PartialEq, Eq, Default)]
pub struct SeiSettings {
#[builder(default)]
pub bit_depth: BitDepth,
#[builder(default)]
pub white_mode: WhiteMode,
#[builder(default)]
pub padding: Padding,
#[builder(default)]
pub stacking_mode: StackingMode,
#[builder(default)]
pub unused_bits: u8,
}
impl SeiSettings {
pub fn parse(settings: u8) -> Result<Self, SeiError> {
let bit_depth = settings & 0b11;
let white_mode = (settings >> 2) & 0b1;
let padding = (settings >> 3) & 0b1;
let stacking_mode = (settings >> 4) & 0b11;
let unused_bits = (settings >> 6) & 0b11;
Ok(SeiSettings {
bit_depth: BitDepth::parse(bit_depth)?,
white_mode: WhiteMode::parse(white_mode),
stacking_mode: StackingMode::parse(stacking_mode)?,
padding: Padding::parse(padding),
unused_bits,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum BitDepth {
#[default]
OneBit = 0b00,
TwoBits = 0b01,
FourBits = 0b10,
}
impl BitDepth {
pub(crate) const fn bits(self) -> u32 {
match self {
BitDepth::OneBit => 1,
BitDepth::TwoBits => 2,
BitDepth::FourBits => 4,
}
}
pub(crate) const fn parse(value: u8) -> Result<Self, SeiError> {
Ok(match value {
0 => BitDepth::OneBit,
_ => return Err(SeiError::UnsupportedBitDepth),
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum WhiteMode {
#[default]
Zeros = 0,
Ones = 1,
}
impl WhiteMode {
pub(crate) const fn parse(value: u8) -> Self {
match value {
0 => WhiteMode::Zeros,
1 => WhiteMode::Ones,
_ => unreachable!(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Padding {
#[default]
Padding = 0,
NoPadding = 1,
}
impl Padding {
pub(crate) const fn parse(value: u8) -> Self {
match value {
0 => Padding::Padding,
1 => Padding::NoPadding,
_ => unreachable!(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum StackingMode {
#[default]
Opaque = 0b00,
WhiteTransparent = 0b01,
BlackTransparent = 0b10,
}
impl StackingMode {
pub(crate) const fn parse(value: u8) -> Result<Self, SeiError> {
Ok(match value {
0 => StackingMode::Opaque,
1 => StackingMode::WhiteTransparent,
2 => StackingMode::BlackTransparent,
_ => return Err(SeiError::UnsupportedTransparency),
})
}
}
#[test]
fn test_sei_settings() {
let settings: u8 = 0b0010_1100;
let parsed = SeiSettings::parse(settings).unwrap();
assert_eq!(
parsed,
SeiSettings::builder()
.bit_depth(BitDepth::OneBit)
.white_mode(WhiteMode::Ones)
.padding(Padding::NoPadding)
.stacking_mode(StackingMode::BlackTransparent)
.build()
);
}