1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use crate::bit::BitStreamReader;
use crate::{Bmp, BmpError, BmpHeader, B, HEADER_SIZE, M};
use std::io::{Cursor, Read};

impl Bmp {
    /// Read the monochrome bitmap from a Read type, such a File
    pub fn read<T: Read>(mut from: T) -> Result<Self, BmpError> {
        let mut header_bytes = [0u8; HEADER_SIZE as usize];
        from.read_exact(&mut header_bytes)?;
        let header = BmpHeader::read(Cursor::new(&mut header_bytes.to_vec()))?;
        let width = header.width;
        let height = header.height;
        let padding = header.padding() as u8;
        let mut reader = BitStreamReader::new(&mut from);
        let mut row_data = Vec::with_capacity(height as usize);
        let mut width_data = Vec::with_capacity(width as usize);
        for _ in 0..height as usize {
            for _ in 0..width as usize {
                if reader.read(1)? == 1 {
                    width_data.push(true);
                } else {
                    width_data.push(false);
                }
            }
            reader.read(8 - (width % 8) as u8)?;
            reader.read(padding * 8)?;
            row_data.push(width_data.clone());
            width_data.clear();
        }
        row_data.reverse();
        let data = row_data.into_iter().flatten().collect();
        let matrix = Bmp::new(data, width as usize)?;
        Ok(matrix)
    }
}

impl BmpHeader {
    pub fn read<T: Read>(mut from: T) -> Result<Self, BmpError> {
        let b = ReadLE::read_u8(&mut from)?;
        let m = ReadLE::read_u8(&mut from)?;
        let _total_size = ReadLE::read_u32(&mut from)?;
        let _creator1 = ReadLE::read_u16(&mut from)?;
        let _creator2 = ReadLE::read_u16(&mut from)?;
        let pixel_offset = ReadLE::read_u32(&mut from)?;
        let dib_header = ReadLE::read_u32(&mut from)?;
        let width = ReadLE::read_u32(&mut from)?;
        let height = ReadLE::read_u32(&mut from)?;
        let planes = ReadLE::read_u16(&mut from)?;
        let bits_per_pixel = ReadLE::read_u16(&mut from)?;
        let compression = ReadLE::read_u32(&mut from)?;
        let _data_size = ReadLE::read_u32(&mut from)?;
        let _hres = ReadLE::read_u32(&mut from)?;
        let _vres = ReadLE::read_u32(&mut from)?;
        let num_colors = ReadLE::read_u32(&mut from)?;
        let _num_imp_colors = ReadLE::read_u32(&mut from)?;
        let _background_color = ReadLE::read_u32(&mut from)?;
        let _foreground_color = ReadLE::read_u32(&mut from)?;

        if b != B
            || m != M
            || pixel_offset != HEADER_SIZE
            || dib_header != 40u32
            || planes != 1u16
            || bits_per_pixel != 1u16
            || compression != 0u32
            || num_colors != 2u32
        {
            return Err(BmpError::Header);
        }

        Ok(BmpHeader { height, width })
    }
}

impl<R: Read> ReadLE for R {
    fn read_u32(&mut self) -> Result<u32, BmpError> {
        let mut buffer = [0u8; 4];
        self.read_exact(&mut buffer)?;
        Ok(u32::from_le_bytes(buffer))
    }

    fn read_u16(&mut self) -> Result<u16, BmpError> {
        let mut buffer = [0u8; 2];
        self.read_exact(&mut buffer)?;
        Ok(u16::from_le_bytes(buffer))
    }

    fn read_u8(&mut self) -> Result<u8, BmpError> {
        let mut buffer = [0u8];
        self.read_exact(&mut buffer)?;
        Ok(buffer[0])
    }
}

trait ReadLE {
    /// Read a 32-bit uint
    fn read_u32(&mut self) -> Result<u32, BmpError>;
    /// Read a 16-bit uint
    fn read_u16(&mut self) -> Result<u16, BmpError>;
    /// Read a 8-bit uint
    fn read_u8(&mut self) -> Result<u8, BmpError>;
}

#[cfg(test)]
mod test {
    use crate::decode::ReadLE;
    use crate::BmpHeader;
    use std::fs::File;
    use std::io::Cursor;

    #[test]
    fn test_read() {
        let mut cursor = Cursor::new(vec![0u8, 1, 1, 0, 1, 0, 0, 0]);
        assert_eq!(0, ReadLE::read_u8(&mut cursor).unwrap());
        assert_eq!(1, ReadLE::read_u8(&mut cursor).unwrap());
        assert_eq!(1, ReadLE::read_u16(&mut cursor).unwrap());
        assert_eq!(1, ReadLE::read_u32(&mut cursor).unwrap());
    }

    #[test]
    fn test_header() {
        let file = File::open("test_bmp/monochrome_image.bmp").unwrap();
        let bmp_header = BmpHeader::read(file).unwrap();
        assert_eq!(18, bmp_header.width);
        assert_eq!(18, bmp_header.height);

        let file = File::open("test_bmp/test1.bmp").unwrap();
        let bmp_header = BmpHeader::read(file).unwrap();
        assert_eq!(2, bmp_header.width);
        assert_eq!(2, bmp_header.height);
    }
}