1extern crate byteorder;
2
3use byteorder::{LittleEndian, ReadBytesExt};
4
5use std::convert::{From, AsRef};
6use std::error::Error;
7use std::fmt;
8use std::io::{self, Cursor, Read, Write, SeekFrom, Seek};
9
10use {BmpHeader, BmpDibHeader, CompressionType, Image, Pixel};
11use BmpVersion::*;
12
13use self::BmpErrorKind::*;
14
15pub type BmpResult<T> = Result<T, BmpError>;
17
18#[derive(Debug)]
20pub enum BmpErrorKind {
21 WrongMagicNumbers,
22 UnsupportedBitsPerPixel,
23 UnsupportedCompressionType,
24 UnsupportedBmpVersion,
25 Other,
26 BmpIoError(io::Error),
27 BmpByteorderError(byteorder::Error),
28}
29
30#[derive(Debug)]
32pub struct BmpError {
33 pub kind: BmpErrorKind,
34 pub details: String,
35}
36
37impl BmpError {
38 fn new<T: AsRef<str>>(kind: BmpErrorKind, details: T) -> BmpError {
39 let description = match kind {
40 WrongMagicNumbers => "Wrong magic numbers",
41 UnsupportedBitsPerPixel => "Unsupported bits per pixel",
42 UnsupportedCompressionType => "Unsupported compression type",
43 UnsupportedBmpVersion => "Unsupported BMP version",
44 _ => "BMP Error",
45 };
46
47 BmpError {
48 kind: kind,
49 details: format!("{}: {}", description, details.as_ref())
50 }
51 }
52}
53
54impl fmt::Display for BmpError {
55 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
56 match self.kind {
57 BmpIoError(ref error) => return error.fmt(fmt),
58 _ => write!(fmt, "{}", self.description())
59 }
60 }
61}
62
63impl From<io::Error> for BmpError {
64 fn from(err: io::Error) -> BmpError {
65 BmpError::new(BmpIoError(err), "Io Error")
66 }
67}
68
69impl From<byteorder::Error> for BmpError {
70 fn from(err: byteorder::Error) -> BmpError {
71 BmpError::new(BmpByteorderError(err), "Byteorder Error")
72 }
73}
74
75impl Error for BmpError {
76 fn description(&self) -> &str {
77 match self.kind {
78 BmpIoError(ref e) => Error::description(e),
79 BmpByteorderError(ref e) => Error::description(e),
80 _ => &self.details
81 }
82 }
83}
84
85pub fn decode_image(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<Image> {
86 try!(read_bmp_id(bmp_data));
87 let header = try!(read_bmp_header(bmp_data));
88 let dib_header = try!(read_bmp_dib_header(bmp_data));
89
90 let color_palette = try!(read_color_palette(bmp_data, &dib_header));
91
92 let width = dib_header.width.abs() as u32;
93 let height = dib_header.height.abs() as u32;
94 let padding = width % 4;
95
96 let data = match color_palette {
97 Some(ref palette) => try!(
98 read_indexes(bmp_data.get_mut(), &palette, width as usize, height as usize,
99 dib_header.bits_per_pixel, header.pixel_offset as usize)
100 ),
101 None => try!(
102 read_pixels(bmp_data, width, height, header.pixel_offset, padding as i64)
103 )
104 };
105
106 let image = Image {
107 header: header,
108 dib_header: dib_header,
109 color_palette: color_palette,
110 width: width,
111 height: height,
112 padding: padding,
113 data: data
114 };
115
116 Ok(image)
117}
118
119fn read_bmp_id(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<()> {
120 let mut bm = [0, 0];
121 try!(bmp_data.read(&mut bm));
122
123 if bm == b"BM"[..] {
124 Ok(())
125 } else {
126 Err(BmpError::new(WrongMagicNumbers, format!("Expected [66, 77], but was {:?}", bm)))
127 }
128}
129
130fn read_bmp_header(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<BmpHeader> {
131 let header = BmpHeader {
132 file_size: try!(bmp_data.read_u32::<LittleEndian>()),
133 creator1: try!(bmp_data.read_u16::<LittleEndian>()),
134 creator2: try!(bmp_data.read_u16::<LittleEndian>()),
135 pixel_offset: try!(bmp_data.read_u32::<LittleEndian>()),
136 };
137
138 Ok(header)
139}
140
141fn read_bmp_dib_header(bmp_data: &mut Cursor<Vec<u8>>) -> BmpResult<BmpDibHeader> {
142 let dib_header = BmpDibHeader {
143 header_size: try!(bmp_data.read_u32::<LittleEndian>()),
144 width: try!(bmp_data.read_i32::<LittleEndian>()),
145 height: try!(bmp_data.read_i32::<LittleEndian>()),
146 num_planes: try!(bmp_data.read_u16::<LittleEndian>()),
147 bits_per_pixel: try!(bmp_data.read_u16::<LittleEndian>()),
148 compress_type: try!(bmp_data.read_u32::<LittleEndian>()),
149 data_size: try!(bmp_data.read_u32::<LittleEndian>()),
150 hres: try!(bmp_data.read_i32::<LittleEndian>()),
151 vres: try!(bmp_data.read_i32::<LittleEndian>()),
152 num_colors: try!(bmp_data.read_u32::<LittleEndian>()),
153 num_imp_colors: try!(bmp_data.read_u32::<LittleEndian>()),
154 };
155
156 match dib_header.header_size {
157 12 => return Err(BmpError::new(UnsupportedBmpVersion, Version2)),
159 40 if dib_header.compress_type == 3 =>
161 return Err(BmpError::new(UnsupportedBmpVersion, Version3NT)),
162 108 | _ => ()
164 }
165
166 match dib_header.bits_per_pixel {
167 1 | 4 | 8 | 24 => (),
169 other => return Err(
170 BmpError::new(UnsupportedBitsPerPixel, format!("{}", other))
171 )
172 }
173
174 match CompressionType::from_u32(dib_header.compress_type) {
175 CompressionType::Uncompressed => (),
176 other => return Err(BmpError::new(UnsupportedCompressionType, other)),
177 }
178
179 Ok(dib_header)
180}
181
182fn read_color_palette(bmp_data: &mut Cursor<Vec<u8>>, dh: &BmpDibHeader) ->
183 BmpResult<Option<Vec<Pixel>>> {
184 let num_entries = match dh.bits_per_pixel {
185 _ if dh.num_colors != 0 => dh.num_colors as usize,
187 bpp @ 1 | bpp @ 4 | bpp @ 8 => 1 << bpp,
189 _ => return Ok(None)
190 };
191
192 let num_bytes = match dh.header_size {
193 40 | 108 => 4,
195 _ => return Err(BmpError::new(UnsupportedBmpVersion, Version2))
197 };
198
199 let mut px = &mut [0; 4][0 .. num_bytes as usize];
200 let mut color_palette = Vec::with_capacity(num_entries);
201 for _ in 0 .. num_entries {
202 try!(bmp_data.read(&mut px));
203 color_palette.push(px!(px[2], px[1], px[0]));
204 }
205
206 Ok(Some(color_palette))
207}
208
209fn read_indexes(bmp_data: &mut Vec<u8>, palette: &Vec<Pixel>,
210 width: usize, height: usize, bpp: u16, offset: usize) -> BmpResult<Vec<Pixel>> {
211 let mut data = Vec::with_capacity(height * width);
212 let bytes_per_row = (width as f64 / (8.0 / bpp as f64)).ceil() as usize;
214 for y in 0 .. height {
215 let padding = match bytes_per_row % 4 {
216 0 => 0,
217 other => 4 - other
218 };
219 let start = offset + (bytes_per_row + padding) * y;
220 let bytes = &bmp_data[start .. start + bytes_per_row];
221
222 for i in bit_index(&bytes, bpp as usize, width as usize) {
223 data.push(palette[i]);
224 }
225 }
226 Ok(data)
227}
228
229fn read_pixels(bmp_data: &mut Cursor<Vec<u8>>, width: u32, height: u32,
230 offset: u32, padding: i64) -> BmpResult<Vec<Pixel>> {
231 let mut data = Vec::with_capacity((height * width) as usize);
232 try!(bmp_data.seek(SeekFrom::Start(offset as u64)));
234 let mut px = [0; 3];
236 for _ in 0 .. height {
237 for _ in 0 .. width {
238 try!(bmp_data.read(&mut px));
239 data.push(px!(px[2], px[1], px[0]));
240 }
241 try!(bmp_data.seek(SeekFrom::Current(padding)));
243 }
244 Ok(data)
245}
246
247const BITS: usize = 8;
248
249#[derive(Debug)]
250struct BitIndex<'a> {
251 size: usize,
252 nbits: usize,
253 bits_left: usize,
254 mask: u8,
255 bytes: &'a [u8],
256 index: usize,
257}
258
259fn bit_index<'a>(bytes: &'a [u8], nbits: usize, size: usize) -> BitIndex {
260 let bits_left = BITS - nbits;
261 BitIndex {
262 size: size,
263 nbits: nbits,
264 bits_left: bits_left,
265 mask: (!0 as u8 >> bits_left),
266 bytes: bytes,
267 index: 0,
268 }
269}
270
271impl<'a> Iterator for BitIndex<'a> {
272 type Item = usize;
273
274 fn next(&mut self) -> Option<usize> {
275 let n = self.index / BITS;
276 let offset = self.bits_left - self.index % BITS;
277
278 self.index += self.nbits;
279
280 if self.size == 0 {
281 None
282 } else {
283 self.size -= 1;
284 self.bytes.get(n).map(|&block|
285 ((block & self.mask << offset) >> offset) as usize
286 )
287 }
288 }
289}
290
291#[test]
292fn test_calculate_bit_index() {
293 let bytes = vec![0b1000_0001, 0b1111_0001];
294
295 let mut bi = bit_index(&bytes, 1, 15);
296 assert_eq!(bi.next(), Some(1));
297 assert_eq!(bi.next(), Some(0));
298 assert_eq!(bi.next(), Some(0));
299 assert_eq!(bi.next(), Some(0));
300 assert_eq!(bi.next(), Some(0));
301 assert_eq!(bi.next(), Some(0));
302 assert_eq!(bi.next(), Some(0));
303 assert_eq!(bi.next(), Some(1));
304 assert_eq!(bi.next(), Some(1));
305 assert_eq!(bi.next(), Some(1));
306 assert_eq!(bi.next(), Some(1));
307 assert_eq!(bi.next(), Some(1));
308 assert_eq!(bi.next(), Some(0));
309 assert_eq!(bi.next(), Some(0));
310 assert_eq!(bi.next(), Some(0));
311 assert_eq!(bi.next(), None);
312 assert_eq!(bi.next(), None);
313
314 let mut bi = bit_index(&bytes, 4, 4);
315 assert_eq!(bi.next(), Some(0b1000));
316 assert_eq!(bi.next(), Some(0b0001));
317 assert_eq!(bi.next(), Some(0b1111));
318 assert_eq!(bi.next(), Some(0b0001));
319 assert_eq!(bi.next(), None);
320
321 let mut bi = bit_index(&bytes, 8, 2);
322 assert_eq!(bi.next(), Some(0b1000_0001));
323 assert_eq!(bi.next(), Some(0b1111_0001));
324 assert_eq!(bi.next(), None);
325}