npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@miconvert/image-watermark

v1.0.1

Published

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.

Downloads

27

Readme

@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