diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/decode.rs | 50 | ||||
-rw-r--r-- | src/encode.rs | 11 | ||||
-rw-r--r-- | src/lib.rs | 8 |
3 files changed, 64 insertions, 5 deletions
diff --git a/src/decode.rs b/src/decode.rs new file mode 100644 index 0000000..59dae97 --- /dev/null +++ b/src/decode.rs | |||
@@ -0,0 +1,50 @@ | |||
1 | use std::io::{self, Cursor, Read}; | ||
2 | |||
3 | use bitvec::prelude::*; | ||
4 | use byteorder::{LittleEndian, ReadBytesExt}; | ||
5 | |||
6 | use crate::{FileHeader, Image, ImageInfoHeader}; | ||
7 | |||
8 | pub fn decode_image(obi_data: &mut Cursor<Vec<u8>>) -> io::Result<Image> { | ||
9 | // file header | ||
10 | let version = obi_data.read_u16::<LittleEndian>()?; | ||
11 | let file_size = obi_data.read_u32::<LittleEndian>()?; | ||
12 | let data_offset = obi_data.read_u32::<LittleEndian>()?; | ||
13 | let file_header = FileHeader { | ||
14 | version, | ||
15 | file_size, | ||
16 | data_offset, | ||
17 | }; | ||
18 | |||
19 | // image info header | ||
20 | let width = obi_data.read_u32::<LittleEndian>()?; | ||
21 | let height = obi_data.read_u32::<LittleEndian>()?; | ||
22 | let compression_type = obi_data.read_u32::<LittleEndian>()?; | ||
23 | let post_compression_size = obi_data.read_u32::<LittleEndian>()?; | ||
24 | let image_info_header = ImageInfoHeader { | ||
25 | width, | ||
26 | height, | ||
27 | compression_type, | ||
28 | post_compression_size, | ||
29 | }; | ||
30 | |||
31 | // pixmap data | ||
32 | let mut data_bytes = vec![]; | ||
33 | obi_data.read_to_end(&mut data_bytes)?; | ||
34 | let data = data_bytes | ||
35 | .iter() | ||
36 | .map(|&b| { | ||
37 | BitVec::<Lsb0, u8>::from_element(b) | ||
38 | .into_iter() | ||
39 | .map(|e| e as bool) | ||
40 | .collect::<Vec<bool>>() | ||
41 | }) | ||
42 | .flatten() | ||
43 | .collect::<Vec<_>>(); | ||
44 | |||
45 | return Ok(Image { | ||
46 | file_header, | ||
47 | image_info_header, | ||
48 | data, | ||
49 | }); | ||
50 | } | ||
diff --git a/src/encode.rs b/src/encode.rs index 24d3792..e5760a8 100644 --- a/src/encode.rs +++ b/src/encode.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | use std::io; | 1 | use std::io; |
2 | 2 | ||
3 | use bitvec::prelude::*; | 3 | use bitvec::{prelude::*, vec::BitVec}; |
4 | use bitvec::slice::BitSlice; | ||
5 | use byteorder::{LittleEndian, WriteBytesExt}; | 4 | use byteorder::{LittleEndian, WriteBytesExt}; |
6 | 5 | ||
7 | use crate::Image; | 6 | use crate::Image; |
@@ -25,9 +24,11 @@ pub fn encode_image(obi_image: Image) -> io::Result<Vec<u8>> { | |||
25 | // pixmap data | 24 | // pixmap data |
26 | let pixmap = obi_image.data; | 25 | let pixmap = obi_image.data; |
27 | for byte in pixmap.chunks(8) { | 26 | for byte in pixmap.chunks(8) { |
28 | let bits_as_u8 = byte.iter().map(|&e| e as u8).collect::<Vec<_>>(); | 27 | let mut bv = BitVec::<Lsb0, u8>::new(); |
29 | let slice = BitSlice::<Lsb0, _>::from_slice(&bits_as_u8).unwrap(); | 28 | for &b in byte { |
30 | obi_data.write_u8(slice.load::<u8>())?; | 29 | bv.push(b); |
30 | } | ||
31 | obi_data.write_u8(bv.load::<u8>())?; | ||
31 | } | 32 | } |
32 | 33 | ||
33 | return Ok(obi_data); | 34 | return Ok(obi_data); |
@@ -1,6 +1,7 @@ | |||
1 | #![allow(unreachable_patterns)] | 1 | #![allow(unreachable_patterns)] |
2 | #![allow(non_snake_case)] | 2 | #![allow(non_snake_case)] |
3 | 3 | ||
4 | pub mod decode; | ||
4 | pub mod encode; | 5 | pub mod encode; |
5 | 6 | ||
6 | #[non_exhaustive] | 7 | #[non_exhaustive] |
@@ -107,4 +108,11 @@ mod tests { | |||
107 | let file_header_size = size_of::<ImageInfoHeader>(); | 108 | let file_header_size = size_of::<ImageInfoHeader>(); |
108 | assert_eq!(16, file_header_size); | 109 | assert_eq!(16, file_header_size); |
109 | } | 110 | } |
111 | |||
112 | #[test] | ||
113 | fn encode_decode() { | ||
114 | let img = Image::new(100, 80); | ||
115 | let encoded = encode::encode_image(img).unwrap(); | ||
116 | assert_eq!(encoded.len(), 1026); | ||
117 | } | ||
110 | } | 118 | } |