bmp_encoder/
decoder.rs

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
15/// A result type, either containing an `Image` or a `BmpError`.
16pub type BmpResult<T> = Result<T, BmpError>;
17
18/// The different kinds of possible BMP errors.
19#[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/// The error type returned if the decoding of an image from disk fails.
31#[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        // BMPv2 has a header size of 12 bytes
158        12 => return Err(BmpError::new(UnsupportedBmpVersion, Version2)),
159        // BMPv3 has a header size of 40 bytes, it is NT if the compression type is 3
160        40 if dib_header.compress_type == 3 =>
161            return Err(BmpError::new(UnsupportedBmpVersion, Version3NT)),
162        // BMPv4 has more data in its header, it is currently ignored but we still try to parse it
163        108 | _ => ()
164    }
165
166    match dib_header.bits_per_pixel {
167        // Currently supported
168        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        // We have a color_palette if there if num_colors in the dib header is not zero
186        _ if dh.num_colors != 0 => dh.num_colors as usize,
187        // Or if there are 8 or less bits per pixel
188        bpp @ 1 | bpp @ 4 | bpp @ 8 => 1 << bpp,
189        _ => return Ok(None)
190    };
191
192    let num_bytes = match dh.header_size {
193        // Each entry in the color_palette is four bytes for Version 3 or 4
194        40 | 108 => 4,
195        // Three bytes for Version two. Though, this is currently not supported
196        _ => 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    // Number of bytes to read from each row, varies based on bits_per_pixel
213    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    // seek until data
233    try!(bmp_data.seek(SeekFrom::Start(offset as u64)));
234    // read pixels until padding
235    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        // seek padding
242        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}