use crate::error::{Jp2Error, Result};
use crate::stream::{SliceReader, VecWriter};
pub struct HtDecoder {
pub mel_run: u32,
pub mel_remaining: u32,
pub vlc_bits: u64,
pub vlc_pos: u32,
pub magsgn_bits: u64,
pub magsgn_pos: u32,
}
impl HtDecoder {
pub fn new() -> Self {
Self {
mel_run: 0,
mel_remaining: 0,
vlc_bits: 0,
vlc_pos: 0,
magsgn_bits: 0,
magsgn_pos: 0,
}
}
}
impl Default for HtDecoder {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CapMarker {
pub pcap: u32,
pub ccap: Vec<u16>,
}
pub fn ht_decode_cblk(
_data: &[u8],
_width: u32,
_height: u32,
_num_passes: u32,
) -> std::result::Result<Vec<i32>, String> {
Err("HTJ2K decoding not yet implemented".to_string())
}
pub fn is_htj2k(cblk_style: u8) -> bool {
(cblk_style & 0x40) != 0
}
pub fn read_cap(reader: &mut SliceReader) -> Result<CapMarker> {
let lcap = reader.read_u16_be()? as usize;
if lcap < 6 {
return Err(Jp2Error::InvalidData(
"CAP marker segment too short".to_string(),
));
}
let pcap = reader.read_u32_be()?;
let num_ccap = pcap.count_ones() as usize;
let expected_len = 6 + 2 * num_ccap;
if lcap != expected_len {
return Err(Jp2Error::InvalidData(format!(
"CAP marker length mismatch: Lcap={lcap}, expected={expected_len}"
)));
}
let mut ccap = Vec::with_capacity(num_ccap);
for _ in 0..num_ccap {
ccap.push(reader.read_u16_be()?);
}
Ok(CapMarker { pcap, ccap })
}
pub fn write_cap(writer: &mut VecWriter, cap: &CapMarker) {
let num_ccap = cap.pcap.count_ones() as usize;
let lcap = 6 + 2 * num_ccap;
writer.write_u16_be(lcap as u16);
writer.write_u32_be(cap.pcap);
for &c in &cap.ccap {
writer.write_u16_be(c);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ht_decoder_default() {
let dec = HtDecoder::new();
assert_eq!(dec.mel_run, 0);
assert_eq!(dec.vlc_bits, 0);
assert_eq!(dec.magsgn_bits, 0);
}
#[test]
fn cap_marker_basic() {
let cap = CapMarker {
pcap: 0x0001_0000, ccap: vec![0x0020],
};
assert_eq!(cap.pcap.count_ones(), 1);
assert_eq!(cap.ccap.len(), 1);
}
}