علامة مائية للصورمجاني · تبقى صورك على جهازك

أدوات الصور المحلية للمطورين والمساعدين

علامات مائية دفعة واحدة، وتسميات أسماء الملفات، وطوابع التاريخ. اكتشف الإمكانيات، ثم قم بمعالجة الصور المحددة بشكل صريح على الجهاز.

قراءة كما تخفيض السعر · 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 باعتباره إصدار العقد؛ قم بوضع إشارة مرجعية على المسارات الأساسية بدلاً من قطع البناء المجزأة. لا يتم الوعد بالوصول إلى المتصفح عبر الأصل؛ استخدم واردات 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)وصفة → أخطاء السلسلة []؛ فارغ يعني أن التكوين صالح. يتحقق التحقق الدلالي أيضًا من المعرفات الفريدة وحدود الاقتصاص.
inspectImage(file)File → Promise<Record> بالمعرف والاسم والملف والعرض والارتفاع وعنوان 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 ميجابايت.
decodeImage(blob)→ Promise<ImageBitmap>; إغلاق () عند الانتهاء. يستخدم 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 + width وy + height داخل الصورة. تستخدم الأحجام والهوامش والحدود والتذييلات نسبًا مئوية من الحافة القصيرة للصورة التي تم قصها وتدويرها. الإخراج 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 ميجابايت و120 مليون بكسل؛ يقتصر إخراج ZIP على 450 ميجابايت. الحد الأقصى 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 المحلي هذا بشكل صريح قبل استخدام الأدوات.