1use self::autobreak::AutoBreak;
8pub use self::decoder::PnmDecoder;
9pub use self::encoder::PnmEncoder;
10use self::header::HeaderRecord;
11pub use self::header::{
12 ArbitraryHeader, ArbitraryTuplType, BitmapHeader, GraymapHeader, PixmapHeader,
13};
14pub use self::header::{PnmHeader, PnmSubtype, SampleEncoding};
15
16mod autobreak;
17mod decoder;
18mod encoder;
19mod header;
20
21#[cfg(test)]
22mod tests {
23 use super::*;
24 use crate::ExtendedColorType;
25 use crate::ImageDecoder as _;
26 use byteorder_lite::{ByteOrder, NativeEndian};
27
28 fn execute_roundtrip_default(buffer: &[u8], width: u32, height: u32, color: ExtendedColorType) {
29 let mut encoded_buffer = Vec::new();
30
31 {
32 let mut encoder = PnmEncoder::new(&mut encoded_buffer);
33 encoder
34 .encode(buffer, width, height, color)
35 .expect("Failed to encode the image buffer");
36 }
37
38 let (header, loaded_color, loaded_image) = {
39 let decoder = PnmDecoder::new(&encoded_buffer[..]).unwrap();
40 let color_type = decoder.color_type();
41 let mut image = vec![0; decoder.total_bytes() as usize];
42 decoder
43 .read_image(&mut image)
44 .expect("Failed to decode the image");
45 let (_, header) = PnmDecoder::new(&encoded_buffer[..]).unwrap().into_inner();
46 (header, color_type, image)
47 };
48
49 assert_eq!(header.width(), width);
50 assert_eq!(header.height(), height);
51 assert_eq!(ExtendedColorType::from(loaded_color), color);
52 assert_eq!(loaded_image.as_slice(), buffer);
53 }
54
55 fn execute_roundtrip_with_subtype(
56 buffer: &[u8],
57 width: u32,
58 height: u32,
59 color: ExtendedColorType,
60 subtype: PnmSubtype,
61 ) {
62 let mut encoded_buffer = Vec::new();
63
64 {
65 let mut encoder = PnmEncoder::new(&mut encoded_buffer).with_subtype(subtype);
66 encoder
67 .encode(buffer, width, height, color)
68 .expect("Failed to encode the image buffer");
69 }
70
71 let (header, loaded_color, loaded_image) = {
72 let decoder = PnmDecoder::new(&encoded_buffer[..]).unwrap();
73 let color_type = decoder.color_type();
74 let mut image = vec![0; decoder.total_bytes() as usize];
75 decoder
76 .read_image(&mut image)
77 .expect("Failed to decode the image");
78 let (_, header) = PnmDecoder::new(&encoded_buffer[..]).unwrap().into_inner();
79 (header, color_type, image)
80 };
81
82 assert_eq!(header.width(), width);
83 assert_eq!(header.height(), height);
84 assert_eq!(header.subtype(), subtype);
85 assert_eq!(ExtendedColorType::from(loaded_color), color);
86 assert_eq!(loaded_image.as_slice(), buffer);
87 }
88
89 fn execute_roundtrip_u16(buffer: &[u16], width: u32, height: u32, color: ExtendedColorType) {
90 let mut encoded_buffer = Vec::new();
91
92 {
93 let mut encoder = PnmEncoder::new(&mut encoded_buffer);
94 encoder
95 .encode(buffer, width, height, color)
96 .expect("Failed to encode the image buffer");
97 }
98
99 let (header, loaded_color, loaded_image) = {
100 let decoder = PnmDecoder::new(&encoded_buffer[..]).unwrap();
101 let color_type = decoder.color_type();
102 let mut image = vec![0; decoder.total_bytes() as usize];
103 decoder
104 .read_image(&mut image)
105 .expect("Failed to decode the image");
106 let (_, header) = PnmDecoder::new(&encoded_buffer[..]).unwrap().into_inner();
107 (header, color_type, image)
108 };
109
110 let mut buffer_u8 = vec![0; buffer.len() * 2];
111 NativeEndian::write_u16_into(buffer, &mut buffer_u8[..]);
112
113 assert_eq!(header.width(), width);
114 assert_eq!(header.height(), height);
115 assert_eq!(ExtendedColorType::from(loaded_color), color);
116 assert_eq!(loaded_image, buffer_u8);
117 }
118
119 #[test]
120 fn roundtrip_gray() {
121 #[rustfmt::skip]
122 let buf: [u8; 16] = [
123 0, 0, 0, 255,
124 255, 255, 255, 255,
125 255, 0, 255, 0,
126 255, 0, 0, 0,
127 ];
128
129 execute_roundtrip_default(&buf, 4, 4, ExtendedColorType::L8);
130 execute_roundtrip_with_subtype(&buf, 4, 4, ExtendedColorType::L8, PnmSubtype::ArbitraryMap);
131 execute_roundtrip_with_subtype(
132 &buf,
133 4,
134 4,
135 ExtendedColorType::L8,
136 PnmSubtype::Graymap(SampleEncoding::Ascii),
137 );
138 execute_roundtrip_with_subtype(
139 &buf,
140 4,
141 4,
142 ExtendedColorType::L8,
143 PnmSubtype::Graymap(SampleEncoding::Binary),
144 );
145 }
146
147 #[test]
148 fn roundtrip_rgb() {
149 #[rustfmt::skip]
150 let buf: [u8; 27] = [
151 0, 0, 0,
152 0, 0, 255,
153 0, 255, 0,
154 0, 255, 255,
155 255, 0, 0,
156 255, 0, 255,
157 255, 255, 0,
158 255, 255, 255,
159 255, 255, 255,
160 ];
161 execute_roundtrip_default(&buf, 3, 3, ExtendedColorType::Rgb8);
162 execute_roundtrip_with_subtype(
163 &buf,
164 3,
165 3,
166 ExtendedColorType::Rgb8,
167 PnmSubtype::ArbitraryMap,
168 );
169 execute_roundtrip_with_subtype(
170 &buf,
171 3,
172 3,
173 ExtendedColorType::Rgb8,
174 PnmSubtype::Pixmap(SampleEncoding::Binary),
175 );
176 execute_roundtrip_with_subtype(
177 &buf,
178 3,
179 3,
180 ExtendedColorType::Rgb8,
181 PnmSubtype::Pixmap(SampleEncoding::Ascii),
182 );
183 }
184
185 #[test]
186 fn roundtrip_u16() {
187 let buf: [u16; 6] = [0, 1, 0xFFFF, 0x1234, 0x3412, 0xBEAF];
188
189 execute_roundtrip_u16(&buf, 6, 1, ExtendedColorType::L16);
190 }
191}