# Référence du filigrane photo local API

Outils photo locaux gratuits : filigrane par lots, étiquettes de nom de fichier et tampons de date.

## Choisissez une surface d'exécution

La découverte API est publique, gratuite, en lecture seule et ne nécessite aucune clé API. Il décrit les outils et les paramètres ; il n'accepte jamais d'images. Il n’existe pas de POST/filigrane, de service de traitement cloud ou de point de terminaison MCP hébergé.

Utilisez le navigateur SDK pour les fichiers explicitement sélectionnés sur cette origine. Pour un assistant ayant accès au système de fichiers local, connectez explicitement le serveur stdio MCP du référentiel et autorisez un répertoire racine. Un modèle trouvant cette documentation n'a pas accès à un appareil ou à ses fichiers.



| Surface | Objectif |
| --- | --- |
| OBTENIR JSON / Démarquage | Découvrez les capacités, les recettes, les contraintes et les signatures d'outils locaux. |
| Navigateur ESM SDK | Décoder et restituer les fichiers localement ; nécessite Canvas, DOM, createImageBitmap et File/Blob. Il ne s'agit pas d'un Node ou d'un traitement HTTP à distance API. |
| CLI locale / stdio MCP | Automatisation locale explicitement connectée à l'aide de Google Chrome installé et des dépendances du référentiel. |


## Ressources publiques

GET et HEAD renvoient des ressources statiques. Aucune authentification, corps de requête, paramètres de requête ou données utilisateur. Les chemins de ressources inconnus renvoient 404. Traitez la version 1 comme la version du contrat ; marquez les chemins canoniques plutôt que les morceaux de construction hachés. L'accès aux navigateurs d'origine croisée n'est pas promis ; utilisez les importations SDK de même origine.

