Watermark.Net
Other languages
Watermark.Net is an open-source .NET library for programmatically adding text and image watermarks to images. Built on SixLabors.ImageSharp, it provides a clean, extensible API for all your watermarking needs — from a single file to entire directory batches. Whether you need to protect copyrights, brand your media, or mark drafts, Watermark.Net makes image watermarking in C# simple and efficient.
Features
- 🖼️ Multi-format support — JPEG, PNG, BMP, GIF
- ✏️ Text watermarks — custom fonts, colors, sizes, rotation, and 9-zone positioning
- 🖌️ Image watermarks — PNG transparency, scaling, and opacity control (0.0–1.0)
- 🧱 Pave (tiling) mode — repeat the watermark across the entire image surface
- 🧩 9 preset positions — TopLeft, TopCenter, TopRight, CenterLeft, Center, CenterRight, BottomLeft, BottomCenter, BottomRight
- 🎨 Custom styling — background color, opacity, rotation angle, and padding
- 📁 Batch processing — watermark all images in a directory with a single method call
- 🔌 Dependency injection ready —
IFileManagerabstraction for testing and custom file I/O - 🔄 Backward compatible — legacy
WatermarkerAPI still supported (marked as[Obsolete])
Installation
Install the NuGet package:
dotnet add package Watermark.Net
Requires .NET 8 or later.
Quick Start
Add a Text Watermark
using SixLabors.Fonts;
using SixLabors.ImageSharp;
using Watermark.Net.src.WatermarkNet.Core;
using Watermark.Net.src.WatermarkNet.Enums;
using Watermark.Net.src.WatermarkNet.Models.Definitions;
var pipeline = new WatermarkPipeline(new FileManager(), new ImageRenderer());
var watermark = new TextWatermark
{
Text = "WATERMARK",
Font = SystemFonts.CreateFont("Arial", 36),
Layout = { Position = ImagePosition.BottomRight, Scale = 0.5f },
Style = { Color = Color.White }
};
ResultImage result = pipeline.ProcessImage("input.jpg", "output", watermark);
Console.WriteLine($"Saved to: {result.Path}");
Add an Image Watermark
using SixLabors.ImageSharp;
using Watermark.Net.src.WatermarkNet.Core;
using Watermark.Net.src.WatermarkNet.Enums;
using Watermark.Net.src.WatermarkNet.Models.Definitions;
var pipeline = new WatermarkPipeline(new FileManager(), new ImageRenderer());
var watermark = new ImageWatermark
{
ImagePath = "logo.png",
Layout = { Scale = 0.3f, Position = ImagePosition.Center },
Style = { Opacity = 0.7f, Pave = true }
};
List<ResultImage> results = pipeline.ProcessDirectory("images", "output", watermark);
Console.WriteLine($"Processed {results.Count} images");
Architecture
Watermark.Net follows a clean pipeline architecture with clear separation of concerns:
┌──────────────────────────────────────┐
│ WatermarkPipeline │ ← Orchestrator layer
│ (coordinates I/O and rendering) │
├──────────────────────────────────────┤
│ IFileManager / FileManager │ ← File I/O abstraction
│ (loading, saving, enumeration) │
├──────────────────────────────────────┤
│ ImageRenderer │ ← Pure rendering engine
│ (image processing, no I/O) │
└──────────────────────────────────────┘
WatermarkPipeline— the main entry point that orchestrates file operations and rendering.IFileManager/FileManager— abstracts all file system I/O. Swap this for custom storage or unit testing.ImageRenderer— a pure image processing engine. Accepts in-memoryImageobjects, returns processedImageinstances. No file I/O dependency.
Configuration Reference
WatermarkLayout
Controls where and how big the watermark appears.
| Property | Type | Default | Description |
|---|---|---|---|
Position |
ImagePosition |
TopLeft |
One of 9 predefined positions |
Scale |
float |
0 |
Scale factor relative to image size |
RotateAngle |
int |
0 |
Rotation angle in degrees |
Padding |
float |
0 |
Padding space around the watermark (px) |
WatermarkStyle
Controls how the watermark looks.
| Property | Type | Default | Description |
|---|---|---|---|
Opacity |
float |
0 |
Transparency level — 0.0 (transparent) to 1.0 (opaque) |
Pave |
bool |
false |
When true, tiles the watermark across the image |
Color |
Color |
default |
Background or text color |
ImagePosition
All 9 available positions:
| Name | Description |
|---|---|
TopLeft |
Top-left corner |
TopCenter |
Top-center |
TopRight |
Top-right corner |
CenterLeft |
Middle-left |
Center |
Exact center |
CenterRight |
Middle-right |
BottomLeft |
Bottom-left corner |
BottomCenter |
Bottom-center |
BottomRight |
Bottom-right corner |
Model types
| Type | Description |
|---|---|
TextWatermark |
Text watermark configuration (Text, Font) |
ImageWatermark |
Image watermark configuration (ImagePath) |
ResultImage |
Output result (.Image + .Path) |
IWatermarkDefinition |
Base interface for custom watermark definitions |
Advanced Usage
Pave (Tiling) Mode
Tile the watermark across every position on the image:
var watermark = new TextWatermark
{
Text = "DRAFT",
Font = SystemFonts.CreateFont("Arial", 36),
Style = { Color = Color.Red, Pave = true },
Layout = { Scale = 0.3f }
};
Opacity Control
Create a subtle, semi-transparent watermark:
var watermark = new ImageWatermark
{
ImagePath = "logo.png",
Style = { Opacity = 0.3f }, // 30% opacity
Layout = { Position = ImagePosition.Center, Scale = 0.5f }
};
Custom Positioning & Rotation
Place a rotated watermark with padding:
var watermark = new TextWatermark
{
Text = "CONFIDENTIAL",
Font = SystemFonts.CreateFont("Arial", 24),
Layout =
{
Position = ImagePosition.TopLeft,
RotateAngle = 45,
Padding = 20
}
};
Dependency Injection
Integrate with your DI container for better testability:
services.AddSingleton<IFileManager, FileManager>();
services.AddSingleton<ImageRenderer>();
services.AddTransient<WatermarkPipeline>();
Batch Directory Processing
Process all images in a directory with a single call:
var results = pipeline.ProcessDirectory("input_photos", "watermarked", textWatermark);
foreach (var result in results)
{
Console.WriteLine($"✓ {result.Path}");
}
Roadmap
- Improved pave mode - tiling isntead if 9 fixed positions
- AI remove protection - color noise, geometric distortion, DCT, texture blend etc.
- Common architecture imorovements
Contributing
Contributions are welcome! To ensure a smooth collaboration:
- Fork the repository and create a feature branch.
- Write tests for any new functionality (see the
UnitTestproject). - Run all tests before opening a pull request — make sure they pass.
- Open a PR with a clear description of the changes.
All tests use sample images located in UnitTest/TestImages/.
License
Watermark.Net is licensed under the MIT License.