# 🖼️ Images Watermark

[![npm version](https://badge.fury.io/js/images-watermark.svg)](https://badge.fury.io/js/images-watermark)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Downloads](https://img.shields.io/npm/dm/images-watermark.svg)](https://www.npmjs.com/package/images-watermark)

> A powerful, fast, and user-friendly Node.js library for adding professional watermarks to images. Protect your content with text watermarks, logo overlays, or both!

📖 **[📚 Full Documentation](https://images-watermark-documentation.vercel.app/)** - Complete guides, API reference, and examples

## ✨ Features

- 🎯 **Text Watermarks** - Add custom text with full styling control
- 🖼️ **Image Watermarks** - Overlay logos or images as watermarks  
- 🔄 **Combined Watermarks** - Use both text and image watermarks simultaneously
- ⚡ **High Performance** - Built with Sharp for lightning-fast processing
- 🎨 **Customizable** - Control position, size, opacity, colors, and fonts
- 🔒 **Security** - Referrer-based access control for protected content
- 💾 **Intelligent Caching** - Automatic caching for improved performance
- 📱 **Multiple Formats** - Support for PNG, JPEG, WebP, and more
- 🚀 **Batch Processing** - Process multiple images at once
- 🎛️ **Flexible Positioning** - 9 different watermark positions
- 📚 **Comprehensive Documentation** - Full JSDoc comments and examples

## 🚀 Quick Start

### Installation

```bash
npm install images-watermark
```

### Basic Usage

```javascript
const Watermark = require('images-watermark');

// Single image watermark
const watermarkedImage = await Watermark.singleImageWatermark({
    imagePath: './path/to/image.jpg',
    textWatermark: 'My Brand',
    allowedReferrers: ['https://mywebsite.com'],
    headers: { referer: 'https://mywebsite.com' }
});

// Multiple images watermark
const watermarkedImages = await Watermark.multiImageWatermark({
    imagePaths: ['./image1.jpg', './image2.jpg'],
    watermarkPath: './logo.png',
    allowedReferrers: ['https://mywebsite.com'],
    headers: { referer: 'https://mywebsite.com' }
});
```

## 📖 API Reference

### `Watermark.singleImageWatermark(options)`

Add watermark to a single image.

#### Parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `imagePath` | `string` | ✅ | - | Path to the source image |
| `allowedReferrers` | `string[]` | ✅ | - | Array of allowed referrer domains |
| `headers` | `object` | ✅ | - | Request headers for access control |
| `watermarkPath` | `string` | ❌ | - | Path to watermark image (logo) |
| `textWatermark` | `string` | ❌ | - | Text to use as watermark |
| `appName` | `string` | ❌ | - | App name (alternative to textWatermark) |
| `textColor` | `string` | ❌ | `'black'` | Text color |
| `opacity` | `string` | ❌ | `'0.3'` | Text opacity (0.0-1.0) |
| `fontWeight` | `string` | ❌ | `'800'` | Font weight |
| `textLineSpacing` | `string` | ❌ | `'5'` | Line spacing multiplier |
| `fontFamily` | `string` | ❌ | `'Inter, Arial, sans-serif'` | Font family |

#### Returns
- `Promise<Buffer>` - Watermarked image buffer
- `Promise<string>` - Original image path (if access denied)

### `Watermark.multiImageWatermark(options)`

Add watermark to multiple images in parallel.

#### Parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `imagePaths` | `string[]` | ✅ | - | Array of image paths |
| `allowedReferrers` | `string[]` | ✅ | - | Array of allowed referrer domains |
| `headers` | `object` | ✅ | - | Request headers for access control |
| `watermarkPath` | `string` | ❌ | - | Path to watermark image (logo) |
| `textWatermark` | `string` | ❌ | - | Text to use as watermark |
| `appName` | `string` | ❌ | - | App name (alternative to textWatermark) |
| `textColor` | `string` | ❌ | `'black'` | Text color |
| `opacity` | `string` | ❌ | `'0.3'` | Text opacity (0.0-1.0) |
| `fontWeight` | `string` | ❌ | `'800'` | Font weight |
| `textLineSpacing` | `string` | ❌ | `'5'` | Line spacing multiplier |
| `fontFamily` | `string` | ❌ | `'Inter, Arial, sans-serif'` | Font family |

#### Returns
- `Promise<Buffer[]>` - Array of watermarked image buffers
- `Promise<string[]>` - Array of original image paths (if access denied)

### Utility Methods

#### `Watermark.clearCache()`
Clear the internal watermark cache.

#### `Watermark.getCacheStats()`
Get cache statistics (hits, misses, keys, etc.).

## 🎯 Examples

### 1. Text Watermark Only

```javascript
const Watermark = require('images-watermark');

const watermarkedImage = await Watermark.singleImageWatermark({
    imagePath: './photos/landscape.jpg',
    textWatermark: '© 2024 My Company',
    textColor: '#FF0000',
    opacity: '0.5',
    fontWeight: 'bold',
    allowedReferrers: ['https://mywebsite.com'],
    headers: { 
        referer: 'https://mywebsite.com',
        'user-agent': 'Mozilla/5.0...'
    }
});
```

### 2. Image Watermark Only

```javascript
const Watermark = require('images-watermark');

const watermarkedImage = await Watermark.singleImageWatermark({
    imagePath: './photos/portrait.jpg',
    watermarkPath: './assets/logo.png',
    allowedReferrers: ['https://mywebsite.com'],
    headers: { 
        referer: 'https://mywebsite.com',
        'user-agent': 'Mozilla/5.0...'
    }
});
```

### 3. Combined Text and Image Watermark

```javascript
const Watermark = require('images-watermark');

const watermarkedImage = await Watermark.singleImageWatermark({
    imagePath: './photos/product.jpg',
    watermarkPath: './assets/brand-logo.png',
    textWatermark: 'PROTECTED CONTENT',
    textColor: '#FFFFFF',
    opacity: '0.7',
    fontWeight: '900',
    fontFamily: 'Arial, sans-serif',
    allowedReferrers: ['https://mywebsite.com'],
    headers: { 
        referer: 'https://mywebsite.com',
        'user-agent': 'Mozilla/5.0...'
    }
});
```

### 4. Batch Processing

```javascript
const Watermark = require('images-watermark');

const imagePaths = [
    './photos/image1.jpg',
    './photos/image2.jpg',
    './photos/image3.jpg'
];

const watermarkedImages = await Watermark.multiImageWatermark({
    imagePaths,
    appName: 'My Brand',
    textColor: '#000000',
    opacity: '0.3',
    allowedReferrers: ['https://mywebsite.com'],
    headers: { 
        referer: 'https://mywebsite.com',
        'user-agent': 'Mozilla/5.0...'
    }
});
```

### 5. Express.js Integration

```javascript
const express = require('express');
const Watermark = require('images-watermark');
const path = require('path');

const app = express();

app.get('/watermark/:imageName', async (req, res) => {
    try {
        const imagePath = path.join(__dirname, 'images', req.params.imageName);
        
        const watermarkedImage = await Watermark.singleImageWatermark({
            imagePath,
            textWatermark: '© 2024 My Website',
            allowedReferrers: ['https://mywebsite.com'],
            headers: req.headers
        });

        res.setHeader('Content-Type', 'image/png');
        res.send(watermarkedImage);
    } catch (error) {
        console.error('Watermark error:', error);
        res.status(500).send('Error processing image');
    }
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});
```

### 6. Cache Management

```javascript
const Watermark = require('images-watermark');

// Get cache statistics
const stats = Watermark.getCacheStats();
console.log('Cache hits:', stats.hits);
console.log('Cache misses:', stats.misses);

// Clear cache if needed
Watermark.clearCache();
```

## 🔒 Security & Access Control

The library uses referrer-based access control to protect your images:

- **Allowed Referrers**: Specify domains that can access images without watermarks
- **Headers Validation**: Uses request headers to determine access permissions
- **Cookie Check**: Validates if user has proper authentication
- **User-Agent Filtering**: Prevents automated access from certain user agents

### Access Control Logic

```javascript
// Access is granted if:
// 1. User has valid cookies
// 2. User-Agent is not 'undici' (prevents automated access)
// 3. Referrer is NOT in allowed list (forces watermark for external access)
const isDirectAccess = headers['user-agent'] !== 'undici' && 
                      !isValidReferrer && 
                      headers.cookie;
```

## 🎨 Customization Options

### Text Watermark Styling

- **Color**: Any valid CSS color (`#FF0000`, `red`, `rgb(255,0,0)`)
- **Opacity**: 0.0 to 1.0 (transparent to opaque)
- **Font Weight**: CSS font-weight values (`normal`, `bold`, `100-900`)
- **Font Family**: Any installed font family
- **Line Spacing**: Multiplier for line spacing

### Watermark Positioning

- **Text Watermarks**: Centered on the image
- **Image Watermarks**: Southeast corner (bottom-right)
- **Combined**: Text centered, image in southeast corner

## ⚡ Performance Features

- **Intelligent Caching**: SVG watermarks are cached for 24 hours
- **Parallel Processing**: Multiple images processed simultaneously
- **Memory Efficient**: Uses Sharp for optimized image processing
- **Async Operations**: Non-blocking image processing

## 🛠️ Requirements

- Node.js >= 20.0.0
- Sharp (automatically installed)
- Node-cache (automatically installed)

## 📝 License

MIT License - see [LICENSE](LICENSE) file for details.

## 🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## 🔗 Author Details

[![portfolio](https://img.shields.io/badge/my_portfolio-000?style=for-the-badge&logo=ko-fi&logoColor=white)](https://tirth-gaudani.github.io/portfolio/)
[![linkedin](https://img.shields.io/badge/linkedin-0A66C2?style=for-the-badge&logo=linkedin&logoColor=white)](https://in.linkedin.com/in/tirthgaudani)

⭐ **Star this repository if you find it helpful!**