I just started programming as a hobby three weeks ago, and I’m amazed at what I can do. I exclusively use Rust.
Before I try making a game with a GUI, I want to create a simple one in the terminal. However, I plan to incorporate Pixel Art for context in that game.
I’ve seen some ways to display pictures in the terminal, but since I’m limited to a font size, I specifically want to try displaying 4×8 pixels within each font space. This means, for example, a 120×120 pixel art would appear in a 30×15 font space.
I don’t want to use average colors; I want the authentic picture to be displayed.
I tryed a method that can divide a font space in 2 (1×2) but:
- It’s not exactly good enough
- It use average colors so there is no detail.
use image::GenericImageView;
use crossterm::{terminal::{self, ClearType}, ExecutableCommand};
use std::io::{stdout, Write};
// Function to get the average color of a sub-region
fn average_color(img: &image::DynamicImage, x_start: u32, y_start: u32, width: u32, height: u32) -> [u8; 3] {
let mut r_sum = 0;
let mut g_sum = 0;
let mut b_sum = 0;
let mut count = 0;
for y in y_start..y_start + height {
for x in x_start..x_start + width {
let pixel = img.get_pixel(x, y);
let [r, g, b, _] = pixel.0;
r_sum += r as u32;
g_sum += g as u32;
b_sum += b as u32;
count += 1;
}
}
[
(r_sum / count) as u8,
(g_sum / count) as u8,
(b_sum / count) as u8,
]
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load the image
let img = image::open("path_to_file.jpg")?;
let (width, height) = img.dimensions();
// Check the size of the image
if width != 54 || height != 54 {
eprintln!("L'image doit être de taille 50x50 !");
return Ok(());
}
// Initialize the terminal
let mut stdout = stdout();
terminal::enable_raw_mode()?;
stdout.execute(terminal::Clear(ClearType::All))?;
// Define the size of each sub-region
let sub_width = 1;
let sub_height = 2;
// Display each pixel
for y in (0..height).step_by(sub_height as usize) {
for x in (0..width).step_by(sub_width as usize) {
// Get the average color for the top half of the character cell
let top_color = average_color(&img, x, y, sub_width, sub_height);
// Get the average color for the bottom half of the character cell
let bottom_color = average_color(&img, x, y + sub_height / 2, sub_width, sub_height / 2);
// Print the top half color
print!("x1b[38;2;{};{};{}mx1b[48;2;{};{};{}m▀", bottom_color[0], bottom_color[1], bottom_color[2], top_color[0], top_color[1], top_color[2]);
}
// Move to the next line
print!("x1b[0mrn");
}
// Reset colors
print!("x1b[0m");
stdout.flush()?;
// Keep the terminal open until a key is pressed
std::io::stdin().read_line(&mut String::new())?;
// Disable raw mode in the terminal
terminal::disable_raw_mode()?;
Ok(())
}
If that matter, I use Linux.
I’m not sure if I’m asking too much, so thank you for your help.
Linux_96 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
8