사진 워터마크무료 · 귀하의 사진은 귀하의 장치에 남아 있습니다

개발자 및 보조자를 위한 로컬 사진 도구

무료 배치 워터마크, 파일 이름 라벨 및 날짜 스탬프. 기능을 살펴보고 장치에서 명시적으로 선택한 사진을 처리하세요.

마크다운으로 읽기 · 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를 가져옵니다. 이는 안정적인 ESM 항목 URL입니다. 구현 청크는 변경될 수 있습니다. 다음 예제에서는 여러 파일 입력을 예상하고 사용자가 로컬 파일을 선택한 후에 실행됩니다. 성공적인 복사본의 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>, 인덱스:번호, maxDimension:번호, 캔버스: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; 결합된 출력이 450MiB를 초과하면 거부됩니다.
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 도우미; 서명은 저장소 packages/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 키, 구독 또는 추가된 사이트 브랜딩이 없습니다. 각 입력은 150MiB 및 1억 2천만 픽셀로 제한됩니다. ZIP 출력은 450MiB로 제한됩니다. 최대 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' 맵은 자산 ID를 동일한 루트 내의 경로에 연결합니다. 기본 output은 루트 내부의 watermark-output입니다. 절대 경로도 이 루트 내에 있어야 합니다. 기호 링크 이스케이프는 거부됩니다. 새 출력 파일 이름을 선택하면 기존 파일이 보존됩니다. 미리보기와 일괄 입력 스키마는 recipe를 필수로 요구하며 inspect_images는 files만 받습니다. 잘못된 이미지는 failures에 기록하고 유효한 이미지는 계속 처리합니다. index는 원본 files 배열의 0부터 시작하는 위치이며 stage는 inspect 또는 render입니다. 미리보기는 files[0]만 처리하며 다른 파일로 대체하지 않습니다. 잘못된 요청은 문자 메시지와 함께 'isError'를 반환합니다. 개별 처리 오류는 failures에 남아있습니다. 호출은 요청/응답이며 중단 도구는 없습니다.

MCP는 structuredContent가 아니라 content[0].text 내부에 직렬화된 JSON를 반환합니다. 검사 및 유효성 검사는 읽기 전용입니다. 미리보기 및 일괄 쓰기 사본. 어떤 도구도 사진을 업로드하지 않습니다. 클라이언트는 도구를 사용하기 전에 이 로컬 stdio 명령을 명시적으로 구성해야 합니다.