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)和最终 导出(原生代码)中渲染出**完全相同的像素**——所见即所得。 ![Lumark 空白工作台](https://static.pigsec.cn/wp-content/uploads/repos/cas/a5/a504bfba9fb63d81da5dff4ea4fb4c91eab45307e2b926b946fc65f7b5ef2af4.png) ## 功能 ### 水印 - **文本水印** —— 支持多行文本、按比例缩放字体大小、 颜色 + 透明度、带对齐旋转、独立的描边/轮廓 (宽度、颜色、透明度),以及精心挑选的 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, 可视化界面, 图像处理, 桌面应用, 水印工具, 网络流量审计, 自动化攻击, 隐写术