Rust Wasm 图片转 ASCII 艺术
有一些隐藏在代码中的 ASCII 有意思的图片,如:
/*__ooOoo_o8888888o88" . "88(| -_- |)O\ = /O____/`---'\____.' \\| |// `./ \\||| : |||// \/ _||||| -:- |||||_ \| | \\\ - /'| | || \_| `\`---'// |_/ |\ .-\__ `-. -'__/-. /___`. .' /--.--\ `. .'___."" '< `.___\_<|>_/___.' _> \"".| | : `- \`. ;`. _/; .'/ / .' ; | \ \ `-. \_\_`. _.'_/_/ -' _.' /================-.`___`-.__\ \___ /__.-'_.'_.-'================`=--=-' 佛祖保佑 永无BUG 永不宕机
*/
可以把一些有意思的图片转成 ASCII 艺术图,嵌到代码中,或者 log 中。
整体原理比较简单,这里用 Rust Wasm 实现一下。
1. 原理
先简单说一下原理。
- RGB 图片转成灰度图片。
- 准备一些不同密度的 ASCII 字符。
- 遍历灰度图片像素,根据亮度值 替换相应的 ASCII 字符。
这里主要说一下灰度的处理过程。
1.1 灰度处理
灰度和彩色图片的区别就是 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 )
效果如下图所示 (演示地址):
这里在 Rust 中用的是加权平均值的第一种方式:
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
}
2. Rust Image 的一些处理
这里罗列一下一些注意点。
2.1 JS 到 Rust 的 File 传递
这里需要转成 Uint8Array 进行传递:
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);
对应的 Rust 按照 Vec<u8>
处理 :
#[wasm_bindgen]
pub fn get_rust_image(raw: Vec<u8>) { ... }
2.2 Rust 到 JS Vec<u8>
传递
Rust 部分只要传递 Vec<u8>
即可:
#[wasm_bindgen]
pub fn get_rust_image(raw: Vec<u8>) -> Vec<u8> { ... }
JS 消费时,按照 Uint8Array 处理即可:
// to Blob
const blob = new Blob([u8buffer.buffer]);
// to File
const file = new File([blob], 'image.unknown');
// to URL
const url = URL.createObjectURL(blob);
2.3 Rust Image Crate 输出图片数据
Image Crate 将图片加载完后,默认输出的 bytes 是一个解码后的原始数据,传递给 JS 后是无法正常使用的,需要对原始数据进行编码后,输出才行。
// 给编码器一块内存空间,用来写入数据
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
3. 实现
这里做了两个版本。
3.1 简版实现
这个比较简单,就是去色,匹配,再连接即可:
#[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
}
演示地址
执行时间在 20ms 左右。
3.2 Tai 版
看到一个支持 ASCII 种类挺多的 Rust 项目 https://github.com/MustafaSalih1993/tai ,于是将这个项目的 IO 部分进行了修改,适配 WASM 进行了编译处理。
演示地址
这个耗时在 50ms 左右。
4. 安装&使用
<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
使用。
接口描述参考这里:pkg/rust_wasm_image_ascii.d.ts
Rust Wasm 图片转 ASCII 艺术相关推荐
- Linux终端上如何将图像转换成 ASCII 艺术
想在 Linux 终端中做一些有趣的事情吗?把一张普通的图片转换成 ASCII 艺术怎么样?来看一下. 想在 Linux 终端中做一些有趣的事情吗?把一张普通的图片转换成 ASCII 艺术怎么样? 你 ...
- linux 图片 ascii,asciiviewer - 将图像转换为ASCII艺术
由于终端仅限于文本,因此像asciiviewer这样的工具通常可用于从纯文本生成图像. 要做到这一点,你需要一个名为asciiviewer的工具. aview/asciiview是一个图像查看器,以A ...
- 一些你不知道的好玩的有趣的linux命令 Linux终端下的ASCII艺术
你知道吗?其实在linux 终端下也是可以玩一些简单的ASCII字符动画.每次提起linux 都觉得害怕,因为那些命令太古板太严肃了.嘿嘿,从现在开始,貌似有点乐趣了哦.当你敲代码敲累了,你可以玩玩这 ...
- 使用 C# 创造 ASCII 艺术
你见过那些很酷的"字母"艺术吗?用一些英文字母和符号组成某种文字或图像的?有些人尝试逐个字母地创建这种艺术,但今天我们将自己实现它! 什么是 ASCII 艺术? 基本上,ASCII ...
- 如何从任何图像创建自己的自定义ASCII艺术
Creating pictures from monospaced ASCII characters may be useless, but it sure is fun! If you've got ...
- linux切换图片的代码,cacaview – Linux终端下将图片转换ASCII Art代码图案
有时你可能需要终端输出许多图片,那么现在就让我们在Linux终端打开一个新窗口显示图片. cacaview – Linux终端下将图片转换ASCII Art代码图案的命令. Ubuntu下安装命令: ...
- java图片转ascii字符画(转载)
弄了一下午,始终不能得到较好的效果 主要是计算灰度值,再计算出对应字符 灰度值计算方法: 效果: 原图: 代码 package com.j;import com.sun.jndi.toolkit.ur ...
- asc码转换 linux_Linux终端下将图片转换ASCII Art代码图案
有时你可能需要终端输出许多图片,那么现在就让我们在Linux终端打开一个新窗口显示图片. cacaview - Linux终端下将图片转换ASCII Art代码图案的命令. Ubuntu下安装命令: ...
- ASCII-Generator.site在线生成ASCII艺术字符图
什么是 ASCII-Generator.site ? ASCII-Generator.site 是一个 Django 网站,用于从图像或文本中生成 ASCII 艺术字符图
最新文章
- keil添加hal库_使用Keil uVision5创建stm32 hal库项目过程
- 实验三+067+冯艳芳
- 如何做到 jQuery-free?
- ios xcode如何在控制台打印frame
- 【土壤分类】基于matlab GUI多类SVM土壤分类【含Matlab源码 1398期】
- PADS2007教程(二)——PCB封装
- 强烈推荐APP破解常用工具集合!
- 69. x 的平方根
- java贴图技术坦克世界_坦克世界游戏图像设置技巧 如何提高FPS
- html设置ie9兼容性视图,ie9兼容性视图设置方法
- Metric study
- mysql对象资源管理器_使用对象资源管理器
- 计算机安全证书有问题怎么办,提示此网站的安全证书有问题怎么办
- Vivo应用商店上架最全最细流程
- 用ZBrush和Maya建模雕刻一位灵长类动物飞行员 你必须要了解角色是不是有甲方客户的创作需求或是基于其他画师的概念。
- 2.1 zio入门——把函数作用作为工作蓝图
- RCLAMP0544T 国产替代上海雷卯ULC0544T
- TextField及富文本框的用法
- 制作arch linux安装u盘,制作 Arch Linux 内存系统启动盘
- java扫描接口_一种扫描接口并生成可调用API接口文档的方法与流程