# Watermark.Net [![.NET](https://github.com/Geckon01/Watermark.Net/actions/workflows/dotnet.yml/badge.svg)](https://github.com/Geckon01/Watermark.Net/actions/workflows/dotnet.yml) ![NuGet Version](https://img.shields.io/nuget/v/Watermark.Net) ![NuGet Downloads](https://img.shields.io/nuget/dt/Watermark.Net?link=https%3A%2F%2Fwww.nuget.org%2Fpackages%2FWatermark.Net%2F) ![Lecense](https://img.shields.io/badge/license-MIT-green) ![GitHub last commit](https://img.shields.io/github/last-commit/Geckon01/Watermark.Net?display_timestamp=author) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/e6340e249ad743bc99c1745aaa0a9838)](https://app.codacy.com/gh/Geckon01/Watermark.Net/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) ### Other languages - ๐Ÿ‡บ๐Ÿ‡ธ [English](docs/README.md) - ๐Ÿ‡ท๐Ÿ‡บ [ะ ัƒััะบะธะน](docs/README.ru.md) - ๐Ÿ‡จ๐Ÿ‡ณ [็ฎ€ไฝ“ไธญๆ–‡](docs/README.zh-CN.md) **Watermark.Net** is an open-source .NET library for programmatically adding text and image watermarks to images. Built on [SixLabors.ImageSharp](https://github.com/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** โ€” `IFileManager` abstraction for testing and custom file I/O - ๐Ÿ”„ **Backward compatible** โ€” legacy `Watermarker` API still supported (marked as `[Obsolete]`) --- ## Installation Install the [NuGet package](https://www.nuget.org/packages/Watermark.Net/): ```bash dotnet add package Watermark.Net ``` Requires **.NET 8** or later. --- ## Quick Start ### Add a Text Watermark ```csharp 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 ```csharp 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 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`](Watermark.Net/src/WatermarkNet.Common/WatermarkPipeline.cs)** โ€” the main entry point that orchestrates file operations and rendering. - **[`IFileManager`](Watermark.Net/src/WatermarkNet.Common/IFileManager.cs)** / **[`FileManager`](Watermark.Net/src/WatermarkNet.Common/FileManager.cs)** โ€” abstracts all file system I/O. Swap this for custom storage or unit testing. - **[`ImageRenderer`](Watermark.Net/src/WatermarkNet.Common/ImageRenderer.cs)** โ€” a pure image processing engine. Accepts in-memory `Image` objects, returns processed `Image` instances. No file I/O dependency. --- ## Configuration Reference ### [`WatermarkLayout`](Watermark.Net/src/WatermarkNet.Models/Layout/WatermarkLayout.cs) 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`](Watermark.Net/src/WatermarkNet.Models/Styling/WatermarkStyle.cs) 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`](Watermark.Net/src/WatermarkNet.Enums/ImagePosition.cs) 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`](Watermark.Net/src/WatermarkNet.Models/Definitions/TextWatermark.cs) | Text watermark configuration (`Text`, `Font`) | | [`ImageWatermark`](Watermark.Net/src/WatermarkNet.Models/Definitions/ImageWatermark.cs) | Image watermark configuration (`ImagePath`) | | [`ResultImage`](Watermark.Net/src/WatermarkNet.Models/Definitions/ResultImage.cs) | Output result (`.Image` + `.Path`) | | [`IWatermarkDefinition`](Watermark.Net/src/WatermarkNet.Models/Definitions/IWatermarkDefinition.cs) | Base interface for custom watermark definitions | --- ## Advanced Usage ### Pave (Tiling) Mode Tile the watermark across every position on the image: ```csharp 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: ```csharp 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: ```csharp 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: ```csharp services.AddSingleton(); services.AddSingleton(); services.AddTransient(); ``` ### Batch Directory Processing Process all images in a directory with a single call: ```csharp var results = pipeline.ProcessDirectory("input_photos", "watermarked", textWatermark); foreach (var result in results) { Console.WriteLine($"โœ“ {result.Path}"); } ``` --- ## Contributing Contributions are welcome! To ensure a smooth collaboration: 1. **Fork** the repository and create a feature branch. 2. **Write tests** for any new functionality (see the [`UnitTest`](UnitTest/UnitTest.cs) project). 3. **Run all tests** before opening a pull request โ€” make sure they pass. 4. **Open a PR** with a clear description of the changes. All tests use sample images located in [`UnitTest/TestImages/`](UnitTest/TestImages/). --- ## License Watermark.Net is licensed under the [MIT License](LICENSE).