aarty/src/ascii_processor.rs

63 lines
1.6 KiB
Rust
Raw Normal View History

use crate::args::{args::Arguments, enums::Mode};
2022-10-03 18:13:59 +00:00
use colored::{ColoredString, Colorize};
use image::{DynamicImage, GenericImageView};
2022-10-03 18:13:59 +00:00
use std::io::{self, BufWriter, Write};
pub fn generate_ascii<W: Write>(
image: DynamicImage,
args: &Arguments,
mut buffer: BufWriter<W>,
) -> io::Result<()> {
2022-10-03 18:13:59 +00:00
let characters = args.characters.chars().collect::<Vec<char>>();
let (width, height) = image.dimensions();
for y in 0..height {
for x in 0..width {
if y % (args.scale * 2) == 0 && x % args.scale == 0 {
let element = get_character(
2022-10-03 18:50:48 +00:00
image.get_pixel(x, y),
&characters,
args.mode,
2022-10-03 19:00:39 +00:00
&args.background,
);
buffer.write_all(format!("{element}").as_bytes())?;
2022-10-03 18:13:59 +00:00
}
}
// Add a new line at the end of each row
if y % (args.scale * 2) == 0 {
buffer.write_all("\n".as_bytes())?;
2022-10-03 18:13:59 +00:00
}
}
Ok(())
2022-10-03 18:13:59 +00:00
}
2022-10-03 18:50:48 +00:00
fn get_character(
pixel: image::Rgba<u8>,
characters: &Vec<char>,
mode: Mode,
2022-10-03 19:00:39 +00:00
background: &Option<String>,
2022-10-03 18:50:48 +00:00
) -> ColoredString {
let intent = if pixel[3] == 0 {
0
} else {
pixel[0] / 3 + pixel[1] / 3 + pixel[2] / 3
};
2022-10-03 18:13:59 +00:00
let ch = characters[(intent / (32 + 7 - (7 + (characters.len() - 7)) as u8)) as usize];
let ch = String::from(ch);
2022-10-03 18:50:48 +00:00
let ch = match mode {
2022-10-03 18:13:59 +00:00
Mode::NormalAscii => ColoredString::from(&*ch),
Mode::Colored => ch.truecolor(pixel[0], pixel[1], pixel[2]),
2022-10-03 18:50:48 +00:00
};
2022-10-03 18:13:59 +00:00
2022-10-03 18:50:48 +00:00
match background {
Some(bg) => ch.on_color(bg.to_string()),
None => ch,
2022-10-03 18:13:59 +00:00
}
}