use pix::Raster;
use pix::bgr::{Bgr, SBgr8};
use pix::chan::Ch8;
use pix::el::Pixel;
use std::fs;
use std::io;
pub fn write<P>(raster: &Raster<P>, filename: &str) -> io::Result<()>
where
P: Pixel,
Ch8: From<P::Chan>,
{
let raster = Raster::<SBgr8>::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<u8>, raster: &Raster<SBgr8>) {
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); write_u32(buf, 0); write_u32(buf, data_offset);
}
fn write_info_header(buf: &mut Vec<u8>, raster: &Raster<SBgr8>) {
write_u32(buf, 40); write_u32(buf, raster.width());
write_u32(buf, raster.height());
write_u16(buf, 1); write_u16(buf, 24); write_u32(buf, 0); write_u32(buf, 0); write_u32(buf, 100); write_u32(buf, 100); write_u32(buf, 0); write_u32(buf, 0); }
fn write_pixel_data(buf: &mut Vec<u8>, raster: &Raster<SBgr8>) {
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<u8>, 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<u8>, val: u16) {
buf.push(val as u8);
buf.push((val >> 8) as u8);
}