Skip to main content

img2txt_rs/
lib.rs

1use image::imageops::FilterType;
2use image::{DynamicImage, GenericImageView, ImageResult, Pixel};
3
4const PIXEL_CHAR_ARRAY: [char; 10] = ['W', '@', '#', '8', '&', '*', 'o', ':', '.', ' '];
5
6/// Load image from path and reshape the image to TARGET_WIDTH
7pub fn load_image(img_path: &str, target_width: u32) -> ImageResult<DynamicImage> {
8    let img = image::open(img_path)?;
9    Ok(resize_image(img, target_width))
10}
11
12pub fn resize_image(img: DynamicImage, target_width: u32) -> DynamicImage {
13    let (src_width, src_height) = img.dimensions();
14    let target_height = get_target_height(src_width, src_height, target_width);
15    img.resize(target_width, target_height, FilterType::CatmullRom)
16}
17
18pub fn print_image(img: DynamicImage) {
19    let (width, height) = img.dimensions();
20    for i in 0..height {
21        for j in 0..width {
22            let rgb = img.get_pixel(j, i);
23            let rgb = rgb.channels();
24            let (red, green, blue) = (rgb[0], rgb[1], rgb[2]);
25            print!("{}", PIXEL_CHAR_ARRAY[calculate_index(red, green, blue)]);
26        }
27        println!();
28    }
29}
30
31#[inline]
32fn calculate_index(r: u8, g: u8, b: u8) -> usize {
33    let grayscale = 0.2126 * r as f64 + 0.7152 * g as f64 + 0.0722 * b as f64;
34    let index = grayscale / ((255 / PIXEL_CHAR_ARRAY.len()) as f64 + 0.5);
35    index.floor() as usize
36}
37
38/// Calculate the target height of the reshaped image
39#[inline]
40fn get_target_height(src_width: u32, src_height: u32, target_width: u32) -> u32 {
41    let mut target_height = src_height;
42    if target_width < src_width {
43        // Image is bigger than target, resize to a smaller size
44        target_height =
45            (target_height as f64 / (src_width as f64 / target_width as f64)).round() as u32;
46    }
47    target_height
48}