De oude manier was pijnlijk

Imagine een compliance officer die de taak heeft te verifiëren dat elk contract in een gedeelde schijf het woord “CONFIDENTIAL” en het bedrijfslogo op elke pagina bevat. Het huidige proces ziet er als volgt uit:

  1. Open een bestand in een viewer.
  2. Blader door elke pagina op zoek naar de zin of afbeelding.
  3. Noteer aantekeningen in een spreadsheet.
  4. Herhaal dit voor duizenden PDF’s, Word‑bestanden en presentaties.

Een enkele gemiste watermerk kan een kostbare controle veroorzaken, en de handmatige inspanning overschrijdt gemakkelijk 8 uur per week voor een klein team. Bovendien ontsnappen roterende tekst, gesplitste woorden of logo’s opgeslagen als afbeeldingen vaak aan het menselijk oog, waardoor de organisatie blootgesteld wordt.

Er is een betere manier

GroupDocs.Watermark for .NET verwijdert elke gokstap. Zijn formaat‑agnostische engine kan meer dan 100 documenttypen lezen, tekst, afbeelding en zelfs gestylede watermerken lokaliseren, en alle relevante metadata blootleggen via een nette API. De volgende tutorial laat zien hoe een paar beknopte fragmenten de handmatige lus vervangen door een geautomatiseerde, herhaalbare workflow.

Vereisten

  • .NET 6.0 of later.
  • GroupDocs.Watermark NuGet‑pakket (dotnet add package GroupDocs.Watermark).
  • (Optioneel) een tijdelijke licentie – zie de link aan het einde van dit artikel.

De nieuwe manier: Geautomatiseerde watermerk‑audit

Hieronder lopen we vier kernbewerkingen door. Elk blok is een zelfstandige voorbeeldcode die je kunt plaatsen in een console‑app, een CI‑stap of een achtergrondservice.

Stap 1 – Scan elk watermerk

Als eerste hebben we een volledige inventaris nodig. De Search()‑methode retourneert een collectie waarbij elk item tekst (of afbeelding), locatie, rotatie, paginanummer en ruwe afbeeldingsgrootte bevat.

using (var wk = new Watermarker(filePath))
{
    var all = wk.Search();
    Console.WriteLine($"Found {all.Count} watermark(s) in " +
        $"'{Path.GetFileName(filePath)}':");
    int i = 0;
    foreach (var wm in all)
    {
        Console.WriteLine($"  #{++i}: {(wm.Text ?? "[image]")} ");
        Console.WriteLine($"     Page {wm.PageNumber}, " +
            $"Pos X={wm.X}, Y={wm.Y}, Rot={wm.RotateAngle}°");
        Console.WriteLine($"     Size {wm.Width}×{wm.Height}");
        if (wm.ImageData != null)
            Console.WriteLine($"     Image bytes {wm.ImageData.Length}");
    }
}

Belangrijk punt: De lus draait in minder dan een seconde voor een typische 50‑pagina PDF.

Stap 2 – Verifieer vereiste tekst‑watermerk

Compliance‑beleid vereist vaak een specifieke zin (bijv. “CONFIDENTIAL”). De TextSearchCriteria met SkipUnreadableCharacters verwerkt gesplitste of geroteerde tekst automatisch.

using (var wk = new Watermarker(filePath))
{
    var crit = new TextSearchCriteria(expectedPhrase);
    crit.SkipUnreadableCharacters = true;   // ignore OCR artefacts
    var hits = wk.Search(crit);
    bool ok = hits.Count > 0;
    Console.WriteLine($"  [{(ok ? "PASS" : "FAIL")}] " +
        $"'{expectedPhrase}' found {hits.Count} time(s)");
    return ok;
}

De methode retourneert true wanneer de zin ten minste één keer voorkomt, waardoor je direct een PASS/FAIL‑vlag krijgt.

Logo’s bestaan als rasterafbeeldingen, en hun uiterlijk kan enigszins variëren door compressie. ImageDctHashSearchCriteria maakt een perceptuele hash van het referentielogo en vergelijkt deze met een configureerbare tolerantie.

using (var wk = new Watermarker(filePath))
{
    var crit = new ImageDctHashSearchCriteria(logoPath);
    crit.MaxDifference = 0.9;   // tolerate moderate scaling / colour shift
    var matches = wk.Search(crit);
    bool ok = matches.Count > 0;
    Console.WriteLine($"  [{(ok ? "PASS" : "FAIL")}] " +
        $"logo instances: {matches.Count}");
    return ok;
}

Zelfs een lage‑resolutie kopie van het logo wordt herkend.

Stap 4 – Voer een volledig compliance‑rapport uit

Beleidsregels in de praktijk combineren meerdere eisen. Het eerste blok controleert vier opmaakregels — tekstaanwezigheid, lettertype, grootte en vet stijl — elk door TextSearchCriteria te combineren met TextFormattingSearchCriteria via .And():

