Last active
March 11, 2025 00:15
-
-
Save kujirahand/bc9c46694693b4db1efe342cad05d811 to your computer and use it in GitHub Desktop.
画像をアスキーアートに変換するツール
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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