1#![cfg_attr(not(feature = "std"), no_std)]
15#![forbid(unsafe_code)]
16#![allow(missing_docs)]
17
18extern crate alloc;
19
20use alloc::vec::Vec;
21
22use crate::arithmetic_decoder::ArithmeticDecoderContext;
23
24#[derive(Default)]
26pub struct DecoderContext {
27 pub(crate) page_state: PageState,
28 pub(crate) scratch_buffers: ScratchBuffers,
29 pub(crate) page_bitmap: Bitmap,
30}
31
32#[derive(Default)]
33pub(crate) struct ScratchBuffers {
34 pub(crate) contexts: Vec<ArithmeticDecoderContext>,
35}
36
37pub trait Decoder {
39 fn push_pixel(&mut self, black: bool);
41 fn push_pixel_chunk(&mut self, black: bool, chunk_count: u32);
50 fn next_line(&mut self);
52}
53
54#[cfg(feature = "image")]
55pub mod integration;
56
57mod arithmetic_decoder;
58mod bitmap;
59mod decode;
60mod error;
61mod file;
62mod gray_scale;
63mod huffman_table;
64mod integer_decoder;
65mod lazy;
66mod page_info;
67mod reader;
68mod segment;
69mod simd;
70mod symbol_id_decoder;
71
72use error::bail;
73pub use error::{
74 DecodeError, FormatError, HuffmanError, OverflowError, ParseError, RegionError, Result,
75 SegmentError, SymbolError, TemplateError,
76};
77
78use crate::file::parse_segments_sequential;
79use bitmap::Bitmap;
80use decode::CombinationOperator;
81use decode::generic;
82use decode::generic_refinement;
83use decode::halftone;
84use decode::pattern;
85use decode::pattern::PatternDictionary;
86use decode::symbol;
87use decode::symbol::SymbolDictionary;
88use decode::text;
89use file::parse_file;
90use huffman_table::{HuffmanTable, StandardHuffmanTables};
91use page_info::{PageInformation, parse_page_information};
92use reader::Reader;
93use segment::SegmentType;
94
95pub struct Image<'a> {
97 segments: Vec<segment::Segment<'a>>,
99 width: u32,
101 height: u32,
103 height_from_stripes: Option<u32>,
105}
106
107impl<'a> Image<'a> {
108 pub fn new(data: &'a [u8]) -> Result<Self> {
113 let file = parse_file(data)?;
114 Self::from_segments(file.segments)
115 }
116
117 pub fn new_embedded(data: &'a [u8], globals: Option<&'a [u8]>) -> Result<Self> {
122 let mut segments = Vec::new();
123 if let Some(globals_data) = globals {
124 let mut reader = Reader::new(globals_data);
125 parse_segments_sequential(&mut reader, &mut segments)?;
126 };
127
128 let mut reader = Reader::new(data);
129 parse_segments_sequential(&mut reader, &mut segments)?;
130
131 segments.sort_by_key(|seg| seg.header.segment_number);
132
133 Self::from_segments(segments)
134 }
135
136 fn from_segments(segments: Vec<segment::Segment<'a>>) -> Result<Self> {
137 let height_from_stripes = segments
139 .iter()
140 .filter(|seg| seg.header.segment_type == SegmentType::EndOfStripe)
141 .filter_map(|seg| u32::from_be_bytes(seg.data.try_into().ok()?).checked_add(1))
142 .max();
143
144 let page_info_seg = segments
146 .iter()
147 .find(|s| s.header.segment_type == SegmentType::PageInformation)
148 .ok_or(FormatError::MissingPageInfo)?;
149
150 let mut reader = Reader::new(page_info_seg.data);
151 let page_info = parse_page_information(&mut reader)?;
152
153 let height = if page_info.height == 0xFFFF_FFFF {
157 height_from_stripes.ok_or(FormatError::UnknownPageHeight)?
158 } else {
159 page_info.height
160 };
161
162 if page_info.width == 0 || height == 0 {
163 bail!(FormatError::EmptyPage);
164 }
165
166 Ok(Self {
167 segments,
168 width: page_info.width,
169 height,
170 height_from_stripes,
171 })
172 }
173
174 pub fn width(&self) -> u32 {
176 self.width
177 }
178
179 pub fn height(&self) -> u32 {
181 self.height
182 }
183
184 pub fn decode<D: Decoder>(&self, decoder: &mut D) -> Result<()> {
186 let mut ctx = DecoderContext::default();
187
188 self.decode_with(decoder, &mut ctx)
189 }
190
191 pub fn decode_with<D: Decoder>(&self, decoder: &mut D, ctx: &mut DecoderContext) -> Result<()> {
196 decode_segments(&self.segments, self.height_from_stripes, ctx)?;
197 emit_bitmap(&ctx.page_bitmap, decoder);
198
199 Ok(())
200 }
201}
202
203fn emit_bitmap<D: Decoder>(bitmap: &Bitmap, decoder: &mut D) {
204 let width = bitmap.width;
205 let bytes_per_row = width.div_ceil(8) as usize;
206
207 for row in bitmap.data.chunks_exact(bitmap.stride as usize) {
208 let mut x = 0_u32;
209 let mut chunk_byte: Option<u8> = None;
210 let mut chunk_count = 0_u32;
211
212 let bytes = row.iter().flat_map(|w| w.to_be_bytes()).take(bytes_per_row);
213
214 for byte in bytes {
215 let remaining = width - x;
216
217 if remaining >= 8 && (byte == 0x00 || byte == 0xFF) {
218 if chunk_byte == Some(byte) {
220 chunk_count += 1;
221 x += 8;
222 continue;
223 }
224
225 if let Some(b) = chunk_byte {
227 decoder.push_pixel_chunk(b == 0xFF, chunk_count);
228 }
229
230 chunk_byte = Some(byte);
231 chunk_count = 1;
232 x += 8;
233
234 continue;
235 }
236
237 if let Some(b) = chunk_byte.take() {
239 decoder.push_pixel_chunk(b == 0xFF, chunk_count);
240 chunk_count = 0;
241 }
242
243 let count = remaining.min(8);
245 for i in 0..count {
246 decoder.push_pixel((byte >> (7 - i)) & 1 != 0);
247 }
248 x += count;
249 }
250
251 if let Some(b) = chunk_byte {
253 decoder.push_pixel_chunk(b == 0xFF, chunk_count);
254 }
255
256 decoder.next_line();
257 }
258}
259
260fn decode_segments(
261 segments: &[segment::Segment<'_>],
262 height_from_stripes: Option<u32>,
263 decoder_ctx: &mut DecoderContext,
264) -> Result<()> {
265 if let Some(page_info) = segments
267 .iter()
268 .find(|s| s.header.segment_type == SegmentType::PageInformation)
269 {
270 let mut reader = Reader::new(page_info.data);
271 init_page(
272 &mut reader,
273 height_from_stripes,
274 &mut decoder_ctx.page_state,
275 &mut decoder_ctx.page_bitmap,
276 )?;
277 } else {
278 bail!(FormatError::MissingPageInfo);
279 }
280
281 let page_bitmap = &mut decoder_ctx.page_bitmap;
282 let page_state = &mut decoder_ctx.page_state;
283 let scratch_buffers = &mut decoder_ctx.scratch_buffers;
284
285 for seg in segments {
287 let mut reader = Reader::new(seg.data);
288
289 match seg.header.segment_type {
290 SegmentType::PageInformation => {
291 }
293 SegmentType::ImmediateGenericRegion | SegmentType::ImmediateLosslessGenericRegion => {
294 let had_unknown_length = seg.header.data_length.is_none();
295 let header = generic::parse(&mut reader, had_unknown_length)?;
296
297 if page_state.can_decode_directly(page_bitmap, &header.region_info, false) {
298 generic::decode_into(&header, page_bitmap, scratch_buffers)?;
299 } else {
300 let region = generic::decode(&header, scratch_buffers)?;
301 page_bitmap.combine(
302 ®ion.bitmap,
303 region.bitmap.x_location as i32,
304 region.bitmap.y_location as i32,
305 region.combination_operator,
306 );
307 }
308 page_state.page_pristine = false;
309 }
310 SegmentType::IntermediateGenericRegion => {
311 let header = generic::parse(&mut reader, false)?;
313 let region = generic::decode(&header, scratch_buffers)?;
314 page_state.store_region(seg.header.segment_number, region.bitmap);
315 }
316 SegmentType::PatternDictionary => {
317 let header = pattern::parse(&mut reader)?;
318 let dictionary = pattern::decode(&header, scratch_buffers)?;
319 page_state.store_pattern_dictionary(seg.header.segment_number, dictionary);
320 }
321 SegmentType::SymbolDictionary => {
322 let input_symbols: Vec<&Bitmap> = seg
326 .header
327 .referred_to_segments
328 .iter()
329 .filter_map(|&num| page_state.get_symbol_dictionary(num))
330 .flat_map(|dict| dict.exported_symbols.iter())
331 .collect();
332
333 let referred_tables: Vec<HuffmanTable> = seg
335 .header
336 .referred_to_segments
337 .iter()
338 .filter_map(|&num| page_state.get_huffman_table(num))
339 .cloned()
340 .collect();
341
342 let retained_contexts = seg
344 .header
345 .referred_to_segments
346 .last()
347 .and_then(|&num| page_state.get_symbol_dictionary(num))
348 .and_then(|dict| dict.retained_contexts.as_ref());
349
350 let header = symbol::parse(&mut reader)?;
351 let dictionary = symbol::decode(
352 &header,
353 &input_symbols,
354 &referred_tables,
355 &page_state.standard_tables,
356 retained_contexts,
357 )?;
358 page_state.store_symbol_dictionary(seg.header.segment_number, dictionary);
359 }
360 SegmentType::ImmediateTextRegion | SegmentType::ImmediateLosslessTextRegion => {
361 let symbols: Vec<&Bitmap> = seg
363 .header
364 .referred_to_segments
365 .iter()
366 .filter_map(|&num| page_state.get_symbol_dictionary(num))
367 .flat_map(|dict| dict.exported_symbols.iter())
368 .collect();
369
370 let referred_tables: Vec<HuffmanTable> = seg
374 .header
375 .referred_to_segments
376 .iter()
377 .filter_map(|&num| page_state.get_huffman_table(num))
378 .cloned()
379 .collect();
380
381 let header = text::parse(&mut reader, symbols.len() as u32)?;
382
383 if page_state.can_decode_directly(
384 page_bitmap,
385 &header.region_info,
386 header.flags.default_pixel,
387 ) {
388 text::decode_into(
389 &header,
390 &symbols,
391 &referred_tables,
392 &page_state.standard_tables,
393 page_bitmap,
394 scratch_buffers,
395 )?;
396 } else {
397 let region = text::decode(
398 &header,
399 &symbols,
400 &referred_tables,
401 &page_state.standard_tables,
402 scratch_buffers,
403 )?;
404 page_bitmap.combine(
405 ®ion.bitmap,
406 region.bitmap.x_location as i32,
407 region.bitmap.y_location as i32,
408 region.combination_operator,
409 );
410 }
411 page_state.page_pristine = false;
412 }
413 SegmentType::IntermediateTextRegion => {
414 let symbols: Vec<&Bitmap> = seg
416 .header
417 .referred_to_segments
418 .iter()
419 .filter_map(|&num| page_state.get_symbol_dictionary(num))
420 .flat_map(|dict| dict.exported_symbols.iter())
421 .collect();
422
423 let referred_tables: Vec<HuffmanTable> = seg
425 .header
426 .referred_to_segments
427 .iter()
428 .filter_map(|&num| page_state.get_huffman_table(num))
429 .cloned()
430 .collect();
431
432 let header = text::parse(&mut reader, symbols.len() as u32)?;
433 let region = text::decode(
434 &header,
435 &symbols,
436 &referred_tables,
437 &page_state.standard_tables,
438 scratch_buffers,
439 )?;
440 page_state.store_region(seg.header.segment_number, region.bitmap);
441 }
442 SegmentType::ImmediateHalftoneRegion | SegmentType::ImmediateLosslessHalftoneRegion => {
443 let pattern_dict = seg
444 .header
445 .referred_to_segments
446 .first()
447 .and_then(|&num| page_state.get_pattern_dictionary(num))
448 .ok_or(SegmentError::MissingPatternDictionary)?;
449
450 let header = halftone::parse(&mut reader)?;
451
452 if page_state.can_decode_directly(
453 page_bitmap,
454 &header.region_info,
455 header.flags.initial_pixel_color,
456 ) {
457 halftone::decode_into(&header, pattern_dict, page_bitmap, scratch_buffers)?;
458 } else {
459 let region = halftone::decode(&header, pattern_dict, scratch_buffers)?;
460 page_bitmap.combine(
461 ®ion.bitmap,
462 region.bitmap.x_location as i32,
463 region.bitmap.y_location as i32,
464 region.combination_operator,
465 );
466 }
467 page_state.page_pristine = false;
468 }
469 SegmentType::IntermediateHalftoneRegion => {
470 let pattern_dict = seg
471 .header
472 .referred_to_segments
473 .first()
474 .and_then(|&num| page_state.get_pattern_dictionary(num))
475 .ok_or(SegmentError::MissingPatternDictionary)?;
476
477 let header = halftone::parse(&mut reader)?;
478 let region = halftone::decode(&header, pattern_dict, scratch_buffers)?;
479 page_state.store_region(seg.header.segment_number, region.bitmap);
480 }
481 SegmentType::IntermediateGenericRefinementRegion => {
482 let reference = seg
484 .header
485 .referred_to_segments
486 .first()
487 .and_then(|&num| page_state.get_referred_segment(num))
488 .unwrap_or(page_bitmap);
489
490 let header = generic_refinement::parse(&mut reader)?;
491 let region = generic_refinement::decode(&header, reference, scratch_buffers)?;
492 page_state.store_region(seg.header.segment_number, region.bitmap);
493 }
494 SegmentType::ImmediateGenericRefinementRegion
495 | SegmentType::ImmediateLosslessGenericRefinementRegion => {
496 let referred_segment = seg
502 .header
503 .referred_to_segments
504 .first()
505 .and_then(|&num| page_state.get_referred_segment(num));
506
507 let header = generic_refinement::parse(&mut reader)?;
508
509 if let Some(referred_segment) = referred_segment
510 && page_state.can_decode_directly(page_bitmap, &header.region_info, false)
511 {
512 generic_refinement::decode_into(
513 &header,
514 referred_segment,
515 page_bitmap,
516 scratch_buffers,
517 )?;
518 } else {
519 let reference = referred_segment.unwrap_or(page_bitmap);
520 let region = generic_refinement::decode(&header, reference, scratch_buffers)?;
521 page_bitmap.combine(
522 ®ion.bitmap,
523 region.bitmap.x_location as i32,
524 region.bitmap.y_location as i32,
525 region.combination_operator,
526 );
527 }
528 page_state.page_pristine = false;
529 }
530 SegmentType::Tables => {
531 let table = HuffmanTable::read_custom(&mut reader)?;
535 page_state.store_huffman_table(seg.header.segment_number, table);
536 }
537 SegmentType::EndOfPage | SegmentType::EndOfFile => {
538 break;
539 }
540 _ => {}
542 }
543 }
544
545 Ok(())
546}
547
548#[derive(Default)]
550pub(crate) struct PageState {
551 pub(crate) page_info: PageInformation,
553 pub(crate) page_pristine: bool,
555 pub(crate) referred_segments: Vec<(u32, Bitmap)>,
557 pub(crate) pattern_dictionaries: Vec<(u32, PatternDictionary)>,
559 pub(crate) symbol_dictionaries: Vec<(u32, SymbolDictionary)>,
561 pub(crate) huffman_tables: Vec<(u32, HuffmanTable)>,
564 pub(crate) standard_tables: StandardHuffmanTables,
566}
567
568impl PageState {
569 fn reset(&mut self, page_info: PageInformation) {
570 self.page_info = page_info;
571 self.page_pristine = true;
572 self.referred_segments.clear();
573 self.pattern_dictionaries.clear();
574 self.symbol_dictionaries.clear();
575 self.huffman_tables.clear();
576 }
578
579 fn can_decode_directly(
581 &self,
582 page_bitmap: &Bitmap,
583 region_info: &decode::RegionSegmentInfo,
584 region_default_pixel: bool,
585 ) -> bool {
586 if !self.page_pristine {
587 return false;
588 }
589
590 let covers_page = region_info.x_location == 0
591 && region_info.y_location == 0
592 && region_info.width == page_bitmap.width
593 && region_info.height == page_bitmap.height;
594
595 if !covers_page {
596 return false;
597 }
598
599 let page_default_is_zero = self.page_info.flags.default_pixel == 0;
600
601 if region_default_pixel == page_default_is_zero {
602 return false;
603 }
604
605 let op = region_info.combination_operator;
606 match op {
607 CombinationOperator::Replace => true,
608 CombinationOperator::Or | CombinationOperator::Xor => page_default_is_zero,
609 CombinationOperator::And | CombinationOperator::Xnor => !page_default_is_zero,
610 }
611 }
612
613 fn store_region(&mut self, segment_number: u32, region: Bitmap) {
615 self.referred_segments.push((segment_number, region));
616 }
617
618 fn get_referred_segment(&self, segment_number: u32) -> Option<&Bitmap> {
620 self.referred_segments
621 .binary_search_by_key(&segment_number, |(num, _)| *num)
622 .ok()
623 .map(|idx| &self.referred_segments[idx].1)
624 }
625
626 fn store_pattern_dictionary(&mut self, segment_number: u32, dictionary: PatternDictionary) {
628 self.pattern_dictionaries.push((segment_number, dictionary));
629 }
630
631 fn get_pattern_dictionary(&self, segment_number: u32) -> Option<&PatternDictionary> {
633 self.pattern_dictionaries
634 .binary_search_by_key(&segment_number, |(num, _)| *num)
635 .ok()
636 .map(|idx| &self.pattern_dictionaries[idx].1)
637 }
638
639 fn store_symbol_dictionary(&mut self, segment_number: u32, dictionary: SymbolDictionary) {
641 self.symbol_dictionaries.push((segment_number, dictionary));
642 }
643
644 fn get_symbol_dictionary(&self, segment_number: u32) -> Option<&SymbolDictionary> {
646 self.symbol_dictionaries
647 .binary_search_by_key(&segment_number, |(num, _)| *num)
648 .ok()
649 .map(|idx| &self.symbol_dictionaries[idx].1)
650 }
651
652 fn store_huffman_table(&mut self, segment_number: u32, table: HuffmanTable) {
654 self.huffman_tables.push((segment_number, table));
655 }
656
657 fn get_huffman_table(&self, segment_number: u32) -> Option<&HuffmanTable> {
659 self.huffman_tables
660 .binary_search_by_key(&segment_number, |(num, _)| *num)
661 .ok()
662 .map(|idx| &self.huffman_tables[idx].1)
663 }
664}
665
666fn init_page(
668 reader: &mut Reader<'_>,
669 height_from_stripes: Option<u32>,
670 page: &mut PageState,
671 bitmap: &mut Bitmap,
672) -> Result<()> {
673 let page_info = parse_page_information(reader)?;
674
675 let height = if page_info.height == 0xFFFF_FFFF {
679 height_from_stripes.ok_or(FormatError::UnknownPageHeight)?
680 } else {
681 page_info.height
682 };
683
684 bitmap.reinitialize(page_info.width, height, page_info.flags.default_pixel != 0)?;
688
689 page.reset(page_info);
690
691 Ok(())
692}