cloudflare_soos/jpeg/
parser.rs

1use 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    // length is including itself.
63    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
83// Section B.2.2
84pub 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
92// Section B.2.2
93pub 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        // Each component's identifier must be unique.
155        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
212// Section B.2.3
213pub 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        // Each of the scan's components must be unique.
242        if component_indices.contains(&component_index) {
243            return Err(Error::Format("duplicate scan component identifier"));
244        }
245
246        // "... the ordering in the scan header shall follow the ordering in the frame header."
247        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}