Skip to content

Commit 1734599

Browse files
Continue work
1 parent 7d456c0 commit 1734599

11 files changed

Lines changed: 136 additions & 65 deletions

File tree

src/bin/test_suite.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use anyhow::{anyhow, Result};
22
use comfy_table::{Attribute, Cell, Color, Table};
33
use iris::{
44
png::{grammar::Png, PngDecoder},
5-
util::test_file_parser::{parse_test_file, PNGSuiteTestCase},
5+
test_file_parser::{parse_test_file, PNGSuiteTestCase},
66
};
77
use std::{ffi::OsStr, fmt, fs, panic};
88

src/bitreader.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use anyhow::{ensure, Result};
2+
3+
#[derive(Debug)]
4+
pub struct BitReader<'a> {
5+
// Note the cursor tracks num bits!
6+
cursor: usize,
7+
data: &'a [u8],
8+
}
9+
10+
impl<'a> BitReader<'a> {
11+
pub fn new(data: &'a [u8]) -> Self {
12+
Self { cursor: 0, data }
13+
}
14+
15+
pub fn read_bit(&mut self) -> Result<u8> {
16+
ensure!(self.cursor < self.data.len() * 8, "oob");
17+
18+
let (byte_idx, bit_idx) = self.divmod();
19+
let byte = self.data[byte_idx];
20+
21+
let bit = (byte >> (7 - bit_idx)) & 0b1;
22+
self.cursor += 1;
23+
24+
Ok(bit)
25+
}
26+
pub fn read_bits(&mut self, bits: usize) -> Result<usize> {
27+
let mut out = 0_usize;
28+
29+
for _ in 0..bits {
30+
out = (out << 1) | self.read_bit()? as usize;
31+
}
32+
33+
Ok(out)
34+
}
35+
36+
fn divmod(&self) -> (usize, usize) {
37+
(self.cursor / 8, self.cursor % 8)
38+
}
39+
}
File renamed without changes.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ macro_rules! impl_read_slice {
5050
}
5151

5252
#[allow(dead_code)]
53-
fn peek_slice(&mut self, len: usize) -> Result<&'a [u8]> {
53+
fn peek_slice(&self, len: usize) -> Result<&'a [u8]> {
5454
self.data
5555
.get(self.cursor..self.cursor + len)
5656
.ok_or_else(|| anyhow::anyhow!("oob"))

src/jpeg/decoder.rs

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use crate::{
22
impl_read_for_datatype, impl_read_slice,
33
jpeg::grammar::{
4-
Component, EncodingProcess, HuffmanTable, Jpeg, Marker, Precision, QuantizationTable,
5-
StartOfFrame, StartOfScan, JFIF,
4+
ApplicationHeader, Component, EncodingProcess, HuffmanTable, Jpeg, Marker, Precision,
5+
QuantizationTable, StartOfFrame, StartOfScan, JFIF,
66
},
77
};
88

99
use anyhow::{anyhow, ensure, Result};
10-
use std::ops::{Range, RangeInclusive};
10+
use std::ops::RangeInclusive;
1111

1212
#[derive(Debug)]
1313
pub struct JpegDecoder<'a> {
@@ -28,9 +28,10 @@ impl<'a> JpegDecoder<'a> {
2828
todo!();
2929
}
3030

