snowyukitty/lumark-watermarker
GitHub: snowyukitty/lumark-watermarker
基于 Tauri、Rust 和 React 构建的本地优先桌面水印工作室,支持可见与隐形水印、批量导出和真正的所见即所得预览。
Stars: 0 | Forks: 0
# Lumark
**Lumark = Luma + Mark。** 一款本地优先、隐私优先的桌面
水印工作室。
一切都在你的机器上运行:无云端上传,无需账户,无
遥测,完全没有任何网络请求。基于 Tauri v2、React、
TypeScript、Tailwind CSS v4 构建,并使用 Rust 图像引擎在
实时预览(通过 WebAssembly)和最终
导出(原生代码)中渲染出**完全相同的像素**——所见即所得。

## 功能
### 水印
- **文本水印** —— 支持多行文本、按比例缩放字体大小、
颜色 + 透明度、带对齐旋转、独立的描边/轮廓
(宽度、颜色、透明度),以及精心挑选的 16 色调色板和
最近使用颜色历史记录。
- **图片 / Logo 叠加** —— 盖上 PNG 或 WebP 格式的 Logo 或签名,
可自定义其缩放比例、透明度、位置和边距。
- **平铺模式** —— 在整个图片上重复平铺文本
水印,可配置间距,经典的“机密文档”
样式。
- **隐形水印 (LSB steganography)** —— 将隐藏的文本
信息嵌入到像素数据中(仅支持 PNG 输出,因为有损格式
会破坏它),之后可以提取还原。对其
局限性保持诚实:UI 会提示该水印无法在 JPEG 重新编码后保留。
- **定位** —— 九宫格锚点、在画布上自由拖拽定位、三分线和
黄金比例线吸附引导,以及带有控制柄的
边界框叠加层。
### 工作流程
- **真正的 WYSIWYG 预览** —— 编辑器预览调用了与导出
完全相同的 Rust 渲染函数,该函数被编译为 WASM 并绘制在
Canvas2D 上。单一渲染器,零偏差。典型重渲染耗时:15–40 ms。
- **批量导出** —— PNG (无损)、JPG (质量滑块)、
WebP (无损),或每张图片导出为单页 **PDF**。提供每张
图片的进度和结果,并在运行前提供
文件大小预估。输出文件名带有时间戳,且导出器
**绝不会覆盖你的源文件**。
- **预设 + token** —— 七个内置模板(验证 /
保护 / 社交),通过 `{purpose}` `{platform}`
`{name}` `{handle}` `{date}` 参数化,带有实时预览标签,并且
支持保存你自己的预设。
- **水印配置文件** —— 将完整的水印设置保存/加载为
便携的 `.lumark` JSON 文件。
- **单图覆盖设置** —— 在批处理中微调单张图片
而不丢失共享配置;支持在缩略图
条中多选。
- **四语种 UI** —— English / 日本語 / 繁體中文 / 简体中文,
首次启动时自动检测操作系统语言。
- **提升体验的特性** —— 深色/浅色主题、可折叠的缩略图
条、画布颜色取色器、最近文件、在系统中显示、状态
持久化及一键重置。
### CLI
`crates/cli` 构建了一个独立的 `lumark` 二进制程序,可驱动相同的
引擎以执行脚本化批处理任务:
```
lumark --overlay logo.png --text "© 2026" input/*.jpg
lumark --text SAMPLE --tile --rotation -30 -f pdf photos/*.png
lumark --hidden-text "ID:12345" --text DRAFT photo.png
```
## 尚未实现的功能
- ❌ EXIF 保留 —— 导出文件会被重新编码,且元数据会被
剥离(参见下方的隐私说明;目前这是有意为之)。
- ❌ WebP 有损编码 —— `image` crate 仅支持无损,因此 WebP 的
质量滑块被禁用。
- ❌ 真正的可变字重 —— `ab_glyph` 无法驱动 `wght`
轴;粗体使用可选的 `Inter-Bold.ttf` 直接替换,或使用诚实的
合成回退方案。
- ❌ 签名 / 公证版本 —— Windows NSIS 安装程序已
实现自动化但未签名;macOS 打包尚未测试。
- ❌ 自动更新 —— 设计使然。Lumark 绝不进行网络回传;获取新
版本的方式与你获取第一个版本的方式相同。
## 隐私
Lumark 的设计确保它*无法*泄露你的图片:
- 应用中**不存在任何网络代码** —— Rust 端没有 HTTP
客户端,前端仅从本地资源协议获取数据。
- 全分辨率图像字节永远不会进入 webview;只有
缩小后的预览 JPG 缓存在应用程序专属的缓存文件夹中。
- 设置、水印配置和最近使用的文件*路径*会保存在
你机器的本地存储中——除此之外,别无其他,也没有任何其他地方。
- 导出的文件都是全新编码的,因此源文件的 EXIF(GPS 位置、
相机序列号等)**不会**随水印副本一同携带。
详情、存储位置以及如何彻底清除所有数据:
[`PRIVACY.md`](PRIVACY.md)。
## 快速开始(基于源码)
前置条件:[Node.js 22+](https://nodejs.org)、
[pnpm](https://pnpm.io)(仓库通过 `packageManager` 锁定了 `10.6.3`)、
稳定的 [Rust 工具链](https://rustup.rs),以及用于引擎开发的
WASM 工具:`rustup target add wasm32-unknown-unknown` 和
`cargo install wasm-pack`。
```
pnpm install --frozen-lockfile
pnpm tauri dev # full desktop app, rebuilds Rust on save
```
开发服务器将绑定到 `http://127.0.0.1:19993`。如果你的
机器保留了该端口(在
Windows 上检查
`netsh interface ipv4 show excludedportrange protocol=tcp`),请在 `vite.config.ts` 和
`src-tauri/tauri.conf.json` (`devUrl`) 中**同时**进行更改
—— 它们必须保持一致。
`src/wasm-engine/` 中的 WASM 引擎构建产物已提交至仓库,因此在
你修改 `crates/engine*` 之前,应用
无需 WASM 工具链即可运行——如果要进行修改,请先运行
`pnpm wasm:build` 再进行测试。
关于日常使用 —— 加载图片、预设、导出 —— 请参阅
[`docs/usage-guide.md`](docs/usage-guide.md)。
## 构建 Windows 安装程序
```
pnpm build:exe
```
运行 `wasm:build` + `tauri build --bundles nsis`,然后打印出
`target/release/bundle/nsis/Lumark_X.Y.Z_x64-setup.exe` 的
绝对路径和 SHA-256 校验值(约 15 MiB,
未签名)。带有 `v*` 标签的推送会在 CI 中通过
`.github/workflows/release-windows.yml` 产生相同的构建产物,并且在此之前有完整的验证
流程。
## 验证
```
pnpm wasm:build
pnpm build
cargo test --workspace # 90 / 90
pnpm qa:image # repeatable engine output QA
pnpm check:ui-overflow # headless layout check
```
手动视觉 QA 位于
[`docs/manual-qa-image-preview.md`](docs/manual-qa-image-preview.md)
——在对引擎、WASM 预览或
资源协议进行任何更改后,都必须执行此操作。
## 字体
- **Inter Variable** (Latin) 在编译时从
`public/fonts/` 嵌入 —— 遵循 SIL OFL 1.1 协议,许可证随附在字体文件旁。
- **Noto Sans TC** (繁体中文子集,约 5.7 MB) 打包在
`src-tauri/resources/fonts/` 中 —— 遵循 SIL OFL 1.1,请参阅那里的 `OFL.txt`。
你可以通过替换文件(保持相同的文件名)来换用其他的 CJK 字体;
如果需要渲染 CJK 文本但无法读取到 CJK 字体,Lumark
会返回明确的错误提示,而不是显示乱码方块。
- **`Inter-Bold.ttf`** 是可选的直接替换文件,用于实现真正的粗体;如果
没有该文件,预览和导出都将使用相同的合成粗体回退方案。
第三方许可证清单:[`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)。
## 一段话架构概述
这是一个 Cargo workspace,其核心是一个纯粹的图像处理 crate
(`crates/engine`) —— 渲染路径中没有 Tauri,也没有文件系统操作。Tauri 外壳
(`src-tauri`) 原生调用它进行
导出;webview 调用同一个编译为 WASM
(`crates/engine-wasm`) 的 crate 来进行实时预览;`crates/cli` 则为终端封装了
该引擎。React 前端将所有状态保存在一个 Zustand
store 中。完整的来龙去脉,包括为什么所有 CSS 叠加预览
方案都被否决了,请参阅
[`docs/wysiwyg-contract.md`](docs/wysiwyg-contract.md)。
## 文档导航
| 文件 | 阅读时机 |
|---|---|
| `docs/usage-guide.md` | 你正在使用该应用。 |
| `docs/wysiwyg-contract.md` | 你要修改预览或引擎。 |
| `docs/watermark-engine-references.md` | 你要修改可见水印引擎。 |
| `docs/manual-qa-image-preview.md` | 你修改了引擎 / 预览 / 资源协议。 |
| `docs/release-smoke-checklist.md` | 你正在生成或检查安装程序。 |
| `docs/releases/v0.1.0-rc3.md` | 最新的 RC 说明和已知问题。 |
| `AGENTS.md` | 你是接手此仓库的 AI 智能体。 |
| `docs/archive/` | 历史设计和里程碑文档。 |
## 项目规范
- **没有虚假的成功状态。** 禁用的功能看起来就是禁用的,并且会说明
原因。
- **`visibleMarkText` 和 `hiddenMarkText` 保持独立** —— 永远不会
相互自动推导。
- **`imagePath` 是唯一事实来源** —— Tauri 命令接收
文件系统路径;webview 永远不会接触全分辨率的字节流。
- **单一渲染器。** 不要重新引入 CSS 叠加预览;请阅读
`docs/wysiwyg-contract.md` 了解这条规则背后的九次迭代历史。
## 许可证
Lumark 基于 [MIT License](LICENSE) 发布。打包的字体单独
基于 SIL Open Font License 1.1 授权 —— 完整的
第三方清单请参阅
[`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)。
本地。诚实。从容。
标签:AI工具, React, Rust, Syscalls, Tauri, 可视化界面, 图像处理, 桌面应用, 水印工具, 网络流量审计, 自动化攻击, 隐写术