aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--src/encode.rs34
-rw-r--r--src/lib.rs32
3 files changed, 54 insertions, 14 deletions
diff --git a/Cargo.toml b/Cargo.toml
index d3ca6e4..d343a43 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,3 +7,5 @@ edition = "2018"
7# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8 8
9[dependencies] 9[dependencies]
10byteorder = "1.4.2"
11bitvec = "0.21.0"
diff --git a/src/encode.rs b/src/encode.rs
new file mode 100644
index 0000000..24d3792
--- /dev/null
+++ b/src/encode.rs
@@ -0,0 +1,34 @@
1use std::io;
2
3use bitvec::prelude::*;
4use bitvec::slice::BitSlice;
5use byteorder::{LittleEndian, WriteBytesExt};
6
7use crate::Image;
8
9pub fn encode_image(obi_image: Image) -> io::Result<Vec<u8>> {
10 let mut obi_data = Vec::with_capacity(obi_image.file_header.file_size as usize);
11
12 // file header
13 let file_header = obi_image.file_header;
14 obi_data.write_u16::<LittleEndian>(file_header.version)?;
15 obi_data.write_u32::<LittleEndian>(file_header.file_size)?;
16 obi_data.write_u32::<LittleEndian>(file_header.data_offset)?;
17
18 // image info header
19 let image_info_header = obi_image.image_info_header;
20 obi_data.write_u32::<LittleEndian>(image_info_header.width)?;
21 obi_data.write_u32::<LittleEndian>(image_info_header.height)?;
22 obi_data.write_u32::<LittleEndian>(image_info_header.compression_type)?;
23 obi_data.write_u32::<LittleEndian>(image_info_header.post_compression_size)?;
24
25 // pixmap data
26 let pixmap = obi_image.data;
27 for byte in pixmap.chunks(8) {
28 let bits_as_u8 = byte.iter().map(|&e| e as u8).collect::<Vec<_>>();
29 let slice = BitSlice::<Lsb0, _>::from_slice(&bits_as_u8).unwrap();
30 obi_data.write_u8(slice.load::<u8>())?;
31 }
32
33 return Ok(obi_data);
34}
diff --git a/src/lib.rs b/src/lib.rs
index 1471aa8..61ca7a8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,11 +1,7 @@
1#![allow(unreachable_patterns)] 1#![allow(unreachable_patterns)]
2#![allow(non_snake_case)] 2#![allow(non_snake_case)]
3#[non_exhaustive] 3
4#[derive(Copy, Clone, Debug, PartialEq, Eq)] 4pub mod encode;
5pub enum Pixel {
6 On,
7 Off,
8}
9 5
10#[non_exhaustive] 6#[non_exhaustive]
11#[derive(Copy, Clone, Debug, PartialEq)] 7#[derive(Copy, Clone, Debug, PartialEq)]
@@ -16,16 +12,16 @@ pub enum OBIVersion {
16impl OBIVersion { 12impl OBIVersion {
17 pub fn header_size(&self) -> u32 { 13 pub fn header_size(&self) -> u32 {
18 match self { 14 match self {
19 One => 26, 15 OBIVersion::One => 26,
20 } 16 }
21 } 17 }
22} 18}
23 19
24#[non_exhaustive] 20#[non_exhaustive]
25pub struct FileHeader { 21pub struct FileHeader {
26 pub version: u16,
27 pub file_size: u32, 22 pub file_size: u32,
28 pub data_offset: u32, 23 pub data_offset: u32,
24 pub version: u16,
29} 25}
30 26
31impl FileHeader { 27impl FileHeader {
@@ -82,15 +78,19 @@ impl CompressionType {
82pub struct Image { 78pub struct Image {
83 pub file_header: FileHeader, 79 pub file_header: FileHeader,
84 pub image_info_header: ImageInfoHeader, 80 pub image_info_header: ImageInfoHeader,
85 pub data: Vec<Pixel>, 81 pub data: Vec<bool>,
86} 82}
87 83
88impl Image { 84impl Image {
89 pub fn new(width: u32, height: u32) -> Self { 85 pub fn new(width: u32, height: u32) -> Self {
90 let data_size = width * height; 86 // round to the nearest multiple of 8
91 let data = vec![Pixel::Off; data_size as usize]; 87 // convert to number of bytes by dividing by 8
88 let mut data_size = width * height + 7;
89 data_size = data_size - (data_size % 8);
90 let data = vec![false; data_size as usize];
91
92 Self { 92 Self {
93 file_header: FileHeader::new(OBIVersion::One, data_size), 93 file_header: FileHeader::new(OBIVersion::One, data_size / 8),
94 image_info_header: ImageInfoHeader::new(width, height), 94 image_info_header: ImageInfoHeader::new(width, height),
95 data, 95 data,
96 } 96 }
@@ -99,8 +99,12 @@ impl Image {
99 99
100#[cfg(test)] 100#[cfg(test)]
101mod tests { 101mod tests {
102 use super::*;
103 use std::mem::size_of;
104
102 #[test] 105 #[test]
103 fn it_works() { 106 fn size_of_image_info_header() {
104 assert_eq!(2 + 2, 4); 107 let file_header_size = size_of::<ImageInfoHeader>();
108 assert_eq!(16, file_header_size);
105 } 109 }
106} 110}