一张普通照片,拖进网页几毫秒就变成由
.:-=+*#%@这些字符拼成的画,宽度、字符集、亮度和对比度都能随手调,还能一键复制字符画或导出 PNG/TXT。整个过程纯前端完成,图片不会上传到任何服务器。先看成品,再讲这次怎么用华为云 CodeArts 码道 WebUI 一段话把它做出来、部署并公开分享。
这个工具做什么
它把「图片像素」翻译成「灰度字符」,做成了一个本地即用的 ASCII 字符画工具:
- 拖拽上传:拖图或点选图片都行,支持 PNG / JPG / WEBP / GIF,右侧实时预览字符画。
- 可调输出宽度:滑块从 20 到 240 个字符,越宽细节越多,越窄越有极简味道。
- 6 套字符集:标准(10)、精细(70)、带块、色块、圆点,以及自定义字符集,灰度层次随字符数变化。
- 亮度 / 对比度:两个独立滑块,照片太暗或灰度拉不开时现场调整,不必回去重改原图。
- 反色 + 彩色字符画:黑底白字 / 白底黑字一键切换,彩色模式会按原图颜色给每个字符上色。
- 导出:一键复制字符画到剪贴板,或下载 TXT、PNG,PNG 是用 Canvas 重新渲染出来的等宽字符图。
码道开通(免费体验版)
开始之前,先免费开通码道体验版。不需要装任何软件,浏览器就能用:
https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwsf&sourcead=dmzntgwwbwz
开通后有三种使用方式:WebUI(浏览器对话)、TUI(终端命令行)和桌面 IDE(IDE 插件)。本文用 WebUI 版演示。
进入 AI 开发者空间
- 浏览器打开 https://devstation.developer.huaweicloud.com/aidevspace?utm_source=opcsfsq&utm_medium=wbwz
- 弹窗「请选择要进入的版本」→ 点击体验版
- 首次使用会跳到华为云登录页,扫码登录一次,后续浏览器会话复用
- 弹窗「临时凭据自动配置」→ 点击同意,沙箱自动创建
进入 AI 开发者空间主界面后,先等左侧菜单加载出来,再找到CodeArts,点击它右侧的浏览器图标,打开码道 WebUI 对话窗口:
打开后码道 WebUI 底部输入框提示「尽管吩咐,我来帮你搞定」:
小贴士:体验版沙箱 3 小时后自动重置,生成完记得把
index.html下载保存。
任务描述
在码道 WebUI 输入框粘贴以下需求,回车发送(模型默认glm-5.2,可直接用):
开发一个「照片转 ASCII 字符画」网页应用:用户可以上传或拖入一张图片,应用把图片转换成由黑白 ASCII 字符组成的字符画,可调整输出宽度、字符集、亮度/对比度,支持一键复制字符画和下载 PNG/文本,界面简洁美观,单个网页打开即用。完成后用部署功能部署成可访问的网页应用,并告诉我访问地址。这轮码道具体做了什么
不是把通用 AI 能力复述一遍,而是它在这篇项目里的实际动作:
- 读取沙箱路径后,在
/workspace/ascii-art下新建项目目录,并清掉了残留的旧目录。 - 发现
PYTHONHOME指向了码道自带的python3.12会导致端口检测异常,改用纯 bash 的/dev/tcp探测空闲端口,启动服务时再清掉相关环境变量。 - 写入约 558 行的单文件
index.html(原生 HTML/CSS/JS,零依赖),包含图像读取、灰度采样、亮度对比度、字符集切换、复制与 Canvas 导出等完整逻辑。 - 检测到 3000 端口空闲,用
python3 -m http.server 3000 --bind 0.0.0.0 --directory /workspace/ascii-art起服务,curl自检通过后给出内部预览地址。
代码亮点
以下是index.html里值得关注的设计思路和实现细节。
1. 用加权灰度把像素映射到字符
图片先画到 Canvas 上,再getImageData逐像素采样。每个像素先做 Alpha 混合到黑底,再用标准亮度公式转灰度,最后按灰度值落到字符集数组的对应下标:
constgray=0.299*r+0.587*g+0.114*b;letidx=Math.floor((gray/255)*n);if(idx>=n)idx=n-1;if(idx<0)idx=0;constch=chars[idx];2. 亮度对比度在采样前先处理像素
对比度不是简单乘系数,而是套用标准对比度公式(259*(C+255))/(255*(259-C)),再叠加亮度偏移:
constcf=(259*(contrast+255))/(255*(259-contrast));r=clamp(cf*(r-128)+128+brightness);g=clamp(cf*(g-128)+128+brightness);b=clamp(cf*(b-128)+128+brightness);3. 彩色字符画和反色
默认是黑白字符,开启「彩色字符画」后,每个字符用<span>单独着色,颜色就是原图对应像素的颜色;「反色」则把 RGB 三点都取反,实现黑底白字 / 白底黑字切换:
constcol=invert?`rgb(${255-c.r},${255-c.g},${255-c.b})`:`rgb(${c.r},${c.g},${c.b})`;html+=`<span style="color:${col}">${escapeHtml(c.ch)}</span>`;4. 复制与 PNG 导出
复制优先用navigator.clipboard,失败再降级到execCommand('copy')。下载 PNG 则直接按字符网格重画一张 Canvas,用等宽字体逐格fillText,再toBlob下载:
ctx.font=`${fontSize}px "Courier New", Consolas, monospace`;for(lety=0;y<rows;y++){for(letx=0;x<cols;x++){constc=cells[y*cols+x];ctx.fillText(c.ch,pad+x*charW,pad+y*charH);}}直接下载试玩
本次生成的项目就是单文件index.html,没有第三方依赖,把文件保存到本地后双击用浏览器打开即可运行。源码同步到公开 Demo Park 仓库:
- Demo Park 仓库:https://atomgit.com/deli007/demo_park
- 本案例目录:https://atomgit.com/deli007/demo_park/tree/main/codearts-ascii-art-generator
总结
照片转 ASCII 字符画这一步,把「图片处理」这件事拆成了清晰的三段:像素采样、灰度/亮度/对比度映射、字符渲染与导出。技术上是 CanvasgetImageData逐像素处理,再加上字符集和反色/彩色两处显示层切换,前后端都不碰服务器,图片隐私也更安心。后续还可以加批量拖图、去色阈值或按区域黑白化。
如果还没用过码道,可以免费开通体验版:https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwsf&sourcead=dmzntgwwbwz