上传一张图片,生成带色号的拼豆图纸(每个格子标注「字母+数字」的拼豆色号),可以直接照着摆豆子。
在线使用 → https://hon-wong.github.io/pindou/
纯前端实现,图片不会上传到任何服务器,全部计算都在你自己的浏览器里完成。也可以把整个仓库下载下来,直接双击 index.html 离线用。
图片预处理
- 旋转 90°(
[/])、水平/垂直翻转,裁剪框会跟着一起变换,不会白框 - 拖框裁剪:八个把手可拉伸,框内可整体拖动;鼠标和触屏同一套操作
- 一键预设:📷 照片 / 🎴 动漫插画 / 👾 像素画 / 🎨 扁平 Logo / ◐ 单色剪影 / 🎯 最大保真(数字键 1–6)
尺寸(像素数目)
- 宽度格数 5–200;滑块按 5 格一档,要非 5 的倍数就在数字框里直接输
- 高度可锁定原图比例或手动指定
- 常用板型预设:29×29、57×57、32×32、48×48、64×64、100×100
- 裁切方式:填充裁切 / 完整包含(周围留空) / 拉伸
- 实时显示总格数、需要几块 29×29 方板、以及按豆子规格算出的成品厘米数
马赛克 / 采样
- 马赛克程度 1–10×:每 N×N 个格子合并成一个色块,格数不变、画面变粗犷
- 采样方式(决定「一个格子该取什么颜色」,格数越少越关键):
-
感知优化(默认,照片推荐)—— 实现自 Perceptually Based Downscaling of Images (Öztireli & Gross, ACM TOG / SIGGRAPH 2015)。把降采样写成「让输出与原图的 SSIM 最大」的 优化问题并求闭式解,等价于一个自适应 unsharp masking:锐化强度由局部的 σ_h/σ_l 决定, 原图细节多而被平均抹平的地方就补回对比度,平坦区完全不动。 实测(不规则自然纹理,原图 std=28.0):
格数 面积平均 感知优化 40×40 15.2 27.3 20×20 10.3 27.1 也就是说,格子越少,普通平均把纹理塌得越狠,而这个方法基本不塌。
-
面积平均 —— 最朴素的做法,纹理会被抹平
-
DPID 细线增强 —— 实现自 Rapid, Detail-Preserving Image Downscaling (Weber et al., SIGGRAPH Asia 2016):反向双边加权,「越不合群的像素越重要」。 对线稿、文字、格纹有效(细线贡献度 14%→50%),但对自然纹理几乎没有效果, 两者适用场景不同,别混用。带「纹理强度 λ」滑块
-
边缘保留 —— 块内 2-means,只有两簇势均力敌(真有一条边穿过)时才让多数派胜出, 硬边不会被平均成中间色;少数派太少(比豆子还细的线)则退回平均,免得整条线被抹掉
-
主色众数 —— 像素画、扁平插画
-
最近邻 —— 最锐利
-
颜色 / 量化
-
量化色数 2–64
-
三种量化算法:
- K-Means(在 CIE Lab 空间聚类,k-means++ 初始化,质量最好)
- 中位切分 Median Cut(快、稳)
- 直接匹配色卡(先整卡匹配,再按用量裁剪到 N 色,最保留原色调)
-
抖动:无 / Floyd–Steinberg(蛇形扫描)/ 有序抖动(Bayer 8×8),强度可调
关于「为什么用色总是偏少」:拼豆色卡是离散的。实测一张普通照片, 哪怕拿整张 221 色卡直接匹配,也只有 20 来种珠子会被用到 —— 这是那张图的色彩天花板, 不是算法保守。要求 48 色也不会凭空变出色卡里没有的过渡色。
想再逼近原图,唯一的办法是抖动:用两种邻近色交错摆放,让肉眼在一定距离外自动混色 (原理同报纸用黑点疏密表现灰阶)。按肉眼观感衡量(3×3 局部平均 ΔE2000)实测能提升 17%~47%; 逐格误差反而变大,那是抖动的代价而非缺陷。「🎯 最大保真」预设就是开满色数 + 抖动。
-
色卡匹配用 CIEDE2000 色差(质心级),逐像素用 Lab 欧氏距离,兼顾质量与速度
-
亮度 / 对比度 / 饱和度 / 伽马微调
-
背景色移除(可在缩略图上直接吸取)、透明阈值
色卡
- 内置 MARD 咪嘟标准 221 色(A 黄橙 26 / B 绿 32 / C 蓝青 29 / D 蓝紫 26 / E 粉玫 24 / F 红 25 / G 棕肤 21 / H 黑白 23 / M 大地 15),色号与色系结构取自公开色卡并经两个独立来源交叉核对
- 另有 Hama 常用 30 色、基础 24 色
- 「只用我有的颜色」:逐色勾选、按系列批量开关,配好的图纸只会用你手上真有的豆子
- 支持自定义色卡:粘贴
色号,名称,#RRGGBB的 CSV 即可,保存在浏览器本地
成品预览 / 熨烫模拟
两个互相独立的维度,可自由组合:
熨烫程度(决定孔洞与平整度)
- 未熨烫(生豆)→ 轻烫(留明显孔洞)→ 中烫(小孔、边缘熔合)→ 重烫(全熔封孔、平整光亮)
表面工艺(「垫什么材料熨烫,冷却后就留什么纹理」)
| 工艺 | 垫材 | 成品观感 |
|---|---|---|
| 烘焙纸 | 烘焙纸 / 烫画纸 | 平整哑光,孔洞几乎不可见(标准做法) |
| 亮面 / 镜面 | 光面膜 | 光滑反光,像上了一层釉 |
| 毛巾烫 | 毛巾 | 毛茸茸的绒面质感 |
| 搓澡巾烫 | 搓澡巾 / 丝瓜络 | 细密斜网,柔和哑光 |
| 网格压纹 | 网布 | 规整方格压痕 |
| 华夫格 | 华夫格布 | 明显的立体格纹 |
| 褶皱做旧 | 揉皱的纸/布 | 随机折痕,做旧感 |
| 格利特闪粉 | 格利特烫画布 | 表面附着闪片,可选银/金/粉/彩 |
| 绒面 | 植绒转印膜 | 哑光丝绒,复古感 |
难度上,有孔/无孔最好烫,烘焙纸和搓澡巾中等,格利特、毛巾和亮面最难。
双面预览
- 反面是左右镜像(照着反面摆豆很容易做反)
- 可选单面/双面熨烫;单面熨烫时反面仍显示生豆质感
以上均为示意渲染,实际观感还取决于豆子品牌、温度与按压力度。
图纸 / 导出
- 图纸视图(色号)与成品预览双视图(
V切换) - 格内标注可切换:色号 / 符号(黑白打印友好)/ 色号+符号 / 不显示
- 行列标尺;网格线可关,加粗间隔可选每 5 格或每 10 格(标尺红色刻度跟着走)
- 格子 6–64px 无级缩放:Ctrl/⌘ + 滚轮以光标为中心缩放,触屏双指捏合
- 鼠标悬停显示「第几行第几列 + 色号」;点格子或点清单只高亮该色,点空白处或按 Esc 恢复全部
- 右侧配色清单:默认按色号排序(A1→A2→…→B1,字母升序、数字从小到大),也可按用量或色相排序;含用量与占比,一键禁用某色并自动替换为最接近的可用色
- 导出:图纸 PNG(含标尺与图例)、成品预览 PNG、色号表 CSV(Excel 可直接打开)、配色清单文本、参数 JSON
- 打印:直接出一张适合 A4 的图纸
- 打开网页,点「打开图片」——也可以把图片拖进页面,或者直接
Ctrl/⌘ + V粘贴剪贴板里的图 - 调「宽度格数」定尺寸,调「量化色数」定用多少种豆子
- 想更粗犷就拉「马赛克程度」;照片建议采样用「面积平均」,像素画/扁平插画用「主色众数」
- 在「管理色卡」里只勾选你手上有的颜色
- 导出图纸 PNG 或直接打印,照着色号摆豆子
撤销/重做:⌘/Ctrl+Z 与 ⌘/Ctrl+Shift+Z。禁用颜色、套预设、旋转裁剪、拖滑块都能回退(拖动滑块整段算一步)。
主题:紫(默认)/ 蓝 / 青绿 / 玫粉 / 琥珀 / 浅色六套,在「6 · 显示」里切换。
全屏与专注:F 全屏,\ 收起两侧面板专心看图纸。
手机可用:360–430px 宽度下面板整页展开;裁剪框、图纸平移与双指捏合缩放都支持触屏
(.scroller 上设了 touch-action:none 关掉浏览器默认手势,否则双指会被拿去缩放整个页面)。
全屏按钮在 iOS Safari 上也能用 —— 那里没有非 video 元素的 Fullscreen API,
所以除了调用真全屏,还始终切换一套纯 CSS 的沉浸模式(隐藏顶栏/面板/页脚,画布铺满 100dvh)。
参数会自动记在浏览器本地,下次打开还在(旋转/裁剪属于当前这张图,不会带到下一张)。
支持 URL 参数,方便把某组参数直接分享出去:
index.html?demo=1&w=64&colors=24&algo=kmeans&dither=fs&view=preview&cell=14
| 参数 | 说明 |
|---|---|
demo=1 |
载入内置示例图片 |
img= |
载入同源图片地址 |
w / h |
宽 / 高格数(给了 h 就自动关掉比例锁定) |
colors |
量化色数 |
algo |
kmeans / mediancut / direct |
dither |
none / fs / ordered,ditherAmt 为强度 |
mosaic |
马赛克程度 1–10 |
sampleMode |
ssim / area / dpid / edge / dominant / nearest |
texture |
DPID 纹理强度 λ×100,0–300 |
fitMode |
cover / contain / stretch |
palette |
mard / hama / basic / custom |
view |
chart / preview |
cell |
格子像素大小 |
label |
code / symbol / both / none |
iron |
熨烫程度 0–3 |
finish |
表面工艺 paper / gloss / towel / loofah / mesh / waffle / crumpled / glitter / velvet |
tint |
闪粉色 silver / gold / pink / multi |
side |
front / back |
theme |
purple / blue / teal / rose / amber / light |
rotate |
0 / 90 / 180 / 270 |
bold |
加粗间隔 0 / 5 / 10 |
MARD 221 色的色号与色系结构取自公开色卡,并用两个独立来源交叉核对过(九个色系的数量完全一致)。 但 HEX 是实物色卡的取样近似值:两个来源之间就有几个单位的差异,不同批次的实物也会有色差。 用来做配色计算够用,但别把它当成精确的印刷色值。
如果你要求颜色完全对上手里的实体色卡,建议自己录一份:打开「管理色卡」→ 展开最下面的「自定义色卡」→ 按 色号,名称,#RRGGBB 每行一个粘进去 → 保存为「我的色卡」。之后所有配色都会严格只用你这份色卡。
不需要任何依赖和构建步骤。
# 方式一:直接双击 index.html(内置示例图片是内联的,离线可用)
# 方式二:起个本地服务(想用 ?img= 加载本地图片时需要)
python3 -m http.server 8899
# 然后打开 http://127.0.0.1:8899/tests/unit.js 纯计算模块的单元测试(色彩空间、色差、降采样、量化、抖动、DPID、感知优化,59 项)
tests/e2e.html 浏览器端到端测试:在同源 iframe 里驱动真实的 index.html(123 项)
tests/fixtures/ 测试图片(风景照、像素精灵、扁平插画、人像色调、纯色、细长条、全透明、3000×2000 大图)
单元测试用 macOS 自带的 JavaScriptCore 跑,不需要装 Node:
/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Helpers/jsc tests/unit.js端到端测试起个本地服务后浏览器打开 tests/e2e.html 即可,页面顶部会显示通过/失败统计,底部有导出图纸的实际渲染结果和一个实时的被测应用。
覆盖内容包括:CIEDE2000 官方测试向量、Lab 往返精度、三种采样、三种量化算法、三种抖动、马赛克块一致性、透明与空格处理、色卡切换与禁用、极端宽高比、3000×2000 大图性能、CSV 与网格一致性、色卡弹窗和配色清单的真实点击交互、非法 URL 参数的兜底、旋转/翻转/裁剪对结果的实际影响、 四档熨烫 × 正反面 × 单双面共 16 种组合的渲染、9 种表面工艺的渲染、 纹理只贴在豆子上而不糊到空格、纹理跟着画布滚动、颗粒感随熨烫程度单调递减、 反面确实是镜像、关掉网格线后加粗线与外框一并消失、 量化质量不低于「色卡理论下限 + 1.5 ΔE」、边缘保留采样确实减少中间色、 DPID 让细线贡献度从 14%(≈面积占比)提升到 50% 且随 λ 单调递增、 感知优化在 40×40 与 20×20 下都保住 ≥85% 的局部对比度而面积平均塌到 54%/37%、纯色区不被造出噪点、撤销重做(含禁用颜色后撤销)、 六套主题切换,以及 360–1024px 六档宽度下的响应式布局(逐元素检查有无超出视口)。
-
无依赖、无构建、无框架,
file://直接打开就能跑 -
撤销用「整份参数快照」而不是操作日志:动作种类太多,逐个写反向操作容易漏,快照只有几百字节
-
细节/纹理与配色精度是两条独立的路:空间纹理靠降采样算法(感知优化 / DPID,有效,见上); 配色精度则无从提升—— 试过三种「细节优先」量化思路,实测都更差,已放弃(
js/quantize.js里留了记录)。 原因是 K-Means 已经贴着色卡的物理极限:在测试图上用 12 色量化得到平均 ΔE2000 = 3.87, 而「不限色号预算、每种颜色都在 221 色卡里挑最近的」这个理论下限也只有 3.00。 残余误差主要来自色卡里根本没有那个颜色,换聚类算法救不回来。 真正能提升细节的是提高格数、感知优化采样和抖动。顺带说明:双线性 / bicubic 不是更好的选择。大倍率降采样时它们是欠采样、会混叠, 实测与面积平均基准的偏差 ΔE=1.20(面积平均自身为 0,感知优化 0.78 是有意补回的对比度)。 面积平均才是正确基线。
-
表面纹理是可平铺的图案,随格子大小缩放;随机图元做 3×3 环绕绘制,否则平铺时能看到接缝
-
纹理用
source-atop叠在只画了豆子的图层上,所以不会糊到空格和底板上 -
色彩计算全部在 CIE Lab (D65) 空间进行;色卡匹配用 CIEDE2000,逐像素匹配用 Lab 欧氏距离以保证速度
-
K-Means 用固定随机种子,同样的参数一定得到同样的图纸,不会每次点都变
-
图纸画布采用视口虚拟化渲染:只画可见范围内的格子,所以 200×200 的大图纸放到 64px 一格也不会卡
-
降采样按 alpha 预乘做面积平均,透明边缘不会发黑;超大原图会逐级减半缩放,避免一次性吃掉几百 MB 显存
MIT