using (var wk = new Watermarker(filePath))
{
    int passed = 0, failed = 0;

    var txtCrit = new TextSearchCriteria(expectedPhrase);
    bool hasText = wk.Search(txtCrit).Count > 0;
    Console.WriteLine($"  [{(hasText ? "PASS" : "FAIL")}] Text present");
    if (hasText) passed++; else failed++;

    var fontCrit = new TextFormattingSearchCriteria { FontName = expFont };
    bool hasFont = wk.Search(txtCrit.And(fontCrit)).Count > 0;
    Console.WriteLine($"  [{(hasFont ? "PASS" : "FAIL")}] Font {expFont}");
    if (hasFont) passed++; else failed++;

    var sizeCrit = new TextFormattingSearchCriteria { MinFontSize = minSize };
    bool hasSize = wk.Search(txtCrit.And(sizeCrit)).Count > 0;
    Console.WriteLine($"  [{(hasSize ? "PASS" : "FAIL")}] Size >= {minSize}");
    if (hasSize) passed++; else failed++;

    var boldCrit = new TextFormattingSearchCriteria { FontBold = true };
    bool hasBold = wk.Search(txtCrit.And(boldCrit)).Count > 0;
    Console.WriteLine($"  [{(hasBold ? "PASS" : "FAIL")}] Bold formatting");
    if (hasBold) passed++; else failed++;

De vijfde regel controleert paginabedekking — het watermerk moet op elke pagina verschijnen. Ten slotte aggregeert het oordeel alle resultaten:

    var perPage = wk.Search(txtCrit);
    var pages = new HashSet<int>();
    foreach (var wm in perPage)
        if (wm.PageNumber.HasValue) pages.Add(wm.PageNumber.Value);
    var allPages = wk.Search();
    int max = 0;
    foreach (var wm in allPages)
        max = Math.Max(max, wm.PageNumber ?? 0);
    bool full = max > 0 && pages.Count == max;
    Console.WriteLine($"  [{(full ? "PASS" : "FAIL")}] " +
        $"Pages covered {pages.Count}/{max}");
    if (full) passed++; else failed++;

    string verdict = failed == 0 ? "COMPLIANT" : "NON-COMPLIANT";
    Console.WriteLine($"\nResult: {verdict} " +
        $"({passed} passed, {failed} failed)");
}

Het rapport is klaar om geëxporteerd te worden als JSON, CSV of direct ingevoerd in een ticketsysteem.

Zij‑aan‑zij: Voor vs. Na

Handmatige beoordeling Geautomatiseerde audit
Tijd Uren per batch Seconden per bestand
Nauwkeurigheid Menselijke fouten Deterministische API
Schaalbaarheid Beperkt tot enkele documenten Verwerkt duizenden
Vereiste code Geen (maar arbeidsintensief) ~30 regels C#
Uitvoer Alleen visuele inspectie Gestructureerd PASS/FAIL‑rapport

Het contrast is opvallend: wat vroeger een volledige werkdag in beslag nam, draait nu als een achtergrondtaak.

Praktijkvoorbeeld: Juridische contractbibliotheek

Een advocatenkantoor slaat 15 000 contracten op in een gedeelde map. Hun beleid vereist de zin “CONFIDENTIAL – CLIENT XYZ” en het zegel van het kantoor op elke pagina. Door de bovenstaande fragmenten te integreren in een nachtelijk PowerShell‑script, heeft het kantoor bereikt:

  • 100 % detectie van ontbrekende markeringen (voorheen glipte 8 % erdoor).
  • Nul handmatige uren besteed aan de audit.
  • Een audit‑trail opgeslagen in een interne SharePoint‑lijst voor toekomstige regelgevende beoordelingen.
// Example of the nightly job entry point
var folder = @"\\fileserver\Contracts";
foreach (var pdf in Directory.GetFiles(folder, "*.pdf", SearchOption.AllDirectories))
{
    // reuse the methods from steps 1‑4
    ScanAll(pdf);
    VerifyText(pdf, "CONFIDENTIAL – CLIENT XYZ");
    VerifyLogo(pdf, @"C:\Logos\firm-seal.png");
    RunReport(pdf);
}

Het script draait zonder toezicht en e‑mailt elke ochtend een samenvatting.

Wat kun je nog meer doen met GroupDocs.Watermark?

Buiten auditing toont het voorbeeldproject hoe je watermerken programmatisch kunt vervangen en verwijderen. De screenshots hieronder demonstreren beide bewerkingen op een echte PDF:

Tekstvervanging — het oude watermerk wordt bijgewerkt met nieuwe tekst, lettertype en kleur

Gerichte verwijdering — alleen watermerken die zowel tekst- als opmaakcriteria matchen, worden verwijderd

Andere scenario’s die je kunt bouwen met dezelfde API:

  • Voeg onzichtbare tracking‑watermerken toe die een unieke ID embedden voor lek‑tracering.
  • Bulk vervang verouderde logo’s in een heel archief.
  • Genereer PDF‑klare compliance‑certificaten na een succesvolle audit.
  • Integreer met Azure Functions of AWS Lambda voor serverless verwerking.

Elk scenario gebruikt dezelfde kern‑API – wissel simpelweg de zoekcriteria of het watermerktype.

Conclusie

Wat vroeger een team vereiste om door pagina’s te bladeren, aantekeningen te maken en het risico op gemiste markeringen liep, is nu een paar seconden code die een auditabel PASS/FAIL‑rapport oplevert. Met GroupDocs.Watermark for .NET krijg je:

  • Volledig zicht op elk watermerk.
  • Betrouwbare detectie van tekst, gestylede tekst en logo’s.
  • Automatische compliance‑rapportage.
  • De mogelijkheid om watermerken programmatisch bij te werken of te verwijderen.

Probeer het en transformeer je watermerk‑complianceproces van een hoofdpijn naar een herhaalbare service.

Volgende stappen

  • Probeer de gratis API‑trial – verkrijg hier een tijdelijke licentie: Temp License
  • Lees de volledige documentatie voor geavanceerde opties: Docs
  • Verken de .NET API‑referentie voor alle klassen en methoden: API Reference
  • Clone het voorbeeldproject op GitHub om een volledige console‑app te zien: GitHub Samples
  • Stel vragen of deel je use‑case op het community‑forum: Forum