31-
fn parse_jfif(&mut self) -> Result<JFIF> {
31+
fn parse_jfif(&mut self) -> Result<JFIF<'a>> {
3232
ensure!(self.read_marker()? == 0xFFD8);
3333

34+
let mut application_header = None;
3435
let mut quantization_tables = Vec::with_capacity(4);
3536
let mut huffman_tables = Vec::new();
3637
let mut start_of_frame = None;
@@ -40,7 +41,7 @@ impl<'a> JpegDecoder<'a> {
4041
loop {
4142
match self.read_marker()? {
4243
0xFFE0 => {
43-
self.parse_application_header()?;
44+
application_header = Some(self.parse_application_header()?);
4445
}
4546
0xFFDB => {
4647
quantization_tables.push(self.parse_quantization_table()?);
@@ -55,7 +56,10 @@ impl<'a> JpegDecoder<'a> {
5556

5657
break;
5758
}
58-
start_of_frame_marker if (start_of_frame_marker as u8 & 0xF0) == 0xC0 => {
59+
start_of_frame_marker
60+
if start_of_frame_marker >> 8 == 0xFF
61+
&& (start_of_frame_marker as u8 & 0xF0) == 0xC0 =>
62+
{
5963
ensure!(start_of_frame.is_none());
6064
start_of_frame = Some(self.parse_start_of_frame(start_of_frame_marker as u8)?);
6165
}
@@ -66,6 +70,8 @@ impl<'a> JpegDecoder<'a> {
6670
ensure!(self.read_marker()? == 0xFFD9);
6771

6872
Ok(JFIF {
73+
application_header: application_header
74+
.ok_or_else(|| anyhow!("expected application header"))?,
6975
quantization_tables,
7076
huffman_tables: {
7177
ensure!(huffman_tables.len() == 4);
@@ -77,15 +83,22 @@ impl<'a> JpegDecoder<'a> {
7783
})
7884
}
7985

80-
fn parse_application_header(&mut self) -> Result<()> {
86+
fn parse_application_header(&mut self) -> Result<ApplicationHeader> {
8187
let offset = self.cursor;
82-
let length = self.read_u16()?;
88+
let length = self.read_u16()? as usize;
8389

8490
ensure!(self.read_slice(5)? == b"JFIF\0");
8591

86-
self.cursor = offset + length as usize;
92+
let app_header = ApplicationHeader {
93+
version: (self.read_u8()?, self.read_u8()?),
94+
unit: self.read_u8()?,
95+
density: (self.read_u16()?, self.read_u16()?),
96+
thumbnail: (self.read_u8()?, self.read_u8()?),
97+
};
8798

88-
Ok(())
99+
ensure!(self.cursor == offset + length);
100+
101+
Ok(app_header)
89102
}
90103

91104
fn parse_quantization_table(&mut self) -> Result<QuantizationTable> {
@@ -148,28 +161,19 @@ impl<'a> JpegDecoder<'a> {
148161
let length = self.read_u16()? as usize;
149162

150163
let flag = self.read_u8()?;
164+
let code_lengths = self.read_fixed_array::<16, _>(Self::read_u8)?;
165+
let num_values = code_lengths.iter().sum::<u8>();
166+
let values = self.read_vec(num_values as usize, Self::read_u8)?;
151167

152-
let huffman_table = HuffmanTable {
168+
let ht = HuffmanTable {
153169
flag,
154-
code_lengths: {
155-
let code_lengths = Range {
156-
start: self.cursor,
157-
end: self.cursor + 16,
158-
};
159-
160-
self.cursor += 16;
161-
162-
code_lengths
163-
},
164-
symbols: Range {
165-
start: self.cursor,
166-
end: offset + length,
167-
},
170+
code_lengths,
171+
values,
168172
};
169173

170-
self.cursor = offset + length;
174+
ensure!(self.cursor == offset + length);
171175

172-
Ok(huffman_table)
176+
Ok(ht)
173177
}
174178

175179
fn parse_start_of_scan(&mut self) -> Result<StartOfScan> {
@@ -192,35 +196,37 @@ impl<'a> JpegDecoder<'a> {
192196
Ok(start_of_scan)
193197
}
194198

195-
fn parse_image_data(&mut self) -> Result<Range<usize>> {
196-
let range = Range {
197-
start: self.cursor,
198-
end: {
199-
while self.peek_slice(2)? != [0xFF, 0xD9] {
200-
self.cursor += 1;
201-
}
199+
fn parse_image_data(&mut self) -> Result<&'a [u8]> {
200+
let len = self.count_until(|this| Ok(this.peek_slice(2)? != [0xFF, 0xD9]))?;
202201

203-
self.cursor
204-
},
205-
};
206-
207-
Ok(range)
202+
self.read_slice(len)
208203
}
209204

210205
impl_read_for_datatype!(read_u8, u8);
211206
impl_read_for_datatype!(read_u16, u16);
212207
impl_read_for_datatype!(read_marker, Marker);
213208
impl_read_slice!();
209+
210+
/// counts the number of bytes until the reader reaches term function
211+
fn count_until(&self, term_fn: impl Fn(&Self) -> Result<bool>) -> Result<usize> {
212+
let mut len = 0;
213+
214+
while !term_fn(self)? {
215+
len += 1;
216+
}
217+
218+
Ok(len)
219+
}
214220
}
215221

216-
// #[cfg(test)]
217-
// mod tests {
218-
// use super::*;
222+
#[cfg(test)]
223+
mod tests {
224+
use super::*;
219225

220-
// #[test]
221-
// fn test_decode_taxi_zone_map_manhattan() {
222-
// let data = std::fs::read("./tests/taxi_zone_map_manhattan.jpg").unwrap();
226+
#[test]
227+
fn test_decode_taxi_zone_map_manhattan() {
228+
let data = std::fs::read("./tests/taxi_zone_map_manhattan.jpg").unwrap();
223229

224-
// let _ = JpegDecoder::new(&data).decode().unwrap();
225-
// }
226-
// }
230+
let _ = JpegDecoder::new(&data).decode().unwrap();
231+
}
232+
}

src/jpeg/grammar.rs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
use crate::image::grammar::{ColorType, ImageExt};
22
use anyhow::bail;
3-
use std::{
4-
borrow::Cow,
5-
ops::{Range, RangeInclusive},
6-
};
3+
use std::{borrow::Cow, ops::RangeInclusive};
74

85
pub type Marker = u16;
96

7+
#[derive(Debug)]
8+
pub struct ApplicationHeader {
9+
pub version: (u8, u8),
10+
pub unit: u8,
11+
pub density: (u16, u16),
12+
pub thumbnail: (u8, u8),
13+
}
14+
1015
#[derive(Debug, Clone, Copy)]
1116
pub enum Precision {
1217
Eight = 1,
@@ -42,11 +47,30 @@ impl QuantizationTable {
4247
}
4348
}
4449

50+
pub enum HuffmanTableClass {
51+
AC,
52+
DC,
53+
}
54+
4555
#[derive(Debug)]
4656
pub struct HuffmanTable {
4757
pub flag: u8,
48-
pub code_lengths: Range<usize>,
49-
pub symbols: Range<usize>,
58+
pub code_lengths: [u8; 16],
59+
pub values: Vec<u8>,
60+
}
61+
62+
impl HuffmanTable {
63+
pub fn table_class(&self) -> HuffmanTableClass {
64+
if (self.flag >> 4) == 1 {
65+
return HuffmanTableClass::AC;
66+
}
67+
68+
HuffmanTableClass::DC
69+
}
70+
71+
pub const fn table_identifier(&self) -> u8 {
72+
self.flag & 0b1111
73+
}
5074
}
5175

5276
#[derive(Debug)]
@@ -103,12 +127,13 @@ pub struct StartOfScan {
103127
}
104128

105129
#[derive(Debug)]
106-
pub struct JFIF {
130+
pub struct JFIF<'a> {
131+
pub application_header: ApplicationHeader,
107132
pub quantization_tables: Vec<QuantizationTable>,
108133
pub huffman_tables: Vec<HuffmanTable>,
109134
pub start_of_frame: StartOfFrame,
110135
pub start_of_scan: StartOfScan,
111-
pub image_data: Range<usize>,
136+
pub image_data: &'a [u8],
112137
}
113138

114139
#[derive(Debug)]

src/jpeg/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
pub use decoder::*;
1+
mod decoder;
22

33
pub mod grammar;
4-
5-
mod decoder;
4+
pub use decoder::*;

src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,8 @@ pub mod jpeg;
99
pub mod png;
1010
pub mod renderer;
1111
pub mod util;
12+
13+
mod bitreader;
14+
pub mod event_log;
15+
pub(crate) mod impl_read;
16+
pub mod test_file_parser;

src/png/decoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ impl<'a> PngDecoder<'a> {
243243
#[cfg(test)]
244244
mod tests {
245245
use super::*;
246-
use crate::{image::grammar::ImageExt, util::test_file_parser::parse_test_file};
246+
use crate::{image::grammar::ImageExt, test_file_parser::parse_test_file};
247247
use anyhow::anyhow;
248248
use image::ImageReader;
249249
use pretty_assertions::assert_eq;

0 commit comments

Comments
 (0)