//! Minimal BMP file writer use pix::bgr::{Bgr, SBgr8}; use pix::chan::Ch8; use pix::el::Pixel; use pix::Raster; use std::fs; use std::io; pub fn write

(raster: &Raster

, filename: &str) -> io::Result<()> where P: Pixel, Ch8: From, { let raster = Raster::::with_raster(raster); let mut buf = vec![]; write_header(&mut buf, &raster); write_info_header(&mut buf, &raster); write_pixel_data(&mut buf, &raster); fs::write(filename, buf) } fn write_header(buf: &mut Vec, raster: &Raster) { let data_offset = 14 + 40; let sz = raster.width() * raster.height(); buf.push(b'B'); buf.push(b'M'); write_u32(buf, data_offset + sz * 3); // file size write_u32(buf, 0); // reserved write_u32(buf, data_offset); } fn write_info_header(buf: &mut Vec, raster: &Raster) { write_u32(buf, 40); // size of info header write_u32(buf, raster.width()); write_u32(buf, raster.height()); write_u16(buf, 1); // planes write_u16(buf, 24); // bits per pixel write_u32(buf, 0); // no compression write_u32(buf, 0); // image size write_u32(buf, 100); // horizontal resolution write_u32(buf, 100); // vertical resolution write_u32(buf, 0); // colors used write_u32(buf, 0); // important colors } fn write_pixel_data(buf: &mut Vec, raster: &Raster) { let padding = (4 - 3 * raster.width() % 4) % 4; let mut rows: Vec<_> = raster.rows(()).collect(); rows.reverse(); for row in rows { for p in row { buf.push(u8::from(Bgr::blue(*p))); buf.push(u8::from(Bgr::green(*p))); buf.push(u8::from(Bgr::red(*p))); } for _ in 0..padding { buf.push(0); } } } fn write_u32(buf: &mut Vec, val: u32) { buf.push(val as u8); buf.push((val >> 8) as u8); buf.push((val >> 16) as u8); buf.push((val >> 24) as u8); } fn write_u16(buf: &mut Vec, val: u16) { buf.push(val as u8); buf.push((val >> 8) as u8); }