- [Catalogue de capacités](/api/v1/capabilities.json)
- [Recettes complètes par défaut et variables de texte prises en charge](/api/v1/templates.json)
- [Recette JSON Schema (2020-12)](/api/v1/recipe.schema.json)
- [Schémas d'entrée locaux MCP](/api/v1/mcp-tools.json)
- [Spécification de découverte OpenAPI 3.1](/openapi.json)
- [Répertoire de découverte facultatif](/llms.txt)

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


## Navigateur SDK

Importez /sdk/watermark.js sur l’origine de ce site. Il s'agit d'une URL d'entrée ESM stable ; les éléments de mise en œuvre peuvent changer. L'exemple suivant attend une entrée de plusieurs fichiers et s'exécute une fois que l'utilisateur a sélectionné les fichiers locaux. Il crée un ZIP de copies réussies ; les appelants doivent inspecter les failures et cancelled plutôt que de considérer l'exportation partielle comme terminée.



```
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));
}
```

| Fonction | Entrée → résultat |
| --- | --- |
| createRecipe(mode) | watermark \| filename \| date \| frame → recette v1 indépendante. |
| validateRecipe(recipe) | Recette → erreurs string[] ; vide signifie que la configuration est valide. La validation sémantique vérifie également les identifiants uniques et les limites de recadrage. |
| inspectImage(file) | File → Promise<Record> avec identifiant, nom, fichier, largeur, hauteur, URL de l'objet miniature, remplacements, métadonnées, métadonnéesAvertissement. Révoquer la vignette une fois terminé. `{id,name,file,width,height,thumbnail,overrides,metadata,metadataWarning}` |
| renderImage(record, recipe, options?) | → Promise<{blob, geometry}> ; preview:true renvoie {canvas, geometry}. options : actifs :Map<assetId,ImageBitmap\|Canvas>, index :numéro, maxDimension :numéro, canevas :Canvas. missingMetadataText?:string. `{blob,geometry} \| {canvas,geometry}` |
| processBatch(records, recipe, options?) | → Promise<{entries,failures,cancelled}>. Entrée : {name,blob,width,height,sourceId} ; panne : {id,name,longEdge,message}. options : actifs, signal : AbortSignal, onProgress({done,total,failed}), onResult(entrée). missingMetadataText?:string. `{entries:[{name,blob,width,height,sourceId}],failures:[{id,name,longEdge,message}],cancelled}` |
| packageResults(entries) | → Promise<Blob> ZIP ; rejette lorsque la sortie combinée dépasse 450 Mio. |
| decodeImage(blob) | → Promise<ImageBitmap> ; close() une fois terminé. HEIC utilise la première image décodée. |
| parseLabelCsv(text) | filename,text CSV → Map<chaîne,chaîne> ; Correspondances de noms exacts, rejet des noms en double. Réglez vous-même le record.label avant le traitement. |
| imageRecipe(recipe, record) | Fusionne record.overrides.image et record.overrides.layers[id] sans muter la recette partagée. |
| renderStudioImage / cleanLogo | Assistants Canvas de bas niveau ; voir packages de référentiel/watermark-core/src/studio.js pour les signatures. Préférez renderImage pour la sortie codée. |


## Règles et erreurs de recette

Téléchargez des recettes complètes à partir de /api/v1/recipes/watermark.json, filename.json, date.json ou frame.json. Validez d'abord JSON Schema, puis validateRecipe pour les contrôles sémantiques. Les ID de couche doivent être uniques. Le recadrage x + largeur et y + hauteur doivent rester à l'intérieur de l'image. Les tailles, marges, bordures et pieds de page utilisent des pourcentages du bord court de l’image recadrée et pivotée. La sortie longEdge:0 conserve la taille ; le redimensionnement n'est jamais mis à l'échelle. Le champ facultatif image.crop.aspectRatio définit la largeur/hauteur du contenu après rotation. Le recadrage est centré dans la sélection normalisée de chaque image, même avec des tailles différentes. Bordures et pied de page sont ajoutés ensuite. Modifier les pourcentages désactive ce rapport.

Variables de texte : {filename} exclut l'extension ; {fullname} l'inclut ; {index} utilise sequence.start et un rembourrage ; {label} utilise record.label. Les variables de la caméra sont {camera}, {lens}, {aperture}, {iso}, {shutter}, {focal}. Un CSV ne remplit pas automatiquement les enregistrements SDK.

Le préréglage de date utilise le DateTimeOriginal ou le CreateDate de chaque image. Aucune date de modification du fichier n'est substituée. La date manquante est par défaut une étiquette de date vide ; missing:error échoue avec cette image, missing:custom utilise date.custom s'il est analysable. source:custom utilise directement la date fournie. Les dates personnalisées ne sont pas des horodatages certifiés. Les dates non valides peuvent générer une étiquette vide ou une erreur conformément à cette politique.

Une recette contient des paramètres, pas des octets de logo ni des polices personnalisées. Fournissez des logos via options.assets saisis par layer.assetId et fermez les bitmaps de logo décodés après utilisation. Les polices personnalisées doivent être chargées dans document.fonts sous leur famille LocalFont. Les ressources manquantes échouent explicitement.

Le SDK recherche des recettes non valides avant l'exécution du lot. Des erreurs de décodage, de rendu, de métadonnées ou d'encodage par image apparaissent dans failures, tandis que le entries réussi reste disponible. Les erreurs contiennent actuellement des messages chinois lisibles par l'homme ; les consommateurs ne devraient pas bifurquer sur leur texte. L'annulation est vérifiée entre les sorties ; le rendu en cours n'est pas interrompu. Avec onResult, les entries sont transmis au rappel et ne sont pas conservés dans le tableau entries renvoyé.




## Limites et confidentialité

Pas de quota de nombre de photos payant, de compte, de clé API, d'abonnement ou de marque de site ajoutée. Chaque entrée est limitée à 150 Mio et 120 millions de pixels ; La sortie ZIP est limitée à 450 Mio. Maximum 30 couches, 6 tailles de sortie supplémentaires, bord long jusqu'à 32768. Les limites du navigateur Canvas, de la mémoire, du décodeur et du système de fichiers peuvent être inférieures ; diviser de gros lots.

Les sorties sont JPEG, PNG ou WebP. JPEG et WebP avec perte sont réencodés. Le mode de métadonnées par défaut est « strip ». Les modes « safe » et « all » nécessitent une sortie JPEG. Le mode « safe » exclut le GPS ; le mode « all » peut conserver les métadonnées de localisation. Les profils ICC, HDR et signatures ne sont pas conservés. Les fichiers originaux ne sont jamais modifiés.

Seules les ressources du programme sont éventuellement mises en cache pour une utilisation hors ligne dans /studio/.. Les nouvelles pages publiques nécessitent une connexion réseau pour se charger initialement. Les images utilisateur et les noms de fichiers ne sont pas envoyés au public API ni stockés dans les préréglages. Enregistrez/partagez uniquement les recettes qui ne contiennent aucun texte privé.




## Local MCP

Cette fonctionnalité est fournie par le référentiel et non par un point de terminaison Internet. Conditions préalables : installation de Node.js, pnpm dans le référentiel et installation de Google Chrome. Exécutez le serveur à partir du référentiel, avec un répertoire autorisé explicite. Ne déduisez pas un chemin de système de fichiers privé à partir des résultats de recherche sur le Web.



```
node scripts/watermark-mcp.mjs --root /absolute/authorized/photo-folder
```

| Outil | Entrée et résultat |
| --- | --- |
| validate_recipe | {recipe} → {errors:string[]}. Ne lit pas les images. |
| 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}. Écrit uniquement la première image, bord le plus long ≤1400. |
| batch_watermark | {files,recipe,output?,logos?} → {files:[{path,width,height}],failures,cancelled}. Écrit des images individuelles, pas un ZIP. |
Les chemins d'entrée dans « files » sont résolus dans « --root ». La carte « logos » relie les ID d'actifs aux chemins au sein de la même racine. Le « output » par défaut est « watermark-output » à l'intérieur de la racine ; les chemins absolus doivent également rester à l'intérieur de cette racine. Les échappements de liens symboliques sont rejetés. Les fichiers existants sont préservés en choisissant de nouveaux noms de fichiers de sortie. Les schémas de prévisualisation et de lot exigent recipe ; inspect_images accepte uniquement files. Les images invalides figurent dans failures, les autres continuent. index commence à 0 dans le tableau files initial ; stage vaut inspect ou render. La prévisualisation traite seulement files[0], sans substitution.  Les requêtes invalides renvoient « isError » avec un message texte ; les erreurs de traitement individuelles restent dans « failures ». Les appels sont des requêtes/réponses et il n’y a pas d’outil d’abandon.

MCP renvoie JSON sérialisé dans content[0].text, et non structuredContent. Inspecter et valider sont en lecture seule ; prévisualiser et écrire des copies par lots. Aucun outil ne télécharge de photos. Un client doit configurer explicitement cette commande stdio locale avant d'utiliser les outils.