- Home
- Plugin
- Strumenti e capacità
- dsh-ink-splash
dsh-ink-splash
lynnchrysteiin/dsh-ink-splash
Custom splash screen line-art animation for DeepSeek Harness
Installazione
dsh plugin --profile web add github:lynnchrysteiin/dsh-ink-splashREADME
开屏线稿动画 · Ink Splash
把一张图片提取成线稿,启动时逐笔勾勒:线条一条条浮现,笔尖带一点光, 全部画完后所有边缘瞬间高亮发光,再化入界面。
- 线稿保留原图颜色:发色、肤色、深色衣料各自成色,按调色板合并成 8 色
- 线稿保留粗细:墨色越重线越粗(深色轮廓明显比浅色细节粗),像压感笔
- 辉光也跟随原图颜色:闪光时每个色相各自发光(红色 D 出粉红光、蓝发出蓝光), 全屏闪光取整幅的加权平均色
- 浅色主题:白底,线条沿用原图色,闪光时加深、同色晕开
- 深色主题:黑底,线条提亮,闪光时烧成各自色相的发光体
- 底色、线色、用色模式、宽度、速度、偏移……全部可在 设置 → 开屏动画 里实时调
内置五套线稿,设置 → 画面 → 线稿 里切换:
| 名称 | 来源 | 构图 | 特点 |
|---|---|---|---|
ds-line(默认,浅色) | ds-bg-line.png | 横 16:9 | 平涂版本,无内描边,提取最干净:902 条 |
ds-bg | ds-bg.png | 横 16:9 | 带内描边的版本,细节更密:929 条 |
maid | 1870.png | 竖 9:16 | 室内场景,整幅保留不抠纸:1039 条 |
chibi | 296.png | 方 1:1 | Q 版 + 思考气泡,白纸抠图:141 条 |
moss(默认,深色) | MOSS.png | 横 16:9 | 字形轮廓,白字 + 红 D:78 条 |

