use crate::bit_reader::BitWriter;
use crate::object::Dict;
use crate::object::Stream;
use crate::object::dict::keys::JBIG2_GLOBALS;
use crate::object::stream::{FilterResult, ImageColorSpace, ImageData, ImageDecodeParams};
use alloc::borrow::Cow;
use alloc::vec;
use alloc::vec::Vec;
use core::iter;
pub(crate) fn decode(
data: &[u8],
params: &Dict<'_>,
image_params: &ImageDecodeParams,
) -> Option<FilterResult<'static>> {
let globals = params
.get::<Stream<'_>>(JBIG2_GLOBALS)
.and_then(|g| g.decoded().ok());
let image = hayro_jbig2::Image::new_embedded(data, globals.as_deref()).ok()?;
let (decoded, bpc) = if image_params.is_indexed {
let row_bytes = (image.width() as usize).div_ceil(8);
let mut packed = vec![0_u8; row_bytes * image.height() as usize];
struct BitWriterDecoder<'a> {
writer: BitWriter<'a>,
}
impl hayro_jbig2::Decoder for BitWriterDecoder<'_> {
fn push_pixel(&mut self, black: bool) {
let _ = self.writer.write(u32::from(!black));
}
fn push_pixel_chunk(&mut self, black: bool, chunk_count: u32) {
let byte_value = if black { 0x00 } else { 0xFF };
let _ = self.writer.fill_bytes(byte_value, chunk_count as usize);
}
fn next_line(&mut self) {
self.writer.align();
}
}
let writer = BitWriter::new(&mut packed, 1)?;
let mut decoder = BitWriterDecoder { writer };
image.decode(&mut decoder).ok()?;
(packed, 1)
} else {
struct Luma8Decoder {
output: Vec<u8>,
}
impl hayro_jbig2::Decoder for Luma8Decoder {
fn push_pixel(&mut self, black: bool) {
self.output.push(if black { 0x00 } else { 0xFF });
}
fn push_pixel_chunk(&mut self, black: bool, chunk_count: u32) {
let byte = if black { 0x00 } else { 0xFF };
self.output
.extend(iter::repeat_n(byte, chunk_count as usize * 8));
}
fn next_line(&mut self) {}
}
let mut decoder = Luma8Decoder { output: Vec::new() };
image.decode(&mut decoder).ok()?;
(decoder.output, 8)
};
Some(FilterResult {
data: Cow::Owned(decoded),
image_data: Some(ImageData {
alpha: None,
color_space: Some(ImageColorSpace::Gray),
bits_per_component: bpc,
width: image.width(),
height: image.height(),
}),
})
}