1use std::io::Read;
2
3use gufo_common::physical_dimension::{
4 PhysicalDimensionUnit, PixelDensity, PixelsPerPhysicalDimension,
5};
6use zerocopy::big_endian::U16;
7
8use super::Error;
9
10#[derive(Debug)]
11pub struct Dqt_<T> {
12 tq: u8,
14 qk: [T; 64],
16}
17
18#[derive(Debug)]
20pub enum Dqt {
21 Dqt8(Dqt_<u8>),
23 Dqt16(Dqt_<u16>),
25}
26
27impl Dqt {
28 pub fn tq(&self) -> u8 {
29 match self {
30 Self::Dqt8(x) => x.tq,
31 Self::Dqt16(x) => x.tq,
32 }
33 }
34
35 pub fn qk(&self) -> [u16; 64] {
40 match self {
41 Self::Dqt8(dqt) => {
42 let mut qk = [0; 64];
43 for (n, i) in dqt.qk.into_iter().enumerate() {
44 qk[n] = i.into();
45 }
46 qk
47 }
48 Self::Dqt16(dqt) => dqt.qk,
49 }
50 }
51
52 pub fn qk_ordered(&self) -> [u16; 64] {
56 const IDX: [[usize; 8]; 8] = [
57 [0, 1, 5, 6, 14, 15, 27, 28],
58 [2, 4, 7, 13, 16, 26, 29, 42],
59 [3, 8, 12, 17, 25, 30, 41, 43],
60 [9, 11, 18, 24, 31, 40, 44, 53],
61 [10, 19, 23, 32, 39, 45, 52, 54],
62 [20, 22, 33, 38, 46, 51, 55, 60],
63 [21, 34, 37, 47, 50, 56, 59, 61],
64 [35, 36, 48, 49, 57, 58, 62, 63],
65 ];
66
67 let qk = self.qk();
68
69 let mut qk_ordered = [0; 64];
70
71 for (i, n) in IDX.into_iter().flatten().enumerate() {
72 qk_ordered[i] = qk[n];
73 }
74
75 qk_ordered
76 }
77
78 pub fn from_data(mut value: &[u8]) -> Result<Vec<Self>, Error> {
79 let mut dqts = Vec::new();
80 while !value.is_empty() {
81 let mut pq_tq = [0; 1];
82 value
83 .read_exact(&mut pq_tq)
84 .map_err(|_| Error::UnexpectedEof)?;
85 let pq_tq = pq_tq[0];
86
87 let pq = pq_tq >> 4;
88 let tq = pq_tq & 0b1111;
89
90 tracing::debug!("Loading DQT entry with Pq={pq}, Tq={tq}");
91
92 match pq {
94 0 => {
95 let mut qk = [0; 64];
96 value
97 .read_exact(&mut qk)
98 .map_err(|_| Error::UnexpectedEof)?;
99 dqts.push(Self::Dqt8(Dqt_ { tq, qk }))
100 }
101 1 => {
102 let mut qk_raw = [0; 64 * 2];
103 value
104 .read_exact(&mut qk_raw)
105 .map_err(|_| Error::UnexpectedEof)?;
106
107 let mut qk = [0; 64];
108 for (n, i) in qk_raw.chunks_exact(2).enumerate() {
109 let entry = u16::from_be_bytes(i.try_into().unwrap());
110 qk[n] = entry;
111 }
112
113 dqts.push(Self::Dqt16(Dqt_ { tq, qk }))
114 }
115 unkown_pq => return Err(Error::UnknownPq(unkown_pq)),
116 }
117 }
118
119 Ok(dqts)
120 }
121}
122
123#[derive(Debug)]
125pub struct Sof {
126 pub p: u8,
128 pub y: u16,
130 pub x: u16,
132 pub parameters: Vec<ComponentSpecificationParameters>,
134}
135
136impl Sof {
137 pub fn from_data(mut data: &[u8]) -> Result<Self, Error> {
138 let p = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
139 let y = data.read_be_u16().map_err(|_| Error::UnexpectedEof)?;
140 let x = data.read_be_u16().map_err(|_| Error::UnexpectedEof)?;
141 let nf = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
142
143 let mut parameters = Vec::with_capacity(nf as usize);
144 let buf = &mut [0; 3];
145 for _ in 0..nf {
146 data.read_exact(buf).map_err(|_| Error::UnexpectedEof)?;
147 parameters.push(ComponentSpecificationParameters::from_data(buf)?);
148 }
149
150 Ok(Self {
151 p,
152 y,
153 x,
154 parameters,
155 })
156 }
157}
158
159#[derive(Debug, Clone, Copy)]
161pub struct ComponentSpecificationParameters {
162 pub c: u8,
164 pub h: u8,
166 pub v: u8,
168 pub tq: u8,
170}
171
172impl ComponentSpecificationParameters {
173 pub fn from_data(mut data: &[u8]) -> Result<Self, Error> {
174 let c = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
175 let h_v = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
176 let tq = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
177
178 let h = h_v >> 4;
179 let v = h_v & 0b1111;
180
181 Ok(Self { c, h, v, tq })
182 }
183}
184
185pub trait ReadExt: Read {
186 fn read_u8(&mut self) -> std::io::Result<u8> {
187 let buf = &mut [0; 1];
188 self.read_exact(buf)?;
189 Ok(buf[0])
190 }
191
192 fn read_be_u16(&mut self) -> std::io::Result<u16> {
193 let buf = &mut [0; 2];
194 self.read_exact(buf)?;
195 Ok(u16::from_be_bytes(*buf))
196 }
197}
198
199impl<T: Read> ReadExt for T {}
200
201#[derive(Debug)]
203pub struct Sos {
204 pub components_specifications: Vec<ComponentSpecification>,
206 pub ss: u8,
208 pub se: u8,
210 pub ah: u8,
212 pub al: u8,
214}
215
216impl Sos {
217 pub fn from_data(mut data: &[u8]) -> Result<Self, Error> {
218 let ns = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
219
220 let mut components_specifications = Vec::with_capacity(ns as usize);
221 let buf = &mut [0; 2];
222 for _ in 0..ns {
223 data.read_exact(buf).map_err(|_| Error::UnexpectedEof)?;
224 components_specifications.push(ComponentSpecification::from_data(buf)?);
225 }
226
227 let ss = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
228 let se = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
229 let ah_al = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
230 let ah = ah_al >> 4;
231 let al = ah_al & 0b1111;
232
233 Ok(Self {
234 components_specifications,
235 ss,
236 se,
237 ah,
238 al,
239 })
240 }
241}
242
243#[derive(Debug)]
244pub struct ComponentSpecification {
245 pub cs: u8,
251 pub td: u8,
253 pub ta: u8,
255}
256
257impl ComponentSpecification {
258 pub fn from_data(mut data: &[u8]) -> Result<ComponentSpecification, Error> {
259 let cs = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
260 let td_ta = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
261 let td = td_ta >> 4;
262 let ta = td_ta & 0b1111;
263
264 Ok(Self { cs, td, ta })
265 }
266}
267
268#[derive(zerocopy::FromBytes, zerocopy::KnownLayout, zerocopy::Immutable, Clone, Debug)]
269#[repr(C)]
270pub struct Jfif {
271 pub major_verson: u8,
272 pub minor_version: u8,
273 pub pixel_density_unit: u8,
274 pub pixel_density_x: U16,
275 pub pixel_density_y: U16,
276 pub thumbnail_width: u8,
277 pub thunbnail_height: u8,
278}
279
280impl Jfif {
281 pub fn pixel_density(&self) -> Option<PixelDensity> {
282 let unit = match self.pixel_density_unit {
283 0 => None,
284 1 => Some(PhysicalDimensionUnit::Inch),
285 2 => Some(PhysicalDimensionUnit::Centimeter),
286 u => {
287 tracing::warn!("Unknown pixel density unit: {u}");
288 None
289 }
290 }?;
291
292 Some(PixelDensity::new(
293 PixelsPerPhysicalDimension::new(self.pixel_density_x.get() as f64, unit),
294 PixelsPerPhysicalDimension::new(self.pixel_density_y.get() as f64, unit),
295 ))
296 }
297}