Skip to content
Image Generation
Skill

/tephra

把一张图重画成黑底像素画,两种正典画法按题材二选一:**纯粒子**(会动的短笔触沿图像自身 的结构方向流动,适合浪/烟/光柱这类本来就在流动的东西),或**网点实体**(把明暗翻译成 逐帧静止的有序点阵,适合人像/雕塑/动物这类要读出轮廓和体积的东西,并且只有它能把形体 梳成硬边碎裂条)。动效按画面的物理规律分区规划;可选地让一部分形体溃散成飞灰,同时锚定 另一部分保持实体与原色。输出静态 PNG 与无缝循环 GIF/MP4。 触发:/tephra、「粒子流动效果」「把这张图重绘成笔触」「黑底像素画」「网点碎裂」。

BOOST
From plugin
labart
2893 skills
Install
$ npx -y skills add haorantang97/LabArt --skill tephra --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/tephra

Context preview

The summary Claude sees to decide when to auto-load this skill.

把一张图重画成黑底像素画,两种正典画法按题材二选一:**纯粒子**(会动的短笔触沿图像自身 的结构方向流动,适合浪/烟/光柱这类本来就在流动的东西),或**网点实体**(把明暗翻译成 逐帧静止的有序点阵,适合人像/雕塑/动物这类要读出轮廓和体积的东西,并且只有它能把形体 梳成硬边碎裂条)。动效按画面的物理规律分区规划;可选地让一部分形体溃散成飞灰,同时锚定 另一部分保持实体与原色。输出静态 PNG 与无缝循环 GIF/MP4。 触发:/tephra、「粒子流动效果」「把这张图重绘成笔触」「黑底像素画」「网点碎裂」。

SKILL.md

tephra.SKILL.md
name: tephra
description: >
  把一张图重画成黑底像素画,两种正典画法按题材二选一:**纯粒子**(会动的短笔触沿图像自身
  的结构方向流动,适合浪/烟/光柱这类本来就在流动的东西),或**网点实体**(把明暗翻译成
  逐帧静止的有序点阵,适合人像/雕塑/动物这类要读出轮廓和体积的东西,并且只有它能把形体
  梳成硬边碎裂条)。动效按画面的物理规律分区规划;可选地让一部分形体溃散成飞灰,同时锚定
  另一部分保持实体与原色。输出静态 PNG 与无缝循环 GIF/MP4。
  触发:/tephra、「粒子流动效果」「把这张图重绘成笔触」「黑底像素画」「网点碎裂」。
  算法与代码全部原创,输出不基于任何模型,也不复制任何具体作品。
license: PolyForm-Noncommercial-1.0.0

Tephra v8

核心脚本 `scripts/tephra.py`,确定性(同参数同 seed 逐字节相同)。

> **改代码时的铁律:不要往共享 `rng` 上加无条件的抽取。** > 每次渲染都会跑到的新噪声场,必须自己开一条流(`np.random.default_rng(seed * 常数)`)。 > 从共享流上抽会把后面所有抽取(笔触播种、雨点)整体挪位,同一条命令换个版本就渲不出 > 同一张图了。0.2.0 修的就是这个(湍流卷曲场 `_n1`)。 **交付时必须报出完整命令**——那就是版本号。

---

先读:工作流(七步,不要跳)

这套东西最常见的失败不是参数调错,是**跳步**。按顺序走:

1. **叠网格** 在源图上叠 0.1 间距的归一化网格,所有坐标参数(漩涡中心/分区/锚定)从图上**读**出来,不要估。 2. **体检** `python3 scripts/dp_fitness.py 图.png [--invert]`。不过就别硬渲,回第 3 步。 3. **前处理** 见下「M0.5」。改的是明暗,不是几何。 4. **列元素 → 逐个判物理** 画面里有哪几样东西,每样在物理上往哪走。见「M3 物理对照表」。 5. **写成分区** 一个元素一条 `--flow-region`;天然同心的结构才用 `--swirl`。 6. **渲** 7. **验** 相位互相关逐区量位移,与第 4 步的判断核对。**方向靠眼睛看会错。**

---

两种正典画法(先选一种,再往下调)

这套东西有**两条都成立的正典**,各自对应一批不同的参考作品。**选错了后面全是白调。**

![两种画法](assets/canon-modes.jpg)

*同一张源图、同一个主体,左 A 右 B。 两边都是各自路线调到最好的版本,不是「同参数开关 mass」——把 B 的参数原样关掉 mass, 画面会直接空掉(B 的 `--density 0.02` 几乎没有笔触,整张画都靠网点层撑着)。*

| | **A · 纯粒子** | **B · 网点实体** | | --- | --- | --- | | 一句话 | 用会动的短笔触把图重画一遍 | 把明暗翻译成一层静止的有序点阵 | | 参考作品 | 样本J 的「尘」那一层 | 样本A / 样本K | | 开关 | `--mass 0`(preset `flux` 的默认) | `--mass 2.6` + 原生网格渲染 | | 主体逐帧 | 一直在动(帧间留存 ≈ 0.83) | **完全静止**(≈ 0.999) | | 落点怎么定 | 按亮度加权**随机采样** | 跟固定 8×8 Bayer 表**阈值判定** | | 质感 | 密集绒毛状笔触,边缘硬 | 规则点阵,能读出连续调子 | | 擅长 | 浪、烟、光柱、火、水花——**本来就在流动的东西** | 人像、雕塑、动物、建筑——**要读出轮廓和体积的东西** | | 不擅长 | 人像(糊成一团毛,读不出结构) | 流体(点阵钉死,动感全没了) |

