Skip to content

Commit 845d280

Browse files
Define image reader trait to support other file formats
1 parent 930d666 commit 845d280

13 files changed

Lines changed: 159 additions & 78 deletions

File tree

src/bin/decode.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ fn main() -> Result<()> {
1616
let image_path = args
1717
.next()
1818
.ok_or_else(|| anyhow!("Failed to read image path"))?;
19+
//
20+
// let image_kind = args.next().and_then(|image_kind| {
21+
// match image_kind.as_bytes() {
22+
// b"jpeg" => {}
23+
// b"png" => {}
24+
// }
25+
// });
1926

2027
let content = std::fs::read(image_path)?;
2128

src/image/grammar.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use anyhow::bail;
2+
use std::borrow::Cow;
3+
4+
#[derive(Debug)]
5+
pub enum ImageKind {
6+
Png,
7+
Jpeg,
8+
}
9+
10+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
11+
pub enum ColorType {
12+
Grayscale = 0,
13+
RGB = 2,
14+
Palette = 3,
15+
GrayscaleAlpha = 4,
16+
RGBA = 6,
17+
}
18+
19+
impl ColorType {
20+
pub(crate) const fn num_channels(&self) -> u8 {
21+
match self {
22+
Self::Grayscale => 1,
23+
Self::RGB => 3,
24+
Self::Palette => 1,
25+
Self::GrayscaleAlpha => 2,
26+
Self::RGBA => 4,
27+
}
28+
}
29+
}
30+
31+
impl TryFrom<u8> for ColorType {
32+
type Error = anyhow::Error;
33+
34+
fn try_from(value: u8) -> anyhow::Result<Self, Self::Error> {
35+
let val = match value {
36+
0 => Self::Grayscale,
37+
2 => Self::RGB,
38+
3 => Self::Palette,
39+
4 => Self::GrayscaleAlpha,
40+
6 => Self::RGBA,
41+
foreign => bail!("Unrecognized color type: {}", foreign),
42+
};
43+
44+
Ok(val)
45+
}
46+
}
47+
48+
pub type Image = Box<dyn ImageExt>;
49+
50+
pub trait ImageExt {
51+
fn width(&self) -> u32;
52+
53+
fn height(&self) -> u32;
54+
55+
fn dimensions(&self) -> (u32, u32) {
56+
(self.width(), self.height())
57+
}
58+
59+
fn gamma(&self) -> u32;
60+
61+
fn color_type(&self) -> ColorType;
62+
63+
fn rgb8(&self) -> Cow<'_, [u8]>;
64+
65+
fn rgba8(&self) -> Cow<'_, [u8]>;
66+
67+
fn bitmap(&self) -> Cow<'_, [u32]>;
68+
}

src/image/mod.rs

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

src/image/reader.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use crate::{
2+
image::grammar::{
3+
Image,
4+
ImageExt,
5+
ImageKind,
6+
},
7+
png::PngDecoder,
8+
};
9+
use anyhow::Result;
10+
use std::path::Path;
11+
12+
#[derive(Debug)]
13+
pub struct ImageReader;
14+
15+
impl ImageReader {
16+
pub fn read_from_path(path: impl AsRef<Path>, image_kind: Option<ImageKind>) -> Result<Image> {
17+
let data = std::fs::read(path)?;
18+
19+
let image_kind = image_kind.expect("how do you infer which image decoder to run?");
20+
21+
let image: Box<dyn ImageExt> = Box::new(match image_kind {
22+
ImageKind::Png => PngDecoder::new(&data).decode()?,
23+
ImageKind::Jpeg => {
24+
todo!();
25+
}
26+
});
27+
28+
Ok(image)
29+
}
30+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use wasm_bindgen::prelude::*;
55

66
pub mod font;
7+
pub mod image;
78
pub mod png;
89
pub mod renderer;
910
pub mod util;

src/main.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use anyhow::{
33
Result,
44
};
55
use iris::{
6-
png::PngDecoder,
6+
image::{
7+
grammar::ImageKind,
8+
ImageReader,
9+
},
710
renderer,
811
};
912
use pollster::block_on;
@@ -14,11 +17,9 @@ fn main() -> Result<()> {
1417
.next()
1518
.ok_or_else(|| anyhow!("Failed to read image path"))?;
1619

17-
let content = std::fs::read(image_path)?;
18-
let mut decoder = PngDecoder::new(&content);
19-
let png = decoder.decode()?;
20+
let image = ImageReader::read_from_path(&image_path, Some(ImageKind::Png))?;
2021

21-
let _ = block_on(renderer::run(png));
22+
let _ = block_on(renderer::run(image));
2223

2324
Ok(())
2425
}

src/png/decoder.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ use crate::util::event_log::{
55
};
66
use crate::{
77
eof,
8+
image::grammar::ColorType,
89
png::{
910
crc32::compute_crc,
1011
grammar::{
1112
Chunk,
12-
ColorType,
1313
ImageHeader,
1414
Png,
1515
},
@@ -273,7 +273,10 @@ impl<'a> PngDecoder<'a> {
273273
#[cfg(test)]
274274
mod tests {
275275
use super::*;
276-
use crate::util::test_file_parser::parse_test_file;
276+
use crate::{
277+
image::grammar::ImageExt,
278+
util::test_file_parser::parse_test_file,
279+
};
277280
use anyhow::anyhow;
278281
use image::ImageReader;
279282
use pretty_assertions::assert_eq;
@@ -298,7 +301,7 @@ mod tests {
298301

299302
let content = std::fs::read(&path)?;
300303
let generated_png = PngDecoder::new(&content).decode()?;
301-
let generated_rgbs = generated_png.to_rgb8().to_vec();
304+
let generated_rgbs = generated_png.rgb8().to_vec();
302305

303306
assert_eq!(
304307
reference_rgbs,

src/png/grammar.rs

Lines changed: 14 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
use crate::image::grammar::{
2+
ColorType,
3+
ImageExt,
4+
};
15
use anyhow::{
26
bail,
37
Result,
@@ -43,44 +47,6 @@ impl ImageHeader {
4347
}
4448
}
4549

46-
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
47-
pub enum ColorType {
48-
Grayscale = 0,
49-
RGB = 2,
50-
Palette = 3,
51-
GrayscaleAlpha = 4,
52-
RGBA = 6,
53-
}
54-
55-
impl ColorType {
56-
pub(crate) const fn num_channels(&self) -> u8 {
57-
match self {
58-
Self::Grayscale => 1,
59-
Self::RGB => 3,
60-
Self::Palette => 1,
61-
Self::GrayscaleAlpha => 2,
62-
Self::RGBA => 4,
63-
}
64-
}
65-
}
66-
67-
impl TryFrom<u8> for ColorType {
68-
type Error = anyhow::Error;
69-
70-
fn try_from(value: u8) -> Result<Self, Self::Error> {
71-
let val = match value {
72-
0 => Self::Grayscale,
73-
2 => Self::RGB,
74-
3 => Self::Palette,
75-
4 => Self::GrayscaleAlpha,
76-
6 => Self::RGBA,
77-
foreign => bail!("Unrecognized color type: {}", foreign),
78-
};
79-
80-
Ok(val)
81-
}
82-
}
83-
8450
#[derive(Debug)]
8551
pub enum Filter {
8652
None = 0,
@@ -114,29 +80,24 @@ pub struct Png {
11480
pub(crate) pixel_buffer: Vec<u8>,
11581
}
11682

117-
impl Png {
118-
pub const fn width(&self) -> u32 {
83+
impl ImageExt for Png {
84+
fn width(&self) -> u32 {
11985
self.image_header.width
12086
}
12187

122-
pub const fn height(&self) -> u32 {
88+
fn height(&self) -> u32 {
12389
self.image_header.height
12490
}
12591

126-
/// The dimensions of the image (width, height).
127-
pub const fn dimensions(&self) -> (u32, u32) {
128-
(self.width(), self.height())
129-
}
130-
131-
pub const fn gamma(&self) -> u32 {
92+
fn gamma(&self) -> u32 {
13293
self.gamma
13394
}
13495

135-
pub const fn color_type(&self) -> ColorType {
96+
fn color_type(&self) -> ColorType {
13697
self.image_header.color_type
13798
}
13899

139-
pub fn to_rgb8(&self) -> Cow<'_, [u8]> {
100+
fn rgb8(&self) -> Cow<'_, [u8]> {
140101
match self.color_type() {
141102
ColorType::RGB => Cow::from(&self.pixel_buffer),
142103
ColorType::RGBA => {
@@ -170,7 +131,7 @@ impl Png {
170131
}
171132
}
172133

173-
pub fn to_rgba8(&self) -> Cow<'_, [u8]> {
134+
fn rgba8(&self) -> Cow<'_, [u8]> {
174135
match self.color_type() {
175136
ColorType::RGBA => Cow::from(&self.pixel_buffer),
176137
ColorType::RGB => {
@@ -204,7 +165,7 @@ impl Png {
204165
}
205166
}
206167

207-
pub fn to_bitmap(&self) -> Cow<'_, [u32]> {
168+
fn bitmap(&self) -> Cow<'_, [u32]> {
208169
match self.color_type() {
209170
ColorType::RGB => {
210171
let b = self
@@ -245,7 +206,9 @@ impl Png {
245206
_ => todo!("What do other color type pixels look like?"),
246207
}
247208
}
209+
}
248210

211+
impl Png {
249212
#[cfg(test)]
250213
#[allow(dead_code)]
251214
pub(crate) fn write_to_binary_blob(&self, path: &str) -> Result<()> {

src/png/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub use decoder::*;
22
pub use encoder::*;
3+
34
pub mod grammar;
45
pub mod ssim;
56

src/png/ssim.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#![allow(clippy::suboptimal_flops)]
22

3-
use crate::png::grammar::{
4-
ColorType,
5-
Png,
3+
use crate::{
4+
image::grammar::{
5+
ColorType,
6+
ImageExt,
7+
},
8+
png::grammar::Png,
69
};
710
use anyhow::ensure;
811

0 commit comments

Comments
 (0)