page-steganography
v0.0.1
Published
页面隐形水印工具:把文本隐写入页面顶层遮罩,从任意截图中鲁棒解码 / Invisibly embed text into a topmost overlay and decode it from any screenshot
Maintainers
Readme
页面隐形水印 · page-steganography
有人截图了!
感谢某里、某为、l*nux.*o 等提供灵感 · 用 fount vibe 而来,谢谢龙胆的陪伴。
在线 Demo:https://steve02081504.github.io/page-steganography/ — 左侧输入水印实时写入当前页,右侧拖入 / 粘贴截图即可解码。
快速开始
直接在任意页面导入:
<script type="module">
import { setWatermark } from 'https://cdn.jsdelivr.net/gh/steve02081504/page-steganography/watermark/index.mjs'
// 写入 — 模块导入时已自动挂载遮罩,调用即实时重绘
await setWatermark('ver abcde')
</script>npm:
npm install page-steganography写入
import { setWatermark, getWatermark, deleteWatermark } from './watermark/index.mjs'
// 写入任意字符串(内部经 TextEncoder + 可选 deflate-raw 压缩 + 白化后铺满整页)
await setWatermark('The quick brown fox jumps over 0123456789 !@#$%')
await deleteWatermark() // 清空
getWatermark() // -> 当前文本(同步)说明:
setWatermark(text)接受string,返回Promise<string>(还是文本),内部会等待一次renderOverlay()完成。- 隐藏 / 显示遮罩(调试用,不影响解码能力——截图时需可见):
const cv = document.querySelector('canvas[data-watermark]')
cv.style.display = cv.style.display === 'none' ? '' : 'none'解码
支持 File / Blob / HTMLImageElement / HTMLCanvasElement / ImageData,在浏览器主线程异步执行,失败返回 '' 而非抛错。
浏览器:拖入 / 粘贴截图
<input type="file" id="file" accept="image/*" />
<script type="module">
import { decodeWatermark } from 'https://cdn.jsdelivr.net/gh/steve02081504/page-steganography/watermark/decode.mjs'
document.getElementById('file').addEventListener('change', async (e) => {
const file = e.target.files[0]
const text = await decodeWatermark(file) // File extends Blob
console.log(text || '(未检测到水印)')
})
</script>检测被 P 过的部位
水印铺满整页、每个像素都带一个可预测的符号。如果截图里某块区域被人用 PS 改过,那处的水印就被破坏、符号对不上。用 decodeWatermarkDetail() 可同时得到文字和一份"损坏掩码":
import { decodeWatermarkDetail } from 'https://cdn.jsdelivr.net/gh/steve02081504/page-steganography/watermark/decode.mjs'
const { text, width, height, data, mask } = await decodeWatermarkDetail(file)
// text : 解出的水印文字(失败为 '')
// data : 原图原始像素(Uint8ClampedArray,RGBA,长 = width*height*4)
// mask : 损坏置信度掩码(Float32Array,长 = width*height,小数。),0 = 完好,1 = 明显被篡改;未检出水印时为 null在线 Demo 里拖入截图后,点 「显示修改部位」,被 P 过的中性区域会按置信度染红,再点一下恢复原图。 为免低置信度的完好/噪声像素把整图染粉,建议显示透明度用膝点 + 幂曲线映射。
Q&A
你为什么要这么做?
好玩且酷,以及我受够了 fount 用户在反馈时不带版本号。
颜色偏转是正常现象吗?
是的,目前的canvas不支持负通道值,且浏览器不支持页面js对页面截图来应用负通道,所以我们很难做出平均通道值为0的遮罩方案,只能选择一个人眼不易觉察的偏转权重。
如果你是某大厂员工,能用 CEF 等掌控渲染管线,可用真正的正负通道叠加做到零偏转。
JPEG/WebP 能解吗?
不能作为保障目标。有损压缩会摧毁 ±(Δ×α)≈±4.8 的色度信号,协议以无损 PNG 截图为鲁棒基准(见 watermark/format.mjs 注释与测试约定)。
我有个想法……
欢迎PR/issue!