作者的预设
仓库里的 presets/ 是作者本人调好的参数,可直接导入(见 presets/README.md)。
每张图一套,互不干扰:
| 线稿 | 预览 |
|---|---|
ds-line | ![]() |
ds-bg | ![]() |
maid | ![]() |
chibi | ![]() |
moss | ![]() |
安装
插件就是这个仓库本身,通过 Profile 的 bundle 机制安装:
plugin_manager install_bundle target = <仓库绝对路径>
安装后刷新应用窗口(Ctrl+R)即可生效。开屏对当前 profile 的所有会话生效。
换一张图(三步)
1. 提取线稿
需要 Python 3.9+ 和 opencv-python / numpy / Pillow(不需要 skimage):
python -m pip install opencv-python numpy pillow
然后把要用的图放进 resources/imgs/,跑提取器(下面的 python 换成你环境里的解释器即可,
虚拟环境、conda 环境、系统 Python 都行):
python tools/ink_extract.py \
--input ../resources/imgs/your-image.png \
--name my-art \
--out assets/my-art.json \
--mode edge \
--colors 8 \
--preview assets/my-art.preview.png
Windows 上用 PowerShell 写多行命令,把续行符换成反引号:
python tools\ink_extract.py `
--input ..\resources\imgs\your-image.png `
--name my-art `
--out assets\my-art.json `
--mode edge `
--colors 8 `
--preview assets\my-art.preview.png
用 conda 的话解释器可能是 "C:\Users\<你>\miniconda3\envs\py311\python.exe",
venv 则是 .venv\Scripts\python.exe(Windows)或 .venv/bin/python(macOS / Linux)。
先看 assets\my-art.preview.png 判断提取质量(预览也是彩色的),不满意就调参数重跑。
模式怎么选
| 模式 | 适用图片 | 观感 |
|---|---|---|
edge(默认) | 插画、人像、有细节的照片 | 忠实还原边缘,线条细密 |
contour | Logo、扁平图形、排版字 | 干净的外轮廓 + 内部孔洞 |
iso | 风景、大面积渐变的照片 | 等高线般的长曲线,最"艺术" |
常用参数
| 参数 | 说明 |
|---|---|
--detail 92 | 边缘密度:调低(如 85)线更多更碎,调高(93+)更干净 |
--min-len 7 | 丢掉短于该长度的碎线(view 单位),对付"太密"最直接 |
--merge 2 | 把端点相距 <2 的碎段接成长笔画,0 关闭 |
--colors 8 | 从原图采样的调色板大小,0 = 单色 |
--width-min/max 0.5/2.1 | 细笔与粗笔的宽度系数(相对 --width-min 到的淡墨到浓墨) |
--width-gamma 1.15 | >1 时只有很浓的墨才变粗 |
--color-source fill | 线色取哪里:fill 取线条旁边那块填充色(和原图实色一致);edge 取轮廓最暗的那个像素(会更黑) |
--color-offset 4.5 | fill 模式沿法线偏离线条多少像素去取色 |
--color-pull 0.12 | 把取到的色再往墨色压一点,越大越深 |
--min-contrast 36 | 与纸面的最小亮度差,防止浅色线看不见(0 = 关) |
--eps 0.9 | 简化强度:越大越抽象、点数越少 |
--order tsp | 描绘顺序:tsp 求一条穿过所有笔画的最短笔路(最像"一路画过去")length 先长后短;region 分块;nearest 全局最近邻;hilbert 空间填充(会有方块感) |
--max-stroke 0 | 把超长线切成等长段;会拆散完整图案,默认关,只有想追求"每笔一样长"时才开(如 60) |
--fill assets\x.fill.webp | 生成上色层(不带此参数就没有填色) |
--fill-style smooth | smooth(默认)柔化上色、无双影;original 直接叠原图、最锐利;flat 硬量化 |
--fill-softness 0.82 | smooth 下原图所占权重:越大越接近原图、越小越"色块化" |
--fill-blur 2.0 | smooth 下的高斯半径(填充层像素),越大越柔 |
--fill-colors 24 | 量化色数;smooth 时只用于"轻量叠回",色数越大越接近原图 |
--fill-size 2000 | 上色层长边。必须明显大于窗口宽度(留 1.25× 余量),否则浏览器放大就会糊 |
--fill-quality 90 | WebP 质量,80 以下渐变会出现色带 |
--levels 7 | iso 模式的等值线条数 |
实验性(默认关,效果尚不稳定):
--mode stroke用中轴+距离变换提取"一笔粗线",--unify 6把平行双线合并成中轴。两者目前都会把线打碎成短段,不建议用于交付图。
顺序怎么选:插画用 tsp——它把整张图的笔画当成一条笔路来优化,
所以不会出现"画一半跳走再回来",也不会有网格/方块感;Logo 用 length
(大字形先出,结尾都是短笔画)。提取器会打印 pen jumps(笔尖跳跃距离)和
locality(当前线到后续 12 条线的中位距离,越小越"一块一块")供比较:
tsp 的跳跃中位数约 13、最大 140,明显优于 nearest(15 / 323)和 hilbert(23 / 135)。
长笔画默认不切分——一个完整的轮廓就是一笔画完,视觉上才是一个图案。 不切分时长笔(~900 单位)在 2.4s 的时间轴里也只占 70ms 左右,不会出现"最后一根线拖尾"。
仓库里五张成品各自的参数(python 换成你的解释器):
# ds-line / ds-bg:白底插画,彩色、粗细分明、一条连续笔路画完(长线不切分)
python tools\ink_extract.py --input ..\resources\imgs\ds-bg-line.png --name ds-line `
--out assets\ds-line.json --mode edge --eps 0.9 --order tsp --merge 2 --colors 8 `
--detail 92 --min-len 7 --width-min 0.5 --width-max 2.1 --width-gamma 1.15 `
--preview assets\ds-line.preview.png `
--fill assets\ds-line.fill.webp --fill-style smooth --fill-size 2000 --fill-quality 90 `
--fill-softness 0.92 --fill-blur 1.3 --fill-colors 24
# maid:竖构图、背景是房间(不抠纸),按比例留白
python tools\ink_extract.py --input ..\resources\imgs\1870.png --name maid `
--out assets\maid.json --mode edge --eps 0.9 --order tsp --merge 2 --colors 8 `
--detail 90 --min-len 7 --width-min 0.5 --width-max 2.0 --fit contain `
--fill assets\maid.fill.webp --fill-style smooth --fill-size 2000 --fill-alpha none
# chibi:方形白纸,抠纸 + 完整留白
python tools\ink_extract.py --input ..\resources\imgs\296.png --name chibi `
--out assets\chibi.json --mode edge --eps 0.9 --order tsp --merge 2 --colors 8 `
--detail 90 --min-len 7 --width-min 0.5 --width-max 2.0 --fit contain `
--fill assets\chibi.fill.webp --fill-style smooth --fill-size 2000 --fill-colors 24
# moss:黑底排版 Logo,字形外轮廓 + 原色(白字 + 红 D)
python tools\ink_extract.py --input ..\resources\imgs\MOSS.png --name moss `
--out assets\moss.json --mode contour --eps 0.7 --min-area 40 --min-len-px 20 `
--colors 3 --width-min 0.42 --width-max 0.62 --merge 0 --min-len 5 `
--preview-bg "#000000" --fill assets\moss.fill.webp --fill-size 2000 --fill-colors 8
--fill 生成上色层(assets/<name>.fill.webp),build.py 会自动把它内联进 client.js。
三种风格:smooth(柔化上色,默认)、original(直接叠原图)、flat(硬量化)。
2. 重新打包
python tools\build.py # 把 assets\*.json 内联进 client.js
node --check client.js # 可选:语法检查
3. 刷新窗口
设置页 → 线稿 → 选新图 → 全屏播放一次。
设置项
| 分组 | 参数 |
|---|---|
| 播放 | 启用、频率(每天首次 / 每次加载 / 仅手动)、允许点击或 Esc 跳过 |
| 这张图的预设 | 把当前一整套参数存成该线稿专属预设;存了之后滑杆只改这张图,可与其它图互不影响 |
| 画面 | 选哪张线稿、铺放(自动 / 铺满裁切 / 完整留白)、缩放、水平偏移、垂直偏移、旋转、不透明度 |
| 线条与颜色 | 用色(原图颜色 / 单色)、线条颜色(选色即切到单色并直接替换全部线条)、线宽、粗细变化、笔锋(两端收细,默认关)、高亮色 / 辉光色、辉光强度与半径、底色 |
| 描绘 | 起始停顿、描绘时长、并发笔数、笔尖光点、描完停顿 |
| 上色 | 描完后填上原图实色(开/关)、填色与发光同时进行(开/关)、填色时长、填色不透明度、填色后线条加深(默认 0)、描线最终不透明度(默认 0)、描线让位时长 |
| 闪光 | 闪光方式(自动 / 亮部炸光 / 墨色洇开)、辉光(光效总开关:光晕 / 全屏染色 / 笔尖光点 / 线条变色加粗)、衰减开关、起亮 / 保持 / 衰减、加粗倍数、脉冲放大、全屏闪光 |
| 退场 | 时长、放大倍数 |
设置保存在本机浏览器(localStorage)。「复制配置」可导出当前 JSON,「恢复默认」回到初始值。
按图预设:方图、竖图、横图的构图差得太远,一套数值不可能都合适。点「保存为这张图的预设」
会把当前整组参数记在这张线稿名下(dsh.ink-splash.v2.presets);之后切换线稿、切主题都会
自动套用它,没有预设的图继续走通用设置。
关于偏移:偏移量是视口宽高的百分比(-50% ~ +50%),所以换分辨率也不会跑偏。
关于颜色:用色 有两个模式——原图颜色 用提取时的调色板,单色 用一条颜色替换全部线条。
点「线条颜色」的色板会自动切到单色并立刻生效,是替换而不是叠加/相乘。
高亮颜色、辉光颜色 保持「自动」时跟随线条自身的颜色(闪光只调整明度,不串色,
辉光也按同色相晕开);手动指定才会覆盖。
结构
ink-splash/
├─ index.js Host 侧入口(空实现,仅承载 bundle 行)
├─ client.js 构建产物:播放器 + 覆盖层 + 设置页(含内联线稿)
├─ src/client.template.js 可读源码
├─ src/defaults.json 默认参数
├─ tools/ink_extract.py 图片 → 有序折线(edge / contour / iso)
├─ tools/build.py 内联资源,产出 client.js
└─ assets/*.json 线稿数据
实现要点
- 线稿在离线阶段提取成矢量折线(归一化到 1000 单位的 view box),每条线带 颜色索引和宽度系数;运行时只播放,所以任意分辨率下线条都锐利。
- 播放是 Canvas 2D:已画完的线按「宽度档 × 调色板」分桶,每桶合并成一条
Path2D一次描完(8 色 × 5 档 = 最多 40 次描边/帧);进行中的线用setLineDash按弧长截断, 每帧的绘制次数与"同时进行的笔数"同阶,1000+ 条线也能稳定 60fps。 - 笔锋(可选,默认关):Canvas 没有变宽描边,所以每条线按弧长切成「尖—粗—尖」三段 (0–30% / 30–70% / 70–100%),两端按比例收细、圆头衔接;描绘过程中也用同一个 弧长窗口截断,所以笔尖落下时是细的,走到中段变粗,收笔再变细。 这套线稿的笔画偏短(中位 18 单位),收细段只有几像素,观感并不明显,默认关闭。
- 辉光不是逐帧模糊:闪光时把整幅线稿画到上层 canvas,用 CSS
filter: blur()做一次模糊, 之后只改透明度和缩放。上层的线稿按调色板分成 8 条Path2D分别上色, 所以模糊出来的是各自色相的晕光,而不是一团单色。浅色主题用multiply(墨色洇开), 深色主题用screen(发光)。 - 上色:描完之后把一张上色图淡入到线条下面,三种风格:
smooth(默认)柔化 + 提饱和 + 18% 轻量化,偏绘画感、和描线不打架;original直接叠原图,最锐利但会和描线出现轻微双影;flat硬量化成色块。 抠纸只去"与图像边缘连通"的背景,被主体包住的浅色(脸颊高光)保持不透明, 所以不会出现白色空洞。存为带 alpha 的 WebP(约 100–140 KB/张)。 填色到位时线条默认保持原色不变;如果发现某些线条和填充同色、糊在一起, 可以把「填色后线条加深」调到 0.15–0.3。 - 上色与发光默认同时开始:线条刚开始炸光,颜色就从下面漫上来,辉光衰减的同时 颜色铺满;关掉「填色与发光同时进行」则回到"先填色、后闪光"的串行节奏。
- 收尾让位:闪光结束后描线在「描线让位时长」(默认 420ms)内淡到「描线最终不透明度」 (默认 0),所以最后一帧就是原图本身,再整体淡出进入软件。想让线稿留在画面上, 把这个值调到 0.3–0.6 即可。
- 开屏层经
react-domportal 挂到document.body,再以popover="manual"进入浏览器 top layer:z-index 对 top layer 无效,这样即使设置面板是原生<dialog>也能盖住。 宿主若未暴露react-dom,退化为「播放前先关闭设置面板」。
已知限制
- 频率"每天首次"按本机日期判定;换机器或清缓存会重新播放。
- 换图需要重新提取并刷新窗口;提取器只依赖
opencv-python / numpy / Pillow(不需要 skimage 或 opencv-contrib)。
Plugin correlati
archify (deepseek-harness)
tt-a1i/archify
next-ai-draw-io (dsh-plugin)
dayuanjiang/next-ai-draw-io
WeKnora (dsh-weknora)
tencent/weknora
weknora
tencent/weknora




