Skip to content

Instantly share code, notes, and snippets.

@GroupDocsGists
Created April 16, 2026 15:11
Show Gist options
  • Select an option

  • Save GroupDocsGists/976672c04aa737802c88301371c22fd3 to your computer and use it in GitHub Desktop.

Select an option

Save GroupDocsGists/976672c04aa737802c88301371c22fd3 to your computer and use it in GitHub Desktop.
Apply text or image watermarks across multiple documents and replace outdated logos with GroupDocs.Watermark for .NET

Batch Watermarking Pipeline for .NET 🚀

Apply watermarks to a whole folder of documents in a single pass and replace old logos when needed. The examples show how to:

  • Add a tiled text watermark to every supported file
  • Add a tiled image (logo) watermark to every supported file
  • Apply a text watermark only when it does not already exist (idempotent processing)
  • Find and replace an outdated logo across a folder of documents

Prerequisites 📦

  • .NET 6+ installed
  • GroupDocs.Watermark for .NET package
  • A temporary or permanent GroupDocs license (see the product documentation for a trial license)
  • Input files in formats supported by GroupDocs.Watermark (DOCX, PDF, XLSX, PPTX, images, etc.)

Feature sections

1️⃣ Add a tiled text watermark

Steps

  1. Create the output folder.
  2. Iterate over each supported file.
  3. Instantiate Watermarker for the file.
  4. Build a TextWatermark with TileOptions.
  5. Add the watermark and save the result.

Code reference: ApplyBatchTextWatermark.cs

2️⃣ Add a tiled image (logo) watermark

Steps

  1. Verify the logo image exists.
  2. Create the output folder.
  3. Loop through all supported files.
  4. Instantiate Watermarker and an ImageWatermark.
  5. Configure opacity, rotation and tiling.
  6. Add the watermark and save the result.

Code reference: ApplyBatchLogoWatermark.cs

3️⃣ Apply a smart text watermark (skip if already present)

Steps

  1. Create the output folder.
  2. For each file, search for the watermark text using TextSearchCriteria.
  3. If a watermark is found, skip the file; otherwise, add the new watermark.
  4. Save the processed file.

Code reference: ApplySmartBatchWatermark.cs

4️⃣ Replace an outdated logo with a new one

Steps

  1. Ensure both old and new logo files exist.
  2. Create the output folder.
  3. Configure WatermarkerSettings to enable searchable PDF objects.
  4. For each file, search for the old logo using DCT‑hash and color‑histogram criteria.
  5. Replace the image data of each found watermark with the new logo bytes.
  6. Save the updated document.

Code reference: ReplaceLogoAcrossFolder.cs

How to use

  1. Install the GroupDocs.Watermark NuGet package.
  2. Add the desired code file to your project.
  3. Provide the input folder path, output folder path, watermark text or logo paths as required.
  4. Run the example – processed files will appear in the output folder.

📎 Related Articles


For detailed API reference and additional use‑cases, see the official documentation at https://docs.groupdocs.com/watermark/net/.

if (!File.Exists(logoPath))
{
return;
}
Directory.CreateDirectory(outputFolder);
int processed = 0, failed = 0;
foreach (var filePath in files)
{
try
{
using (var watermarker = new Watermarker(filePath))
{
using (var watermark = new ImageWatermark(logoPath))
{
watermark.Opacity = 0.4;
watermark.RotateAngle = -30;
watermark.TileOptions = new TileOptions
{
LineSpacing = new MeasureValue
{
MeasureType = TileMeasureType.Percent,
Value = 15
},
WatermarkSpacing = new MeasureValue
{
MeasureType = TileMeasureType.Percent,
Value = 12
}
};
watermarker.Add(watermark);
}
watermarker.Save(Path.Combine(outputFolder, Path.GetFileName(filePath)));
processed++;
}
}
catch (Exception)
{
failed++;
}
}
// Ensure the output folder exists
Directory.CreateDirectory(outputFolder);
int processed = 0, failed = 0;
foreach (var filePath in files)
{
try
{
using (var watermarker = new Watermarker(filePath))
{
var watermark = new TextWatermark(watermarkText, new Font("Arial", 19, FontStyle.Bold))
{
ForegroundColor = Color.Red,
Opacity = 0.3,
RotateAngle = -30,
TileOptions = new TileOptions
{
LineSpacing = new MeasureValue
{
MeasureType = TileMeasureType.Percent,
Value = 12
},
WatermarkSpacing = new MeasureValue
{
MeasureType = TileMeasureType.Percent,
Value = 10
}
}
};
watermarker.Add(watermark);
watermarker.Save(Path.Combine(outputFolder, Path.GetFileName(filePath)));
processed++;
}
}
catch (Exception)
{
failed++;
}
}
Directory.CreateDirectory(outputFolder);
int applied = 0, skipped = 0, failed = 0;
foreach (var filePath in files)
{
try
{
using (var watermarker = new Watermarker(filePath))
{
TextSearchCriteria criteria = new TextSearchCriteria(watermarkText, false);
PossibleWatermarkCollection existing = watermarker.Search(criteria);
if (existing.Count > 0)
{
skipped++;
continue;
}
var watermark = new TextWatermark(watermarkText, new Font("Arial", 19, FontStyle.Bold))
{
ForegroundColor = Color.Red,
Opacity = 0.3,
RotateAngle = -30,
TileOptions = new TileOptions
{
LineSpacing = new MeasureValue
{
MeasureType = TileMeasureType.Percent,
Value = 12
},
WatermarkSpacing = new MeasureValue
{
MeasureType = TileMeasureType.Percent,
Value = 10
}
}
};
watermarker.Add(watermark);
watermarker.Save(Path.Combine(outputFolder, Path.GetFileName(filePath)));
applied++;
}
}
catch
{
failed++;
}
}
if (!File.Exists(oldLogoPath) || !File.Exists(newLogoPath))
{
return;
}
Directory.CreateDirectory(outputFolder);
byte[] newLogoData = File.ReadAllBytes(newLogoPath);
int replaced = 0, notFound = 0;
var settings = new WatermarkerSettings
{
SearchableObjects = new SearchableObjects
{
PdfSearchableObjects = PdfSearchableObjects.All
}
};
foreach (var filePath in files)
{
try
{
using (var watermarker = new Watermarker(filePath, settings))
{
ImageSearchCriteria dctCriteria = new ImageDctHashSearchCriteria(oldLogoPath);
dctCriteria.MaxDifference = 0.4;
ImageSearchCriteria histCriteria = new ImageColorHistogramSearchCriteria(oldLogoPath);
histCriteria.MaxDifference = 0.5;
SearchCriteria criteria = dctCriteria.Or(histCriteria);
PossibleWatermarkCollection found = watermarker.Search(criteria);
if (found.Count == 0)
{
notFound++;
continue;
}
foreach (PossibleWatermark watermark in found)
{
try
{
watermark.ImageData = newLogoData;
}
catch
{
// Some entities may not support image replacement
}
}
watermarker.Save(Path.Combine(outputFolder, Path.GetFileName(filePath)));
replaced++;
}
}
catch
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment