cloudflare_soos/jpeg/
parser.rs1use crate::error::{Error, Result};
2use crate::jpeg::byteorder::ReadBytesExt;
3use crate::jpeg::marker::Marker;
4use crate::jpeg::marker::Marker::{SOF, SOS};
5use std::io::{self, Read};
6use std::ops::RangeInclusive;
7
8#[derive(Clone, Copy, Debug, PartialEq)]
9pub struct Dimensions {
10 pub width: u16,
11 pub height: u16,
12}
13
14#[derive(Clone, Copy, Debug, PartialEq)]
15pub enum CodingProcess {
16 DctSequential,
17 DctProgressive,
18 Lossless,
19}
20
21#[derive(Debug, Clone)]
22pub struct FrameInfo {
23 pub is_baseline: bool,
24 pub is_differential: bool,
25 pub coding_process: CodingProcess,
26 pub precision: u8,
27
28 pub image_size: Dimensions,
29 pub mcu_size: Dimensions,
30 pub components: Vec<Component>,
31}
32
33#[derive(Debug)]
34pub struct ScanInfo {
35 pub component_indices: Vec<usize>,
36 pub dc_table_indices: Vec<usize>,
37 pub ac_table_indices: Vec<usize>,
38
39 pub spectral_selection: RangeInclusive<u8>,
40 pub successive_approximation_high: u8,
41 pub successive_approximation_low: u8,
42}
43
44#[derive(Clone, Debug)]
45pub struct Component {
46 pub identifier: u8,
47
48 pub horizontal_sampling_factor: u8,
49 pub vertical_sampling_factor: u8,
50
51 pub quantization_table_index: usize,
52
53 pub size: Dimensions,
54 pub block_size: Dimensions,
55}
56
57fn read_length<R: Read>(reader: &mut R, marker: Marker) -> Result<usize> {
58 if !marker.has_length() {
59 return Err(Error::Format("unexpected empty marker"));
60 }
61
62 let length = reader.read_u16_be()? as usize;
64
65 if length < 2 {
66 return Err(Error::Format("encountered invalid length"));
67 }
68
69 Ok(length - 2)
70}
71
72fn skip_bytes<R: Read>(reader: &mut R, length: usize) -> Result<()> {
73 let length = length as u64;
74 let to_skip = &mut reader.by_ref().take(length);
75 let copied = io::copy(to_skip, &mut io::sink())?;
76 if copied < length {
77 Err(Error::Io(io::ErrorKind::UnexpectedEof.into()))
78 } else {
79 Ok(())
80 }
81}
82
83pub fn skip_marker<R: Read>(reader: &mut R, marker: Marker) -> Result<()> {
85 if marker.has_length() {
86 let length = read_length(reader, marker)?;
87 skip_bytes(reader, length)?;
88 }
89 Ok(())
90}
91
92pub fn parse_sof<R: Read>(reader: &mut R, marker: Marker) -> Result<FrameInfo> {
94 let length = read_length(reader, marker)?;
95
96 if length <= 6 {
97 return Err(Error::Format("invalid length in SOF"));
98 }
99
100 let is_baseline = marker == SOF(0);
101 let is_differential = match marker {
102 SOF(0..=3 | 9..=11) => false,
103 SOF(5..=7 | 13..=15) => true,
104 _ => panic!(),
105 };
106 let coding_process = match marker {
107 SOF(0 | 1 | 5 | 9 | 13) => CodingProcess::DctSequential,
108 SOF(2 | 6 | 10 | 14) => CodingProcess::DctProgressive,
109 SOF(3 | 7 | 11 | 15) => CodingProcess::Lossless,
110 _ => panic!(),
111 };
112
113 let precision = reader.read_u8()?;
114
115 match precision {
116 8 => {},
117 12 => {
118 if is_baseline {
119 return Err(Error::Format("12 bit sample precision is not allowed in baseline"));
120 }
121 },
122 _ => {
123 if coding_process != CodingProcess::Lossless {
124 return Err(Error::Format("invalid precision in frame header"))
125 }
126 },
127 }
128
129 let height = reader.read_u16_be()?;
130 let width = reader.read_u16_be()?;
131
132 if width == 0 || height == 0 {
133 return Err(Error::Format("zero size in frame header"));
134 }
135
136 let component_count = reader.read_u8()?;
137
138 if component_count == 0 {
139 return Err(Error::Format("zero component count in frame header"));
140 }
141 if coding_process == CodingProcess::DctProgressive && component_count > 4 {
142 return Err(Error::Format("progressive frame with more than 4 components"));
143 }
144
145 if length != 6 + 3 * component_count as usize {
146 return Err(Error::Format("invalid length in SOF"));
147 }
148
149 let mut components: Vec<Component> = Vec::with_capacity(component_count as usize);
150
151 for _ in 0..component_count {
152 let identifier = reader.read_u8()?;
153
154 if components.iter().any(|c| c.identifier == identifier) {
156 return Err(Error::Format("duplicate frame component identifier"));
157 }
158
159 let byte = reader.read_u8()?;
160 let horizontal_sampling_factor = byte >> 4;
161 let vertical_sampling_factor = byte & 0x0f;
162
163 if horizontal_sampling_factor == 0 || horizontal_sampling_factor > 4 {
164 return Err(Error::Format("invalid horizontal sampling factor"));
165 }
166 if vertical_sampling_factor == 0 || vertical_sampling_factor > 4 {
167 return Err(Error::Format("invalid vertical sampling factor"));
168 }
169
170 let quantization_table_index = reader.read_u8()?;
171
172 if quantization_table_index > 3 || (coding_process == CodingProcess::Lossless && quantization_table_index != 0) {
173 return Err(Error::Format("invalid quantization table index"));
174 }
175
176 components.push(Component {
177 identifier,
178 horizontal_sampling_factor,
179 vertical_sampling_factor,
180 quantization_table_index: quantization_table_index as usize,
181 size: Dimensions {width: 0, height: 0},
182 block_size: Dimensions {width: 0, height: 0},
183 });
184 }
185
186 let h_max = components.iter().map(|c| c.horizontal_sampling_factor).max().unwrap();
187 let v_max = components.iter().map(|c| c.vertical_sampling_factor).max().unwrap();
188 let mcu_size = Dimensions {
189 width: (f32::from(width) / (f32::from(h_max) * 8.0)).ceil() as u16,
190 height: (f32::from(height) / (f32::from(v_max) * 8.0)).ceil() as u16,
191 };
192
193 for component in &mut components {
194 component.size.width = (f32::from(width) * (f32::from(component.horizontal_sampling_factor) / f32::from(h_max))).ceil() as u16;
195 component.size.height = (f32::from(height) * (f32::from(component.vertical_sampling_factor) / f32::from(v_max))).ceil() as u16;
196
197 component.block_size.width = mcu_size.width * u16::from(component.horizontal_sampling_factor);
198 component.block_size.height = mcu_size.height * u16::from(component.vertical_sampling_factor);
199 }
200
201 Ok(FrameInfo {
202 is_baseline,
203 is_differential,
204 coding_process,
205 precision,
206 image_size: Dimensions { width, height },
207 mcu_size,
208 components,
209 })
210}
211
212pub fn parse_sos<R: Read>(reader: &mut R, frame: &FrameInfo) -> Result<ScanInfo> {
214 let length = read_length(reader, SOS)?;
215 if 0 == length {
216 return Err(Error::Format("zero length in SOS"));
217 }
218
219 let component_count = reader.read_u8()?;
220
221 if component_count == 0 || component_count > 4 {
222 return Err(Error::Format("invalid component count in scan header"));
223 }
224
225 if length != 4 + 2 * component_count as usize {
226 return Err(Error::Format("invalid length in SOS"));
227 }
228
229 let mut component_indices = Vec::with_capacity(component_count as usize);
230 let mut dc_table_indices = Vec::with_capacity(component_count as usize);
231 let mut ac_table_indices = Vec::with_capacity(component_count as usize);
232
233 for _ in 0..component_count {
234 let identifier = reader.read_u8()?;
235
236 let component_index = match frame.components.iter().position(|c| c.identifier == identifier) {
237 Some(value) => value,
238 None => return Err(Error::Format("scan component identifier does not match any of the component identifiers defined in the frame")),
239 };
240
241 if component_indices.contains(&component_index) {
243 return Err(Error::Format("duplicate scan component identifier"));
244 }
245
246 if component_index < *component_indices.iter().max().unwrap_or(&0) {
248 return Err(Error::Format("the scan component order does not follow the order in the frame header"));
249 }
250
251 let byte = reader.read_u8()?;
252 let dc_table_index = byte >> 4;
253 let ac_table_index = byte & 0x0f;
254
255 if dc_table_index > 3 || (frame.is_baseline && dc_table_index > 1) {
256 return Err(Error::Format("invalid dc table index"));
257 }
258 if ac_table_index > 3 || (frame.is_baseline && ac_table_index > 1) {
259 return Err(Error::Format("invalid ac table index"));
260 }
261
262 component_indices.push(component_index);
263 dc_table_indices.push(dc_table_index as usize);
264 ac_table_indices.push(ac_table_index as usize);
265 }
266
267 let blocks_per_mcu = component_indices.iter().map(|&i| {
268 u32::from(frame.components[i].horizontal_sampling_factor) * u32::from(frame.components[i].vertical_sampling_factor)
269 }).fold(0, ::std::ops::Add::add);
270
271 if component_count > 1 && blocks_per_mcu > 10 {
272 return Err(Error::Format("scan with more than one component and more than 10 blocks per MCU"));
273 }
274
275 let spectral_selection_start = reader.read_u8()?;
276 let spectral_selection_end = reader.read_u8()?;
277
278 let byte = reader.read_u8()?;
279 let successive_approximation_high = byte >> 4;
280 let successive_approximation_low = byte & 0x0f;
281
282 Ok(ScanInfo {
283 component_indices,
284 dc_table_indices,
285 ac_table_indices,
286 spectral_selection: spectral_selection_start..=spectral_selection_end,
287 successive_approximation_high,
288 successive_approximation_low,
289 })
290}