Vai al contenuto principale
L

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-splash

README

开屏线稿动画 · Ink Splash

把一张图片提取成线稿,启动时逐笔勾勒:线条一条条浮现,笔尖带一点光, 全部画完后所有边缘瞬间高亮发光,再化入界面。

  • 线稿保留原图颜色:发色、肤色、深色衣料各自成色,按调色板合并成 8 色
  • 线稿保留粗细:墨色越重线越粗(深色轮廓明显比浅色细节粗),像压感笔
  • 辉光也跟随原图颜色:闪光时每个色相各自发光(红色 D 出粉红光、蓝发出蓝光), 全屏闪光取整幅的加权平均色
  • 浅色主题:白底,线条沿用原图色,闪光时加深、同色晕开
  • 深色主题:黑底,线条提亮,闪光时烧成各自色相的发光体
  • 底色、线色、用色模式、宽度、速度、偏移……全部可在 设置 → 开屏动画 里实时调

内置五套线稿,设置 → 画面 → 线稿 里切换:

名称来源构图特点
ds-line(默认,浅色)ds-bg-line.png横 16:9平涂版本,无内描边,提取最干净:902 条
ds-bgds-bg.png横 16:9带内描边的版本,细节更密:929 条
maid1870.png竖 9:16室内场景,整幅保留不抠纸:1039 条
chibi296.png方 1:1Q 版 + 思考气泡,白纸抠图:141 条
moss(默认,深色)MOSS.png横 16:9字形轮廓,白字 + 红 D:78 条

浅色 闪光

作者的预设

仓库里的 presets/ 是作者本人调好的参数,可直接导入(见 presets/README.md)。 每张图一套,互不干扰:

线稿预览
ds-lineds-line
ds-bgds-bg
maidmaid
chibichibi
mossmoss

安装

插件就是这个仓库本身,通过 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(默认)插画、人像、有细节的照片忠实还原边缘,线条细密
contourLogo、扁平图形、排版字干净的外轮廓 + 内部孔洞
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.5fill 模式沿法线偏离线条多少像素去取色
--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 smoothsmooth(默认)柔化上色、无双影;original 直接叠原图、最锐利;flat 硬量化
--fill-softness 0.82smooth 下原图所占权重:越大越接近原图、越小越"色块化"
--fill-blur 2.0smooth 下的高斯半径(填充层像素),越大越柔
--fill-colors 24量化色数;smooth 时只用于"轻量叠回",色数越大越接近原图
--fill-size 2000上色层长边。必须明显大于窗口宽度(留 1.25× 余量),否则浏览器放大就会糊
--fill-quality 90WebP 质量,80 以下渐变会出现色带
--levels 7iso 模式的等值线条数

实验性(默认关,效果尚不稳定):--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-dom portal 挂到 document.body,再以 popover="manual" 进入浏览器 top layer:z-index 对 top layer 无效,这样即使设置面板是原生 <dialog> 也能盖住。 宿主若未暴露 react-dom,退化为「播放前先关闭设置面板」。

已知限制

  • 频率"每天首次"按本机日期判定;换机器或清缓存会重新播放。
  • 换图需要重新提取并刷新窗口;提取器只依赖 opencv-python / numpy / Pillow(不需要 skimage 或 opencv-contrib)。

Plugin correlati