A · 纯粒子——裸跑即正典

python3 scripts/tephra.py in.png -o out --size 1400 --seconds 1.6 --fps 25 --mp4

默认 preset `flux` 就是它,`--floor auto` 从这张图自己的直方图读。 **不要为了「用上正典」手打一长串参数**——那串就是默认值。

B · 网点实体——必须走原生网格

python3 scripts/tephra.py in.png -o nat --size 768 --supersample 1 --palette ash \
  --mass 2.6 --density 0.02 --sparsity 6.0 --floor 0.008 --contrast 1.15 --coherence 16 --stroke 3 \
  --dissolve 溃散方向,0.45,0.40 --dissolve-patch 0.35 --escape 0 \
  --comb-life 0.04 --comb-emit 0.2 --comb=梳向,2.3,30,1.45,0.16,5,0.70,66,0.24,7.0,0.26,3.6 \
  --seconds 0.96 --fps 25 --mp4
python3 scripts/upscale_nearest.py nat.png out.png 1400

细节与实测验收表见 **M4**。这一路**必须在 512–768 的原生网格上渲再 NEAREST 放大**—— 直接渲 1400 会把碎料糊成烟,这是最容易踩的一个坑。

> **`--comb` 的碎裂条只能从网点上梳出来。** > 没有 mass 层就没有点阵可梳,梳笔触只会得到一团运动模糊。 > 所以 B 那种硬边碎裂条在 A 里做不出来——**不是参数没调对,是缺一层。**

> **`--mass` 不是风格开关,是亮度门槛。** 它只决定「多暗算暗到不画」。 > 画出来长什么样由**源图的明暗分布形状**决定,不由这个数决定: > 侧光雕塑的调子摊在中间段 → 网点连续过渡,读得出体积; > 逆光剪影被相机压死、内部几乎一个值 → 近三成面积顶到 90% 以上,读起来是一块剪纸。 > (实测:同一套参数,雕像只有 8.5% 的面积超过 80% 占空比,马是 29.8%。) > 想让剪影也有层次,要在 **M0.5 前处理**里造体积明暗,改 `--mass` 没用。

共用的加料(两条路都适用)

| 想要 | 加什么 | | --- | --- | | 换色 | `--palette gold / ember / blood / violet / phosphor / neon` | | 虚空不够/主体发碎 | `--floor 0.05` 覆盖自动值 | | 白底图或暗主体 | `--invert`(**注意副作用,见 M0.5 P1**) | | 焦点星爆 | `--burst-at X,Y,强度` | | 三维漩涡 | `--swirl X,Y,S,R,RATIO,TILT,PITCH` | | 保留一个实体物 | `--anchor X,Y,RX,RY[,S][,#色][,块][,曝光][,黑点分位][,彩度]` | | 一部分溃散 | `--dissolve DEG,START,SOFT` + `--dissolve-patch 0.5` |

---

模块(一个模块只负责一件事)

**铁律:模块之间不许偷偷改对方的参数。** 历史教训:`--dissolve` 曾经把 `--mass` 从 0 改成 1,于是「只加一点溃散」实际换掉了整张图的画法。

M0 输入判定

`scripts/dp_fitness.py`。判据:**中位亮度 < 0.20 直接过;否则要求可分离性 > 0.55**。 (依据:4 张成功/失败样本实测。中位亮度低 = 虚空是图自带的;可分离性高 = 删哪儿由图决定不由你猜。)

M0.5 前处理(只改明暗,不改几何)

| 规则 | 触发 | 手段 | | --- | --- | --- | | P1 反相 | 主体比背景暗 | `--invert`。**副作用:主体自己的高光会变成 floor 首先删除的对象**,造型强的物体会掉一截 | | P2 去梯度 | 大尺度亮度梯度(大气/景深/渐晕) | 减一个超大尺度高斯背景再归一化 | | P3 裁非画面物 | 水印/字幕/拼接缝 | **裁掉,不要修补**——修补留下的直角缝会被忠实渲染成方块 | | P4 换轴 | 主体与背景亮度接近(差 < 0.05)但纹理差 1.5 倍以上 | 用局部对比度当门槛 | | P5 重打光 | 前四条都救不回来 | img2img,denoise 0.25–0.35,**几何锁死**,结构保真 > 0.55 |

**什么时候必须上 P4**:主体上某个你要保住的部件(耳朵、下颌、发丝)与背景**中位亮度差 < 0.02**。 量一下再决定——雕像的耳朵和背景烟都是 0.055,试多少个 `--floor` 都是白试。 现成脚本:`scripts/p4_mask.py 源图 输出.png`(小而亮的东西如余烬会被纹理判据误杀,脚本单独保留)。

