pdfluent_jpeg2000/jp2/
mod.rs1use alloc::vec::Vec;
4
5use crate::error::{FormatError, Result, bail};
6use crate::j2c::ComponentData;
7use crate::jp2::r#box::{FILE_TYPE, JP2_SIGNATURE};
8use crate::jp2::cdef::ChannelDefinitionBox;
9use crate::jp2::cmap::{ComponentMappingBox, ComponentMappingEntry, ComponentMappingType};
10use crate::jp2::colr::ColorSpecificationBox;
11use crate::jp2::pclr::PaletteBox;
12use crate::reader::BitReader;
13use crate::{DecodeSettings, Image, resolve_alpha_and_color_space};
14
15pub(crate) mod r#box;
16pub(crate) mod cdef;
17pub(crate) mod cmap;
18pub(crate) mod colr;
19pub(crate) mod icc;
20pub(crate) mod pclr;
21
22#[derive(Debug, Clone, Default)]
23pub(crate) struct ImageBoxes {
24 pub(crate) color_specification: Option<ColorSpecificationBox>,
25 pub(crate) channel_definition: Option<ChannelDefinitionBox>,
26 pub(crate) palette: Option<PaletteBox>,
27 pub(crate) component_mapping: Option<ComponentMappingBox>,
28}
29
30pub struct DecodedImage<'a> {
32 pub(crate) decoded_components: &'a mut Vec<ComponentData>,
34 pub(crate) boxes: ImageBoxes,
37}
38
39pub(crate) fn parse<'a>(data: &'a [u8], mut settings: DecodeSettings) -> Result<Image<'a>> {
40 let mut reader = BitReader::new(data);
41 let signature_box = r#box::read(&mut reader).ok_or(FormatError::InvalidBox)?;
42
43 if signature_box.box_type != JP2_SIGNATURE {
44 bail!(FormatError::InvalidSignature);
45 }
46
47 let file_type_box = r#box::read(&mut reader).ok_or(FormatError::InvalidBox)?;
48
49 if file_type_box.box_type != FILE_TYPE {
50 bail!(FormatError::InvalidFileType);
51 }
52
53 let mut image_boxes: Option<ImageBoxes> = None;
54 let mut parsed_codestream = None;
55
56 while !reader.at_end() {
58 let Some(current_box) = r#box::read(&mut reader) else {
59 if settings.strict {
60 bail!(FormatError::InvalidBox);
61 }
62
63 break;
64 };
65
66 match current_box.box_type {
67 r#box::JP2_HEADER => {
68 let mut boxes = ImageBoxes::default();
69
70 let mut jp2h_reader = BitReader::new(current_box.data);
71
72 while !jp2h_reader.at_end() {
74 let child_box = r#box::read(&mut jp2h_reader).ok_or(FormatError::InvalidBox)?;
75
76 match child_box.box_type {
77 r#box::CHANNEL_DEFINITION => {
78 if cdef::parse(&mut boxes, child_box.data).is_err() && settings.strict {
79 bail!(FormatError::InvalidBox);
80 }
81 }
84 r#box::COLOUR_SPECIFICATION => {
85 colr::parse(&mut boxes, child_box.data)?;
86 }
87 r#box::PALETTE => {
88 if pclr::parse(&mut boxes, child_box.data).is_err() && settings.strict {
89 bail!(FormatError::InvalidBox);
90 }
91
92 settings.target_resolution = None;
96 }
97 r#box::COMPONENT_MAPPING => {
98 cmap::parse(&mut boxes, child_box.data)?;
99 }
100 _ => {
101 debug!(
102 "ignoring header box {}",
103 r#box::tag_to_string(child_box.box_type)
104 );
105 }
106 }
107 }
108
109 image_boxes = Some(boxes);
110 }
111 r#box::CONTIGUOUS_CODESTREAM => {
112 parsed_codestream = Some(crate::j2c::parse_raw(current_box.data, &settings)?);
113 }
114 _ => {}
115 }
116 }
117
118 let mut image_boxes = image_boxes.ok_or(FormatError::InvalidBox)?;
119 let parsed_codestream = parsed_codestream.ok_or(FormatError::MissingCodestream)?;
120
121 if let Some(palette) = image_boxes.palette.as_ref()
122 && image_boxes.component_mapping.is_none()
123 {
124 let mappings = (0..palette.columns.len())
128 .map(|i| ComponentMappingEntry {
129 component_index: 0,
130 mapping_type: ComponentMappingType::Palette { column: i as u8 },
131 })
132 .collect::<Vec<_>>();
133
134 image_boxes.component_mapping = Some(ComponentMappingBox { entries: mappings });
135 }
136
137 let (color_space, has_alpha) =
138 resolve_alpha_and_color_space(&image_boxes, &parsed_codestream.header, &settings)?;
139
140 Ok(Image {
141 codestream: parsed_codestream.data,
142 header: parsed_codestream.header,
143 boxes: image_boxes,
144 settings,
145 color_space,
146 has_alpha,
147 })
148}