Skip to main content

gufo_jpeg/
segments.rs

1use std::io::Read;
2
3use super::Error;
4
5#[derive(Debug)]
6pub struct Dqt_<T> {
7    /// Quantization table destination identifier
8    tq: u8,
9    /// Quantization table elements
10    qk: [T; 64],
11}
12
13/// Quantization Table
14#[derive(Debug)]
15pub enum Dqt {
16    /// Table definition with 8 bit elements
17    Dqt8(Dqt_<u8>),
18    /// Table definition with 16 bit elements
19    Dqt16(Dqt_<u16>),
20}
21
22impl Dqt {
23    pub fn tq(&self) -> u8 {
24        match self {
25            Self::Dqt8(x) => x.tq,
26            Self::Dqt16(x) => x.tq,
27        }
28    }
29
30    /// Quantization table elements in 16 bit
31    ///
32    /// This resturns the data in 16 bit, even if defined as 8 bit. The 8-bit
33    /// data is not scaled to 16-bit.
34    pub fn qk(&self) -> [u16; 64] {
35        match self {
36            Self::Dqt8(dqt) => {
37                let mut qk = [0; 64];
38                for (n, i) in dqt.qk.into_iter().enumerate() {
39                    qk[n] = i.into();
40                }
41                qk
42            }
43            Self::Dqt16(dqt) => dqt.qk,
44        }
45    }
46
47    /// Quantization table in non-zig-zag order
48    ///
49    /// Otherwise same as `qk()`
50    pub fn qk_ordered(&self) -> [u16; 64] {
51        const IDX: [[usize; 8]; 8] = [
52            [0, 1, 5, 6, 14, 15, 27, 28],
53            [2, 4, 7, 13, 16, 26, 29, 42],
54            [3, 8, 12, 17, 25, 30, 41, 43],
55            [9, 11, 18, 24, 31, 40, 44, 53],
56            [10, 19, 23, 32, 39, 45, 52, 54],
57            [20, 22, 33, 38, 46, 51, 55, 60],
58            [21, 34, 37, 47, 50, 56, 59, 61],
59            [35, 36, 48, 49, 57, 58, 62, 63],
60        ];
61
62        let qk = self.qk();
63
64        let mut qk_ordered = [0; 64];
65
66        for (i, n) in IDX.into_iter().flatten().enumerate() {
67            qk_ordered[i] = qk[n];
68        }
69
70        qk_ordered
71    }
72
73    pub fn from_data(mut value: &[u8]) -> Result<Vec<Self>, Error> {
74        let mut dqts = Vec::new();
75        while !value.is_empty() {
76            let mut pq_tq = [0; 1];
77            value
78                .read_exact(&mut pq_tq)
79                .map_err(|_| Error::UnexpectedEof)?;
80            let pq_tq = pq_tq[0];
81
82            let pq = pq_tq >> 4;
83            let tq = pq_tq & 0b1111;
84
85            tracing::debug!("Loading DQT entry with Pq={pq}, Tq={tq}");
86
87            // Matrix entries can be 8bit and 16bit precision
88            match pq {
89                0 => {
90                    let mut qk = [0; 64];
91                    value
92                        .read_exact(&mut qk)
93                        .map_err(|_| Error::UnexpectedEof)?;
94                    dqts.push(Self::Dqt8(Dqt_ { tq, qk }))
95                }
96                1 => {
97                    let mut qk_raw = [0; 64 * 2];
98                    value
99                        .read_exact(&mut qk_raw)
100                        .map_err(|_| Error::UnexpectedEof)?;
101
102                    let mut qk = [0; 64];
103                    for (n, i) in qk_raw.chunks_exact(2).enumerate() {
104                        let entry = u16::from_be_bytes(i.try_into().unwrap());
105                        qk[n] = entry;
106                    }
107
108                    dqts.push(Self::Dqt16(Dqt_ { tq, qk }))
109                }
110                unkown_pq => return Err(Error::UnknownPq(unkown_pq)),
111            }
112        }
113
114        Ok(dqts)
115    }
116}
117
118/// Frame Header / Start of Frame
119#[derive(Debug)]
120pub struct Sof {
121    /// Sample precision
122    pub p: u8,
123    /// Number of lines
124    pub y: u16,
125    /// Number of samples per line
126    pub x: u16,
127    /// Component specification parameters
128    pub parameters: Vec<ComponentSpecificationParameters>,
129}
130
131impl Sof {
132    pub fn from_data(mut data: &[u8]) -> Result<Self, Error> {
133        let p = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
134        let y = data.read_be_u16().map_err(|_| Error::UnexpectedEof)?;
135        let x = data.read_be_u16().map_err(|_| Error::UnexpectedEof)?;
136        let nf = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
137
138        let mut parameters = Vec::with_capacity(nf as usize);
139        let buf = &mut [0; 3];
140        for _ in 0..nf {
141            data.read_exact(buf).map_err(|_| Error::UnexpectedEof)?;
142            parameters.push(ComponentSpecificationParameters::from_data(buf)?);
143        }
144
145        Ok(Self {
146            p,
147            y,
148            x,
149            parameters,
150        })
151    }
152}
153
154/// Component specification parameters
155#[derive(Debug, Clone, Copy)]
156pub struct ComponentSpecificationParameters {
157    /// Component identifier
158    pub c: u8,
159    /// Horizontal sampling factor
160    pub h: u8,
161    /// Vertical sampling factor
162    pub v: u8,
163    /// Quantization table destination selector
164    pub tq: u8,
165}
166
167impl ComponentSpecificationParameters {
168    pub fn from_data(mut data: &[u8]) -> Result<Self, Error> {
169        let c = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
170        let h_v = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
171        let tq = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
172
173        let h = h_v >> 4;
174        let v = h_v & 0b1111;
175
176        Ok(Self { c, h, v, tq })
177    }
178}
179
180pub trait ReadExt: Read {
181    fn read_u8(&mut self) -> std::io::Result<u8> {
182        let buf = &mut [0; 1];
183        self.read_exact(buf)?;
184        Ok(buf[0])
185    }
186
187    fn read_be_u16(&mut self) -> std::io::Result<u16> {
188        let buf = &mut [0; 2];
189        self.read_exact(buf)?;
190        Ok(u16::from_be_bytes(*buf))
191    }
192}
193
194impl<T: Read> ReadExt for T {}
195
196/// Scan Header / Start of Scan
197#[derive(Debug)]
198pub struct Sos {
199    /// List of components (channels)
200    pub components_specifications: Vec<ComponentSpecification>,
201    /// Start of spectral or predictor selection
202    pub ss: u8,
203    /// End of spectral selection
204    pub se: u8,
205    /// Successive approximation bit position high
206    pub ah: u8,
207    /// Successive approximation bit position low or point transform
208    pub al: u8,
209}
210
211impl Sos {
212    pub fn from_data(mut data: &[u8]) -> Result<Self, Error> {
213        let ns = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
214
215        let mut components_specifications = Vec::with_capacity(ns as usize);
216        let buf = &mut [0; 2];
217        for _ in 0..ns {
218            data.read_exact(buf).map_err(|_| Error::UnexpectedEof)?;
219            components_specifications.push(ComponentSpecification::from_data(buf)?);
220        }
221
222        let ss = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
223        let se = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
224        let ah_al = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
225        let ah = ah_al >> 4;
226        let al = ah_al & 0b1111;
227
228        Ok(Self {
229            components_specifications,
230            ss,
231            se,
232            ah,
233            al,
234        })
235    }
236}
237
238#[derive(Debug)]
239pub struct ComponentSpecification {
240    /// Scan component selector
241    ///
242    /// References a `c` value in
243    /// `ComponentSpecificationParameters`](ComponentSpecificationParameters#
244    /// structfield.c).
245    pub cs: u8,
246    /// DC entropy coding table
247    pub td: u8,
248    /// AC entropy coding table
249    pub ta: u8,
250}
251
252impl ComponentSpecification {
253    pub fn from_data(mut data: &[u8]) -> Result<ComponentSpecification, Error> {
254        let cs = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
255        let td_ta = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
256        let td = td_ta >> 4;
257        let ta = td_ta & 0b1111;
258
259        Ok(Self { cs, td, ta })
260    }
261}