bmp_encoder/
encoder.rs

1extern crate byteorder;
2use byteorder::{LittleEndian, WriteBytesExt};
3
4use std::io::{self, Write};
5
6use Image;
7
8const B: u8 = 66;
9const M: u8 = 77;
10
11pub fn encode_image(bmp_image: &Image) -> io::Result<Vec<u8>> {
12    let mut bmp_data = Vec::with_capacity(bmp_image.header.file_size as usize);
13
14    try!(write_header(&mut bmp_data, bmp_image));
15    try!(write_data(&mut bmp_data, bmp_image));
16    Ok(bmp_data)
17}
18
19fn write_header(bmp_data: &mut Vec<u8>, img: &Image) -> io::Result<()> {
20    let header = &img.header;
21    let dib_header = &img.dib_header;
22    let (header_size, data_size) = file_size!(24, img.width, img.height);
23
24    try!(io::Write::write(bmp_data, &[B, M]));
25
26    try!(bmp_data.write_u32::<LittleEndian>(header_size + data_size));
27    try!(bmp_data.write_u16::<LittleEndian>(header.creator1));
28    try!(bmp_data.write_u16::<LittleEndian>(header.creator2));
29    try!(bmp_data.write_u32::<LittleEndian>(header_size)); // pixel_offset
30
31    try!(bmp_data.write_u32::<LittleEndian>(dib_header.header_size));
32    try!(bmp_data.write_i32::<LittleEndian>(dib_header.width));
33    try!(bmp_data.write_i32::<LittleEndian>(dib_header.height));
34    try!(bmp_data.write_u16::<LittleEndian>(1));  // num_planes
35    try!(bmp_data.write_u16::<LittleEndian>(24)); // bits_per_pixel
36    try!(bmp_data.write_u32::<LittleEndian>(0));  // compress_type
37    try!(bmp_data.write_u32::<LittleEndian>(data_size));
38    try!(bmp_data.write_i32::<LittleEndian>(dib_header.hres));
39    try!(bmp_data.write_i32::<LittleEndian>(dib_header.vres));
40    try!(bmp_data.write_u32::<LittleEndian>(0)); // num_colors
41    try!(bmp_data.write_u32::<LittleEndian>(0)); // num_imp_colors
42    Ok(())
43}
44
45fn write_data(bmp_data: &mut Vec<u8>, img: &Image) -> io::Result<()> {
46    let padding = &[0; 4][0 .. img.padding as usize];
47    for y in 0 .. img.height {
48        for x in 0 .. img.width {
49            let index = (y * img.width + x) as usize;
50            let px = &img.data[index];
51            try!(Write::write(bmp_data, &[px.b, px.g, px.r]));
52        }
53        try!(Write::write(bmp_data, padding));
54    }
55    Ok(())
56}