**P4 的陷阱(必读)**:纹理能量本质上是边缘检测,直接拿它当形体会把实心物体变成**铁丝网**—— 只有一圈亮边、内部是空的,粒子化之后糊成一团。正确用法是: **纹理只用来造「区域掩膜」(闭运算→填洞→大尺度平滑),形体交回给主体自己的明暗。** 这样还有个好处:背景已由掩膜杀掉,就**不需要反相**,主体内部直接用源图明暗—— 受光处密、背光处疏,「张弛有度」是光影本身给的,不用另外发明规则。

M1 形体

互斥三选一,前两个都是正典,按上面那张表按题材选: **A 纯粒子 `--mass 0`** / **B 网点实体 `--mass 2.6`(要碎裂条就只能选它)** / 局部锚定 `--anchor`。

`--anchor` **不做主体分割**:逐 RGB 通道对源图抖动,暗的自己不印、彩的自己出色, 黑点分位从椭圆区内自取(区内多数面积是背景 → 背景自动归零)。 彩度提升必须**按已有彩度开门**,否则中性色的微弱色偏会被放大成假色(白浪变青)。

M2 笔触质感

`--stroke` 最长笔长 / `--length-mix` 长短偏斜 / `--aniso-len` 各向异性区才给长笔 / `--fray` 子段错位 / `--gap` 断口 / `--jitter` `--curve` 歪与弯 / `--density` `--sparsity`。

**笔长必须小于你要读出来的最小部件**。一根 22px 的笔画不出一个 25px 的蹄子,只会盖过去。 细节多的图:`--stroke 10 --coherence 18`;大形为主:`--stroke 22 --coherence 45`。

M3 流动(三层,各自独立、都可局部化,权重最强者赢)

| 层 | 参数 | 何时用 | | --- | --- | --- | | 全局朝向 | `--flow-bias` / `--flow-from-burst` | 兜底 | | **分区朝向** | `--flow-region X,Y,RX,RY,ANGLE[,S]` | **默认手段**,一个元素一条 | | 分区旋转 | `--swirl X,Y,S,R[,RATIO,TILT,PITCH]` | 只给天然同心的结构 |

**物理对照表**:光柱/雨/瀑布/坠落=90° | 火焰/余烬/上升烟=−90° | 破碎浪的浪背≈−40° | 浪的桶内/发髻/年轮/星系=`--swirl` | 爆炸碎片=`--flow-from-burst` | **岩石/建筑不动,什么都不给**。 拿不准就问:关掉重力和风,它还会往那个方向动吗?不会就是编的。

**M3.a 三维漩涡**:`RATIO` = 投影椭圆的短长轴比(**必须实测**,拟合泡沫环主轴),`TILT` 长轴倾角,`PITCH` 径向内收。 在水面平面里旋转再把速度投影回画面——透视压缩自动产生(端部慢、鳍部快),速度按 1/r。 **平面圆形漩涡会把水推着横切过所有的圈**,读起来就是一个转盘。

`--conserve 1.5` **必开**:消除吸引子造出的假轮廓。

M4 溃散(可选,非每图必用)

> ### 最关键的一条:**在原生网格上渲,再 NEAREST 放大** > 样本A 的原生画幅是 **512×384**(GIF 容器 2048×1536,4×4 块 100% 一致,实测), > 墨严格二值(只有 0 和 210 两个值),点亮率 10.2%。 > **一个"像素"= 画幅宽度的 1/512。** 直接在 1400 宽上抖动,格子就细了 2.7 倍—— > 单个像素永远读不出来,整片碎料糊成烟。这是"感觉像烟不像破损"的唯一根因。 > 做法:`--size 512 --supersample 1` 渲,再用 `scripts/upscale_nearest.py` 放到交付尺寸。 > 验收用 `scripts/native_check.py 成品.gif`,逐项对照下表实测值。 > > | 指标(512 网格) | 样本A 实测 | > | --- | --- | > | 点亮率 | 10.21% | > | 实体(≥80% 帧点亮) | 8.18%,**逐帧完全静止 1.000** | > | 碎料 | 2.03%,**1101 个独立块/帧** | > | 单块面积 | 中位 **2**,p90 8,p99 25,max 36(最大约 15×10) | > | 碎料运动 | 每帧漂移 **+1,+1 px**,最佳平移后仍**每帧死掉 61%** | > | 碎料射程 | 184 px ≈ **1.0 S**

Read more
Ships withlabart

Black-pen illustrations, animated pixel art, and deadpan watercolor illustrations. Explore each plugin below.

Get the whole plugin
Stats
289
Stars
15
Forks
Active
Maintenance
Python
Language
3d ago
Last commit
2mo ago
Created
3h ago
Added

Repo: haorantang97/LabArt

Other skills on labart.

deadpan-doodles
Skill

deadpan-doodles

用通透的钢笔淡水彩画有冷幽默、童趣和反常比例的插画,适用于人物 IP、猫狗、花草、物件和小场景,也可局部修改已选作品。真人头像走专用模块;不用于写实肖像或精致萌系插画。