ลายน้ำภาพถ่ายฟรี · รูปภาพของคุณยังคงอยู่ในอุปกรณ์ของคุณ

เครื่องมือถ่ายภาพท้องถิ่นสำหรับนักพัฒนาและผู้ช่วย

ชุดลายน้ำ ป้ายชื่อไฟล์ และการประทับวันที่ฟรี ค้นพบความสามารถ จากนั้นประมวลผลรูปภาพที่เลือกไว้อย่างชัดเจนบนอุปกรณ์

อ่านเป็นมาร์กดาวน์ · OpenAPI 3.1 · สคีสูตร

เลือกพื้นผิวการดำเนินการ

การค้นพบ 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 เป็นเวอร์ชันสัญญา บุ๊กมาร์กเส้นทางตามรูปแบบบัญญัติแทนที่จะแฮช build chunks การเข้าถึงเบราว์เซอร์แบบข้ามต้นทางไม่ได้ถูกสัญญาไว้ ใช้การนำเข้า SDK ที่มีต้นกำเนิดเดียวกัน

curl https://watermark.noxxxx.com/api/v1/capabilities.json
curl https://watermark.noxxxx.com/api/v1/recipes/filename.json

เบราว์เซอร์ SDK

นำเข้า /sdk/watermark.js จากที่มาของไซต์นี้ นี่คือ URL รายการ 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)ข้อผิดพลาดของสูตร → สตริง[]; ว่างเปล่าหมายถึงการกำหนดค่าถูกต้อง การตรวจสอบความหมายยังตรวจสอบ 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>, ดัชนี:หมายเลข, maxDimension:number, แคนวาส: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 สำหรับการตรวจสอบความหมาย รหัสเลเยอร์ต้องไม่ซ้ำกัน ครอบตัด 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 ใช้วันที่ที่ให้มาโดยตรง วันที่ที่กำหนดเองไม่ได้รับการรับรองการประทับเวลา วันที่ที่ไม่ถูกต้องอาจทำให้ป้ายกำกับว่างเปล่าหรือมีข้อผิดพลาดตามนโยบายนี้

สูตรอาหารประกอบด้วยการตั้งค่า ไม่ใช่ไบต์ของโลโก้หรือแบบอักษรที่กำหนดเอง จัดหาโลโก้ผ่าน options.assets ที่คีย์โดย layer.assetId และปิดบิตแมปโลโก้ที่ถอดรหัสหลังการใช้งาน ต้องโหลดแบบอักษรที่กำหนดเองลงใน document.fonts ภายใต้ตระกูล LocalFont ทรัพยากรที่หายไปล้มเหลวอย่างชัดเจน

SDK ส่งหาสูตรที่ไม่ถูกต้องก่อนดำเนินการแบบแบตช์ ข้อผิดพลาดในการถอดรหัส การเรนเดอร์ ข้อมูลเมตา หรือการเข้ารหัสต่อภาพปรากฏใน failures ในขณะที่ entries ที่สำเร็จยังคงอยู่ ข้อผิดพลาดในปัจจุบันประกอบด้วยข้อความภาษาจีนที่มนุษย์สามารถอ่านได้ ผู้บริโภคไม่ควรแตกแยกจากข้อความของพวกเขา มีการตรวจสอบการยกเลิกระหว่างเอาต์พุต การเรนเดอร์ปัจจุบันจะไม่ถูกขัดจังหวะ ด้วย onResult นั้น entries จะถูกส่งไปยังการโทรกลับ และจะไม่ถูกเก็บไว้ในอาร์เรย์ entries ที่ส่งคืน

ข้อจำกัดและความเป็นส่วนตัว

ไม่มีโควต้าการนับรูปภาพ, บัญชี, คีย์ API, การสมัครสมาชิก หรือการเพิ่มแบรนด์ไซต์ แต่ละอินพุตจำกัดอยู่ที่ 150 MiB และ 120 ล้านพิกเซล เอาต์พุต 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 รันเซิร์ฟเวอร์จากพื้นที่เก็บข้อมูล โดยมีไดเร็กทอรีที่อนุญาตอย่างชัดเจน อย่าอนุมานเส้นทางระบบไฟล์ส่วนตัวจากผลการค้นหาเว็บ

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 เชื่อมโยงรหัสสินทรัพย์กับเส้นทางภายในรูทเดียวกัน ค่าเริ่มต้น output คือ watermark-output ภายในรูท เส้นทางที่แน่นอนจะต้องอยู่ภายในรูทนี้ด้วย การหลีกลิงก์สัญลักษณ์จะถูกปฏิเสธ ไฟล์ที่มีอยู่จะถูกเก็บรักษาไว้โดยการเลือกชื่อไฟล์เอาต์พุตใหม่ สคีมาแสดงตัวอย่างและประมวลผลชุดกำหนดให้มี recipe ส่วน inspect_images รับเฉพาะ files ภาพที่เสียจะอยู่ใน failures และภาพที่ใช้ได้จะประมวลผลต่อ index เริ่มจาก 0 ในอาร์เรย์ files เดิม และ stage เป็น inspect หรือ render ตัวอย่างจะประมวลผลเฉพาะ files[0] โดยไม่แทนด้วยภาพอื่น คำขอที่ไม่ถูกต้องส่งคืน isError พร้อมข้อความ ข้อผิดพลาดในการประมวลผลแต่ละรายการยังคงอยู่ใน failures การโทรเป็นการร้องขอ/ตอบกลับ และไม่มีเครื่องมือในการยกเลิก

MCP ส่งคืน JSON ที่ทำให้เป็นอนุกรมภายใน content[0].text ไม่ใช่ structuredContent การตรวจสอบและตรวจสอบเป็นแบบอ่านอย่างเดียว ดูตัวอย่างและเขียนสำเนาเป็นชุด ไม่มีเครื่องมืออัพโหลดรูปภาพ ไคลเอ็นต์ต้องกำหนดค่าคำสั่ง stdio ในเครื่องนี้อย่างชัดเจนก่อนที่จะใช้เครื่องมือ