供开发者和助理使用的本地照片工具
免费批量水印、文件名标签和日期戳。探索功能,然后在设备上处理明确选择的照片。
阅读为 Markdown · OpenAPI 3.1 · 配置 Schema
选择执行方式
发现 API 是公开的、免费的、只读的,并且不需要 API 密钥。它描述了工具和设置;它从不接受图像。没有 POST /水印、云处理服务或托管 MCP 端点。
使用浏览器 SDK 来显式选择此源上的文件。对于具有本地文件系统访问权限的助手,请显式连接存储库的 stdio MCP 服务器并授权根目录。找到此文档的模型无法访问设备或其文件。
| 表面 | 目的 |
|---|---|
| 获取 JSON / 降价 | 发现功能、配置、约束和本地工具签名。 |
| 浏览器 ESM SDK | 本地解码并渲染文件;需要 Canvas、DOM、createImageBitmap 和 File/Blob。不是 Node 或远程 HTTP 处理 API。 |
| 本地 CLI/stdio MCP | 使用已安装的 Google Chrome 和存储库依赖项显式连接本地自动化。 |
公开接口
GET 和 HEAD 返回静态资源。没有身份验证、请求正文、查询参数或用户数据。未知资源路径返回404。将版本1视为合约版本;为规范路径添加书签,而不是散列构建块。不承诺跨域浏览器访问;使用同源SDK进口。
curl https://watermark.noxxxx.com/api/v1/capabilities.json
curl https://watermark.noxxxx.com/api/v1/recipes/filename.json浏览器 SDK
在本网站的来源导入 /sdk/watermark.js。这是一个稳定的ESM入口网址;实现块可能会改变。以下示例需要多个文件输入,并在用户选择本地文件后运行。它创建了 ZIP 的成功副本;调用者必须检查 failures 和 cancelled,而不是将部分导出视为完成。
import { createRecipe, validateRecipe, inspectImage, processBatch, packageResults }
from '/sdk/watermark.js';
// Run on this site's origin in a modern browser, after explicit file selection.
const files = [...document.querySelector('input[type="file"]').files];
const recipe = createRecipe('filename'); // watermark | filename | date | frame
const errors = validateRecipe(recipe);
if (errors.length) throw new Error(errors.join('; '));
const records = [];
try {
for (const file of files) records.push(await inspectImage(file));
const result = await processBatch(records, recipe);
if (result.failures.length || result.cancelled) {
console.warn('Check partial results before downloading', result);
}
if (result.entries.length) {
const zip = await packageResults(result.entries);
const url = URL.createObjectURL(zip);
const link = document.createElement('a');
link.href = url; link.download = 'labeled-photos.zip'; link.click();
setTimeout(() => URL.revokeObjectURL(url), 30000);
}
} finally {
records.forEach(record => URL.revokeObjectURL(record.thumbnail));
}| 功能 | 输入→结果 |
|---|---|
| createRecipe(mode) | watermark | filename | date | frame → 独立的v1配置。 |
| validateRecipe(recipe) | 配置 → string[] 错误列表;空数组表示配置有效。语义校验还会检查图层 ID 是否重复、裁剪是否越界。 |
| inspectImage(file) | File → Promise<Record> 带有 id、名称、文件、宽度、高度、缩略图对象 URL、覆盖、元数据、元数据警告。完成后撤销缩略图。{id,name,file,width,height,thumbnail,overrides,metadata,metadataWarning} |
| renderImage(record, recipe, options?) | → Promise<{blob, geometry}>; preview:true 返回 {canvas, geometry}。选项:资产:Map <assetId,ImageBitmap | Canvas>,索引:数字,最大尺寸:数字,画布:Canvas。 missingMetadataText?:string.{blob,geometry} | {canvas,geometry} |
| processBatch(records, recipe, options?) | → Promise<{entries,failures,cancelled}>。条目:{name,blob,width,height,sourceId};故障:{id,name,longEdge,message}。选项:资产,信号:AbortSignal、onProgress({done,total,failed})、onResult(入场)。 missingMetadataText?:string.{entries:[{name,blob,width,height,sourceId}],failures:[{id,name,longEdge,message}],cancelled} |
| packageResults(entries) | → Promise<Blob> ZIP;当组合输出超过 450 MiB 时拒绝。 |
| decodeImage(blob) | → Promise<ImageBitmap>;完成后 close() 。 HEIC 使用第一个解码图像。 |
| parseLabelCsv(text) | filename,text CSV → Map<字符串,字符串>;精确名称匹配,重复名称拒绝。加工前自行设置record.label。 |
| imageRecipe(recipe, record) | 合并 record.overrides.image 和 record.overrides.layers[id] 而不改变共享配置。 |
| renderStudioImage / cleanLogo | 低级 Canvas 助手;请参阅存储库包/watermark-core/src/studio.js 以获取签名。优选 renderImage 进行编码输出。 |
配置规则与错误
从 /api/v1/recipes/watermark.json、filename.json、date.json 或 frame.json 下载完整配置。首先验证 JSON Schema,然后验证 validateRecipe 进行语义检查。层 ID 必须是唯一的。裁剪 x + 宽度和 y + 高度必须保留在图像内。大小、边距、边框和页脚使用裁剪和旋转图像的短边的百分比。输出 longEdge:0 保持大小;调整大小永远不会升级。 可选的 image.crop.aspectRatio 表示旋转后内容的宽高比。每张图片在各自的归一化选区内居中裁剪,混合尺寸批次保持同一比例;随后添加边框和底栏。手动编辑裁剪百分比会清除比例规则。
文本变量:{filename} 不包括扩展名; {fullname} 包括它; {index}使用sequence.start和填充; {label} 使用 record.label。相机变量为 {camera}、{lens}、{aperture}、{iso}、{shutter}、{focal}。 CSV 不会自动填充 SDK 记录。
日期预设使用每个图像的 DateTimeOriginal 或 CreateDate。不替换文件修改日期。缺少日期默认为空日期标签; missing:error 使该图像失败,missing:custom 如果可解析则使用 date.custom。 source:custom 直接使用提供的日期。自定义日期不是经过认证的时间戳。根据此政策,无效日期可能会产生空标签或错误。
配置包含设置,而不是徽标字节或自定义字体。通过由 layer.assetId 键入的 options.assets 提供徽标,并在使用后关闭解码的徽标位图。自定义字体必须加载到 LocalFont 系列下的 document.fonts 中。缺少资源会显式失败。
SDK 在批量执行之前抛出无效配置。每个图像的解码、渲染、元数据或编码错误出现在 failures 中,而成功的 entries 仍然可用。错误当前包含人类可读的中文消息;消费者不应该在他们的文字上分支。在输出之间检查取消;当前渲染不会中断。对于 onResult,entries 将传递给回调,并且不会保留在返回的 entries 数组中。
限制与隐私
无需付费照片计数配额、帐户、API 密钥、订阅或添加网站品牌。每个输入限制为 150 MiB 和 1.2 亿像素; ZIP 输出限制为 450 MiB。最大 30 层,6 个附加输出尺寸,长边可达 32768。浏览器 Canvas、内存、解码器和文件系统限制可以更低;分割大批次。
输出为 JPEG、PNG 或 WebP。 JPEG 和有损 WebP 被重新编码。默认元数据模式为“strip”。 “safe”和“all”模式需要 JPEG 输出。 safe模式不包括GPS; all模式可以保留位置元数据。不保留 ICC 配置文件、HDR 和签名。原始文件永远不会改变。
在 /studio/ 中,仅可选择缓存程序资源以供离线使用。新的公共页面最初需要网络连接才能加载。用户图像和文件名不会发送到公众 API 或存储在预设中。仅保存/共享不包含私人文本的配置。
本地 MCP
此功能由存储库提供,而不是互联网端点。先决条件:Node.js、pnpm安装在存储库中,并安装了Google Chrome。从存储库运行服务器,并使用明确允许的目录。不要从 Web 搜索结果推断私有文件系统路径。
node scripts/watermark-mcp.mjs --root /absolute/authorized/photo-folder| 工具 | 输入和结果 |
|---|---|
| validate_recipe | {recipe} → {errors:string[]}。不读取图像。 |
| inspect_images | {files:string[]} → {images:[{id,name,width,height,metadata,metadataWarning}],failures:[{id,name,index,stage,message}]}. |
| preview_watermark | {files,recipe,output?,logos?} → {files:[{path,width,height}],failures,cancelled}。仅写入第一张图像,最长边缘≤1400。 |
| batch_watermark | {files,recipe,output?,logos?} → {files:[{path,width,height}],failures,cancelled}。写入单个图像,而不是 ZIP。 |
“files”中的输入路径在“--root”内解析。 “logos”映射将资产 ID 链接到同一根中的路径。默认的“output”是根目录中的“watermark-output”;绝对路径也必须保留在该根目录内。符号链接转义被拒绝。通过选择新的输出文件名来保留现有文件。 预览和批量工具的输入契约均要求 recipe;inspect_images 只接受 files。坏图记录在 failures 中,有效图片继续处理。失败的 index 是原始 files 数组中从 0 开始的索引,stage 为 inspect 或 render。预览只处理 files[0],不会替换为其他图片。 无效请求返回“isError”并带有文本错误消息;个别处理错误仍保留在“failures”中。调用是请求/响应,没有中止工具。
MCP 返回在 content[0].text 内部序列化的 JSON,而不是 structuredContent。检查和验证是只读的;预览和批量写入副本。没有工具上传照片。在使用这些工具之前,客户端必须显式配置此本地 stdio 命令。