@miconvert/image-watermark

Add text or logo watermark to images in the browser. Client-side, fast, beautiful — no server needed. Supports tiled patterns, 9-point positioning, responsive scaling, and full opacity/rotation control.


Keywords
watermark, image watermark, add text to image, add logo to image, canvas watermark, client-side watermark, browser image processing, copyright protection, photo branding, e-commerce image tool, tiled watermark, image copyright, stock photo watermark, miconvert
License
MIT
Install
npm install @miconvert/image-watermark@1.0.2

Documentation

@miconvert/image-watermark

Add text or logo watermark to images right in the browser. Fast, beautiful, zero server dependency.

npm license size

✨ Features

  • Text Watermark — Custom font, size, color, stroke outline & drop shadow
  • Image/Logo Watermark — Supports URL, File, Blob, or HTMLImageElement
  • 9-Point Positioningtop-left, top-center, top-right, center-left, center, center-right, bottom-left, bottom-center, bottom-right
  • Tiled Pattern Mode — Repeat watermark across entire image (anti-crop protection, like Shutterstock)
  • Responsive Scaling — Logo/text auto-scales based on image resolution (no more tiny watermarks on 4K images)
  • Rotation & Opacity — Full control over angle and transparency
  • 🌍 Multilingual Font Auto-Loading — Auto-detects script (CJK, Arabic, Thai, Vietnamese, Cyrillic, Devanagari...) and loads the correct Google Noto font. No more □□□ tofu boxes!
  • 100% Client-Side — Uses HTML5 Canvas, no server required
  • TypeScript — Full type definitions included

📦 Installation

npm install @miconvert/image-watermark

🚀 Quick Start

Text Watermark

import { addWatermark } from '@miconvert/image-watermark';

const watermarked = await addWatermark(imageFile, {
  type: 'text',
  text: '© Miconvert Property',
  position: 'bottom-right',
  fontSize: 48,
  color: 'rgba(255, 255, 255, 0.5)',
  strokeColor: 'black',
  strokeWidth: 2,
  padding: 20,
});

// Display result
const url = URL.createObjectURL(watermarked);
document.getElementById('preview').src = url;

Logo Watermark

// Logo auto-scales to 15% of image width
const watermarked = await addWatermark(imageFile, {
  type: 'image',
  source: './logo.png',       // URL string
  // imageElement: logoBlob,  // or File/Blob/HTMLImageElement
  position: 'bottom-right',
  width: 0.15,                // 15% of image width
  opacity: 0.7,
  padding: 20,
});

Tiled Pattern (Anti-Crop Protection)

const watermarked = await addWatermark(imageFile, {
  type: 'text',
  text: 'Bản quyền thuộc Miconvert',
  mode: 'tiled',
  opacity: 0.3,
  rotate: -45,
  fontSize: 36,
  color: 'rgba(255, 255, 255, 0.4)',
});

📖 API Reference

addWatermark(file, options): Promise<Blob>

Parameter Type Description
file File | Blob Source image
options WatermarkOptions Configuration object

Common Options

Option Type Default Description
type 'text' | 'image' Required. Watermark type
position WatermarkPosition 'bottom-right' Anchor position (9 presets)
mode 'single' | 'tiled' 'single' Single stamp or tiled pattern
opacity number 1.0 Transparency (0.0–1.0)
rotate number 0 Rotation in degrees
padding number 20 Distance from image edge (px)
offsetX number 0 Extra horizontal offset (px)
offsetY number 0 Extra vertical offset (px)
scale number Responsive scale factor
tileSpacingX number 100 Horizontal tile gap (px)
tileSpacingY number 80 Vertical tile gap (px)

Text-Specific Options

Option Type Default Description
text string Required. Text content
fontFamily string 'Arial, Helvetica, sans-serif' CSS font family
fontSize number 48 Font size in pixels
fontWeight string 'bold' 'normal', 'bold', etc.
fontStyle string 'normal' 'normal', 'italic'
color string 'rgba(255,255,255,0.5)' Fill color (any CSS color)
strokeColor string Outline color
strokeWidth number 2 Outline width (px)
shadowColor string 'rgba(0,0,0,0.5)' Drop shadow color
shadowBlur number 4 Shadow blur radius

Image-Specific Options

Option Type Default Description
source string Logo URL
imageElement File | Blob | HTMLImageElement Logo as File/Blob/Element
width number 0.15 Logo width as fraction of image width (0.0–1.0)

🎯 Position Map

┌─────────────┬─────────────┬─────────────┐
│  top-left   │ top-center  │  top-right  │
├─────────────┼─────────────┼─────────────┤
│ center-left │   center    │center-right │
├─────────────┼─────────────┼─────────────┤
│ bottom-left │bottom-center│bottom-right │
└─────────────┴─────────────┴─────────────┘

🌍 Multilingual Font Support

Text watermarks automatically detect the language/script of your text and load the correct Google Noto font via the FontFace API. No manual font configuration needed!

Script Languages Auto-loaded Font
CJK (Simplified Chinese) Chinese Noto Sans SC
Japanese Japanese Noto Sans JP
Korean Korean Noto Sans KR
Arabic Arabic, Persian, Urdu Noto Sans Arabic
Devanagari Hindi, Sanskrit, Marathi Noto Sans Devanagari
Bengali Bengali, Assamese Noto Sans Bengali
Thai Thai Noto Sans Thai
Vietnamese Vietnamese Noto Sans
Cyrillic Russian, Ukrainian Noto Sans
Hebrew Hebrew Noto Sans Hebrew
Tamil Tamil Noto Sans Tamil
Latin English, European Noto Sans

Custom Font Loading

import { loadCustomFont, addWatermark } from '@miconvert/image-watermark';

// Load a custom font from URL
await loadCustomFont('MyBrand', 'https://example.com/fonts/mybrand.woff2');

const result = await addWatermark(imageFile, {
  type: 'text',
  text: 'My Brand™',
  fontFamily: 'MyBrand',
  // ...other options
});

⚠️ Important Notes

  • EXIF metadata is lost — Canvas processing strips EXIF data (GPS, camera info, orientation). Modern browsers auto-apply EXIF orientation before drawing, so images will look correct, but the metadata is not preserved in the output.
  • iOS Safari limit — Images larger than ~16.7 megapixels are automatically downscaled to prevent Safari crashes. A console warning is logged when this happens.
  • SSR / Node.js — This library requires a browser environment (DOM + Canvas). In Next.js/Nuxt, use dynamic import() or check typeof window !== 'undefined' before importing.
  • Multiline text — Use \n in your text string for multi-line watermarks. Example: text: '© Company\nAll Rights Reserved'
  • Animated GIF — Only the first frame is watermarked. Canvas API does not support multi-frame GIF rendering.
  • AVIF output — When using outputType: 'image/avif', color quality depends on your browser's AVIF encoder. Chrome 121+ and Safari 17+ produce good results.

🌐 Browser Support

Works in all modern browsers that support HTMLCanvasElement.toBlob() and FontFace API: Chrome 50+, Firefox 19+, Safari 11+, Edge 79+

🤝 Support

For bug reports and feature requests, please visit miconvert.com/en/contact.

📄 License

MIT © Miconvert