npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

page-steganography

v0.0.1

Published

页面隐形水印工具:把文本隐写入页面顶层遮罩,从任意截图中鲁棒解码 / Invisibly embed text into a topmost overlay and decode it from any screenshot

Readme

页面隐形水印 · page-steganography

有人截图了!

感谢某里、某为、l*nux.*o 等提供灵感 · 用 fount vibe 而来,谢谢龙胆的陪伴。

Demo

在线 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!

猜你喜欢