Skip to content

Instantly share code, notes, and snippets.

@kujirahand
Last active March 11, 2025 00:15
Show Gist options
  • Save kujirahand/bc9c46694693b4db1efe342cad05d811 to your computer and use it in GitHub Desktop.
Save kujirahand/bc9c46694693b4db1efe342cad05d811 to your computer and use it in GitHub Desktop.
画像をアスキーアートに変換するツール
use image::{GenericImageView, imageops::FilterType};
use std::fs;
use std::env;
// 画素に対応するASCII文字を指定
const ASCII_CHARS: &[u8] = b"@#%8&o*=+-:. ";
// RGB値を256色ANSIカラーコードに変換
fn rgb_to_ansi256(r: u8, g: u8, b: u8) -> u8 {
let r_idx = (r as u16 * 5 / 255) as u8;
let g_idx = (g as u16 * 5 / 255) as u8;
let b_idx = (b as u16 * 5 / 255) as u8;
16 + 36 * r_idx + 6 * g_idx + b_idx
}
// 画像を読み込み色付きアスキーアートに変換して返す
fn image_to_ascii(img_path: &str, width: u32) -> String {
// 画像を読み込み
let img = image::open(img_path).expect("画像の読み込みに失敗しました");
// リサイズ後の画像サイズを計算
let (w, h) = img.dimensions();
let aspect_ratio = h as f32 / w as f32;
let new_height = (width as f32 * aspect_ratio * 0.6) as u32;
// 画像を指定サイズにリサイズ
let img = img.resize_exact(width, new_height, FilterType::Nearest);
// 結果を代入するString
let mut result = String::new();
for y in 0..new_height {
for x in 0..width {
let pixel = img.get_pixel(x, y); // ピクセルを取得
let r = pixel.0[0];
let g = pixel.0[1];
let b = pixel.0[2];
// 輝度を計算して文字を選択
let intensity = (0.299 * r as f32 + 0.587 * g as f32 + 0.114 * b as f32) / 255.0;
let index = (intensity * (ASCII_CHARS.len() - 1) as f32) as usize;
let ch = ASCII_CHARS[index] as char;
// 256色のANSIカラーコードを取得
let ansi_code = rgb_to_ansi256(r, g, b);
// ANSIエスケープシーケンスを用いて文字に色を設定
// result.push_str(&format!("\x1b[38;5;{}m{}", ansi_code, ch));
// ANSIエスケープシーケンスを用いて背景色を設定
result.push_str(&format!("\x1b[48;5;{}m{}", ansi_code, ch));
}
// 各行の終わりで色設定をリセットし改行
result.push_str("\x1b[0m\n");
}
result
}
fn main() {
// コマンドライン引数を収集(最初の引数はプログラム名)
let args: Vec<String> = env::args().collect();
// 引数が1つ以上指定されていればその値を、なければ "sample.jpg" を使う
let filename = if args.len() > 1 {
&args[1]
} else {
"sample.jpg"
};
// 画像をアスキーアートに変換
let aa = image_to_ascii(filename, 80);
println!("{}", aa);
// ファイルに保存
fs::write("output.txt", &aa).unwrap();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment