pub mod bitmap;
use bitmap::BitMap;
use gif::EncodingError;
use gif::{Encoder, Frame, Repeat};
use std::fs::File;
use std::sync::mpsc::Sender;
use crate::prog::Message;
enum Colour {
WHITE,
BLACK,
}
fn push_pixel(vec: &mut Vec<u8>, colour: Colour) {
vec.push(match colour {
Colour::WHITE => 0,
Colour::BLACK => 1,
});
}
pub fn init_image(
width: u16,
height: u16,
init_line: &mut BitMap,
rule: u8,
) -> Result<Vec<u8>, EncodingError> {
let num_pixels: usize = (width as usize) * (height as usize);
let mut image: Vec<u8> = Vec::with_capacity(num_pixels);
for _y in 0..height {
for x in 0..width {
if init_line.get(x.into()) == 1 {
push_pixel(&mut image, Colour::BLACK);
} else {
push_pixel(&mut image, Colour::WHITE);
}
}
init_line.rule_step(rule);
}
assert!(image.len() == num_pixels);
Ok(image)
}
pub fn gen_next_image(
image: &mut Vec<u8>,
width: u16,
height: u16,
line: &mut BitMap,
rule: u8,
) -> Result<(), EncodingError> {
let first_row_len: usize = width.into();
image.drain(0..first_row_len);
line.rule_step(rule);
for x in 0..width {
match line.get(x.into()) {
1 => push_pixel(image, Colour::BLACK),
0 => push_pixel(image, Colour::WHITE),
_ => panic!(),
}
}
debug_assert!(image.len() == (width as usize) * (height as usize));
Ok(())
}
fn build_frame(width: u16, height: u16, img: &[u8]) -> Frame {
let frame = Frame::from_indexed_pixels(width, height, img, None);
frame
}
pub fn build_gif(
width: u16,
height: u16,
steps: u32,
init_line: &mut BitMap,
file_name: &str,
progress_bar_tx_wrap: Option<&Sender<Message>>,
rule: u8,
) -> Result<(), EncodingError> {
let mut file = File::create(file_name)?;
let color_map = &[0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00];
let mut encoder = Encoder::new(&mut file, width, height, color_map)?;
encoder.set_repeat(Repeat::Infinite)?;
let mut img = init_image(width, height, init_line, rule)?;
let frame = build_frame(width, height, &img);
encoder.write_frame(&frame)?;
match progress_bar_tx_wrap {
Some(progress_bar_tx) => {
for s in 1..steps {
gen_next_image(&mut img, width, height, init_line, rule)?;
let frame = build_frame(width, height, &img);
encoder.write_frame(&frame)?;
progress_bar_tx.send(Message::Update(s)).unwrap();
}
progress_bar_tx.send(Message::Kill).unwrap();
}
None => {
for _ in 1..steps {
gen_next_image(&mut img, width, height, init_line, rule)?;
let frame = build_frame(width, height, &img);
encoder.write_frame(&frame)?;
}
}
}
Ok(())
}