首页 > 数据库 > 数据库开发技术 > Rust Wasm 图片转 ASCII 艺术
有一些隐藏在代码中的 ASCII 有意思的图片,如:
/* _
_ooOoo_
o8888888o 88" . "88
(| -_- |)
O\ = /O
____/`---'\____
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||_ \
| | \\\ - /'| | |
| \_| `\`---'// |_/ |
\ .-\__ `-. -'__/-. /
___`. .' /--.--\ `. .'___
."" '< `.___\_<|>_/___.' _> \"".
| | : `- \`. ;`. _/; .'/ / .' ; |
\ \ `-. \_\_`. _.'_/_/ -' _.' /
================-.`___`-.__\ \___ /__.-'_.'_.-'================ `=--=-'
佛祖保佑 永无BUG 永不宕机
*/
可以把一些有意思的图片转成 ASCII 艺术图,嵌到代码中,或者 log 中。
整体原理比较简单,这里用 Rust Wasm 实现一下。
先简单说一下原理。
RGB 图片转成灰度图片。
准备一些不同密度的 ASCII 字符。
遍历灰度图片像素,根据亮度值 替换相应的 ASCII 字符。
这里主要说一下灰度的处理过程。
灰度和彩色图片的区别就是 R=G=B。
关于灰度值的计算,有 3 种主流方式:
最大值法:Max(R, G, B)。
平均值法:(R + G + B) / 3。
加权平均值法:
0.2126 * R + 0.7152 * G + 0.0722 * B
0.299 * R + 0.587 * G + 0.114 * B
Math.sqrt( (0.299 * R) ** 2 + (0.587 * G) ** 2 + (0.114 * B) ** 2 )
效果如下图所示 (演示地址):

pub fn get_luminance(r: u8, g: u8, b: u8) -> f32 { let r = 0.2126 * (r as f32); let g = 0.7152 * (g as f32); let b = 0.0722 * (b as f32);
r + g + b
}
const file = e.target.files[0];const reader = new FileReader();
reader.onloadend = (evt) => { try { const u8buffer = new Uint8Array(evt.target.result); const result = get_rust_image(u8buffer);
} catch (error) { console.log({ error });
}
};
file && reader.readAsArrayBuffer(file);
Vec<u8> 处理 :#[wasm_bindgen]pub fn get_rust_image(raw: Vec<u8>) { ... }
Vec<u8> 传递Vec<u8> 即可:#[wasm_bindgen]pub fn get_rust_image(raw: Vec<u8>) -> Vec<u8> { ... }
// to Blobconst blob = new Blob([u8buffer.buffer]);// to Fileconst file = new File([blob], 'image.unknown');// to URLconst url = URL.createObjectURL(blob);

// 给编码器一块内存空间,用来写入数据let mut output_buffer = vec![];// 创建一个编码器let mut encoder = JpegEncoder::new_with_quality(&mut output_buffer, 100);// 编码输出encoder
.encode(&img_raw, width, height, ColorType::L8)
.unwrap();// 直接把内存输出就行output_buffer
#[wasm_bindgen]pub fn get_ascii_by_image(raw: Vec<u8>, scale: u32, reverse: bool) -> String { let img = load_from_memory(&raw).unwrap(); let img = img
.resize(
(img.width() * scale / 100) as u32,
(img.height() * scale / 100) as u32,
FilterType::Nearest,
)
.grayscale(); let mut pallete = [' ', '.', '\\', '*', '#', '$', '@']; let mut current_line = 0; let mut result = "".to_string(); if reverse {
pallete.reverse();
} for (_, line, rgba) in img.pixels() { if current_line != line {
result.push('\n');
current_line = line;
} let r = 0.2126 * (rgba.0[0] as f32); let g = 0.7152 * (rgba.0[0] as f32); let b = 0.0722 * (rgba.0[0] as f32); let gray = r + g + b; let caracter = ((gray / 255.0) * (pallete.len() - 1) as f32).round() as usize;
result.push(pallete[caracter]); // 填充一下,有些扁
if caracter < (pallete.len() - 2) {
result.push('.');
} else {
result.push(' ');
}
}
result
}


<script type="module">
import initWasm, {
get_gray_image,
get_ascii_by_image,
get_ascii_by_image_tai,
} from "./pkg/rust_wasm_image_ascii.js";
initWasm()
.then(() => {});</script>
pkg/ 目录中的文件,也可以使用 upkg 的资源 https://unpkg.com/browse/rust-wasm-image-ascii/ ,也可以 npm install rust-wasm-image-ascii 使用。🌟 Github 代码地址:https://github.com/lecepin/rust-wasm-image-ascii
原文作者:Rust语言中文社区;如有侵权,请联系管理员删除。