ASCII Art 字符画生成
点击"生成"按钮…
输入文字→艺术字符画
点击"生成"按钮…
· 代码注释装饰:项目入口文件 / 大文件起始注释 / 启动 banner
· README banner:GitHub README 顶部用 ```text 代码块展示
· CLI 欢迎语:Node CLI / Go 程序启动时打印
· Git commit:里程碑提交注释
· 显示要求:复制后需用等宽字体(Courier / Menlo / Consolas)显示
了解工具定位 · 使用场景 · 对比优势
后端开发者在 SSH 登录提示、服务启动日志、README 文件头部需要醒目的项目标识,但服务器没有图形界面。本工具将项目名或团队名转为等宽字符画,复制粘贴直接嵌入 .bashrc、启动脚本或 Markdown 代码块,无需安装 figlet 或依赖字体包,纯浏览器完成。
游戏主播在 OBS 或 Streamlabs 中添加频道名称或粉丝团口号时,希望文字有像素风或复古 CRT 效果,但不会使用 Photoshop 或 AE。输入文字后选择「块状」或「灰度」算法,截图保存为 PNG,直接作为场景过渡动画的标题卡,比默认字体更有辨识度。
老牌技术论坛(如 V2EX、NGA、Stage1st)的签名档只允许纯文本,无法使用图片或富媒体。用户用本工具将座右铭、设备配置或联系方式转为字符画,复制到论坛个人设置中,在每次回帖时自动展示,既遵守版规又突出个性。
嵌入式工程师在串口终端或 OLED 屏幕上调试设备时,需要输出大号状态标识(如「OK」「ERROR」「WARNING」),但标准库的 printf 只能输出小字。用本工具生成字符画后,直接硬编码到固件中的日志函数里,在 128×64 像素的屏幕上也能一眼看清错误信息。
手账爱好者在 Notion、GoodNotes 或纸质笔记本的章节开头,希望有一个与众不同的标题装饰,但手绘能力有限。输入章节名,选择「轮廓」或「阴影」风格,将生成的字符画截图或手抄到页面中央,比普通标题更吸引眼球,且无需额外素材库。
| 维度 | 本工具 | 竞品 A (patorjk.com) | 传统方法 |
|---|---|---|---|
| 数据隐私 | 纯浏览器处理,文字不离开设备 | 部分字体需上传至服务器生成 | 手动绘制,完全离线 |
| 处理速度 | 即时生成,<1秒 | 1-3秒(含网络传输) | 数小时至数天(取决于字符画复杂度) |
| 离线可用 | 完全离线(浏览器本地运行) | 需联网 | 完全离线 |
| 字体数量 | 20+ 种字体 | 100+ 种字体 | 无限制(取决于个人技能) |
| 字体预览 | 实时预览,所见即所得 | 需点击生成后查看 | 需脑补或草稿 |
| 输出格式 | 纯文本,可一键复制 | 纯文本 / HTML / 图片下载 | 纯文本 |
| 使用门槛 | 零门槛,输入文字即出图 | 零门槛,但需选择字体 | 需掌握字符画绘制技巧 |
上手步骤 · 输入输出 · 避坑提示
| 输入 | 输出 | 说明 |
|---|---|---|
| Hello | _ _ _ _ | | | | ___| | | ___ | |_| |/ _ \ | |/ _ \ | _ | __/ | | (_) | |_| |_|\___|_|_|\___/ | 典型场景:英文单词,默认字体 |
| 你好 | _ _ _ | \ | | ___| |_ | \| |/ _ \ __| | |\ | __/ |_ |_| \_|\___|\__| | 典型场景:中文词语,默认字体 |
| ABC | _ ____ ____ / \ | __ )| __ ) / _ \ | _ \| _ \ / ___ \| |_) | |_) | /_/ \_\____/|____/ | 典型场景:纯大写字母,默认字体 |
| a b c | _ _ _ / \ | | | | / _ \ | | | | / ___ \| |__| |__ /_/ \_\_____|____ | 边界 case:带空格的输入,空格会被渲染为空白 |
| 123 | _ _ _ | | | | | | | | | | | | |_| |_| |_| | 边界 case:纯数字,默认字体 |
| !@# | _ _ _ | | | | | | | | | | | | |_| |_| |_| | 边界 case:特殊符号,部分符号可能被渲染为相同形状 |
| Hello World | _ _ _ _ __ _ _ | | | | ___| | | ___ / _| | | | | | |_| |/ _ \ | |/ _ \ | |_ ___ | | | | | _ | __/ | | (_) || _| |___|| | | | |_| |_|\___|_|_|\___/ |_| \____/ | 易错 case:含空格的长文本,注意换行效果 |
| a | _ / | | | | | |_| | 边界 case:单字符输入,最小单位 |
你好世界Hello WorldASCII Art 工具只处理标准 ASCII 字符(0-127)。中文字符、Emoji、特殊符号会被忽略或显示为乱码,因为字符画映射表仅覆盖英文字母、数字和基础标点。
This is a very long sentence that will be converted into ASCII art and it will definitely exceed the typical terminal width of 80 characters.Keep it short字符画每个字母通常占 5-8 列宽度,一个 50 字符的句子会变成 250-400 列宽,超出大多数屏幕/终端显示范围,导致自动换行破坏图形结构。
Hello WorldHello World全角空格(U+3000)和制表符(\t)在字符画映射表中没有对应图案,会被渲染成空白或意外字符,破坏单词间的对齐和整体排版。
Hi工具需要至少一个非空白 ASCII 字符来生成图案。纯空格、换行符或空输入不会产生任何输出,界面应提示「请输入至少一个字符」。
输入 "Test" 期望看到大写 T 和小写 e 的图案不同大多数 ASCII Art 字体不区分大小写,或大小写图案完全相同许多经典 ASCII Art 字体(如 Standard、Big)对大小写字母使用同一套图案映射,输入 "A" 和 "a" 可能输出完全相同的字符画。
Line1\nLine2在输入框中直接按回车换行字面量 \n 不会被解析为换行,而是作为反斜杠和字母 n 两个字符处理。要生成多行字符画,应在输入框内直接按 Enter 键插入真实换行符。
在 Outlook 或 Gmail 纯文本模式下粘贴字符画使用等宽字体(Courier New、Consolas)查看,或截图发送字符画依赖等宽字体对齐每个字符。邮件客户端默认比例字体会打乱列对齐,导致图案完全变形。HTML 邮件需指定 <pre> 标签和等宽字体。
公式推导 · 流程图解 · 依据出处
字符映射:输入字符 → 灰度值 → 预定义字符集索引
输入字符 — 用户输入的文本字符灰度值 — 字符在字体中的视觉亮度(0-255)字符集 — 预定义的 ASCII 字符序列(如 @%#*+=-:.)索引 — 灰度值映射到字符集中的位置输入字符 'A',其灰度值约为 180(基于等宽字体渲染)。字符集为 '@%#*+=-:. '(共 10 个字符,灰度区间 0-255)。索引 = floor(180 / (256/10)) = floor(7.03) = 7,对应字符集第 7 位 '-'。因此 'A' 在输出中显示为 '-'。
适用于等宽字体下的单字符灰度映射,不同字体/字号/字符集排列顺序会影响最终视觉效果,不涉及数学精确计算,仅基于视觉亮度近似映射。
3 种主流语言 · 复制即用
from PIL import Image, ImageDraw, ImageFont
# 将文字渲染为图像,再按像素亮度映射为 ASCII 字符
text = "Hello"
font_size = 20
font = ImageFont.truetype("arial.ttf", font_size)
# 计算文字尺寸
img = Image.new("L", (1, 1), 255)
draw = ImageDraw.Draw(img)
bbox = draw.textbbox((0, 0), text, font=font)
w, h = bbox[2] - bbox[0], bbox[3] - bbox[1]
# 渲染文字到灰度图
img = Image.new("L", (w, h), 255)
draw = ImageDraw.Draw(img)
draw.text((0, 0), text, font=font, fill=0)
# 亮度映射字符(从暗到亮)
chars = "@%#*+=-:. "
scale = 255 / (len(chars) - 1)
pixels = img.load()
for y in range(h):
line = ""
for x in range(w):
idx = min(int(pixels[x, y] / scale), len(chars) - 1)
line += chars[idx]
print(line)package main
import (
"fmt"
"image"
"image/color"
"image/png"
"os"
"strings"
"golang.org/x/image/font"
"golang.org/x/image/font/basicfont"
"golang.org/x/image/math/fixed"
)
func main() {
text := "Go"
face := basicfont.Face7x13
// 计算文字边界
w := 0
for _, r := range text {
adv, ok := face.GlyphAdvance(r)
if ok {
w += adv.Ceil()
}
}
h := face.Metrics().Ascent.Ceil() + face.Metrics().Descent.Ceil()
// 创建灰度图
img := image.NewGray(image.Rect(0, 0, w, h))
drawer := font.Drawer{
Dst: img,
Src: image.NewUniform(color.White),
Face: face,
Dot: fixed.P(0, face.Metrics().Ascent.Ceil()),
}
drawer.DrawString(text)
// 像素 → ASCII
chars := "@%#*+=-:. "
scale := 255.0 / float64(len(chars)-1)
for y := 0; y < h; y++ {
var line strings.Builder
for x := 0; x < w; x++ {
gray := img.GrayAt(x, y).Y
idx := int(float64(gray) / scale)
if idx >= len(chars) {
idx = len(chars) - 1
}
line.WriteByte(chars[idx])
}
fmt.Println(line.String())
}
}// 浏览器环境:利用 Canvas 渲染文字,读取像素亮度
function textToAscii(text, charSet = '@%#*+=-:. ') {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 测量文字尺寸
ctx.font = '20px monospace';
const metrics = ctx.measureText(text);
const w = Math.ceil(metrics.width);
const h = 30; // 固定高度
canvas.width = w;
canvas.height = h;
// 白底黑字
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, w, h);
ctx.fillStyle = 'black';
ctx.font = '20px monospace';
ctx.fillText(text, 0, 20);
// 读取像素
const imageData = ctx.getImageData(0, 0, w, h);
const pixels = imageData.data;
const scale = 255 / (charSet.length - 1);
let result = '';
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
const idx = (y * w + x) * 4;
const gray = pixels[idx]; // R 通道(黑白图 R=G=B)
const charIdx = Math.min(Math.floor(gray / scale), charSet.length - 1);
result += charSet[charIdx];
}
result += '\n';
}
return result;
}
console.log(textToAscii('Hello'));8 个高频疑问