O Método Antigo Era Doloroso

Imagine um oficial de conformidade encarregado de verificar se cada contrato em uma unidade de rede contém a palavra “CONFIDENTIAL” e o logotipo da empresa em cada página. O processo atual se parece com isto:

  1. Abra um arquivo em um visualizador.
  2. Passe pelas páginas procurando a frase ou a imagem.
  3. Anote observações em uma planilha.
  4. Repita para milhares de PDFs, arquivos Word e apresentações.

Uma única marca d’água perdida pode disparar uma revisão custosa, e o esforço manual facilmente ultrapassa 8 horas por semana para uma pequena equipe. Além disso, textos rotacionados, palavras divididas ou logotipos salvos como imagens costumam escapar ao olho humano, deixando a organização vulnerável.

Existe uma Maneira Melhor

GroupDocs.Watermark for .NET elimina todas as etapas de adivinhação. Seu motor agnóstico a formatos pode ler mais de 100 tipos de documentos, localizar marcas d’água de texto, imagem e até estilizadas, e expor todos os metadados relevantes através de uma API limpa. O tutorial a seguir mostra como alguns trechos concisos substituem o loop manual por um fluxo de trabalho automatizado e repetível.

Pré-requisitos

  • .NET 6.0 ou superior.
  • GroupDocs.Watermark pacote NuGet (dotnet add package GroupDocs.Watermark).
  • (Opcional) uma licença temporária – veja o link ao final deste artigo.

O Novo Método: Auditoria Automatizada de Marca d’Água

A seguir percorremos quatro operações principais. Cada bloco é um exemplo autônomo que pode ser inserido em um aplicativo console, em uma etapa de CI ou em um serviço em segundo plano.

Etapa 1 – Escanear Todas as Marcas d’Água

Primeiro precisamos de um inventário completo. O método Search() devolve uma coleção onde cada entrada contém texto (ou imagem), localização, rotação, número da página e tamanho bruto da imagem.

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}");
    }
}

Ponto chave: O loop roda em menos de um segundo para um PDF típico de 50 páginas.

Etapa 2 – Verificar a Marca d’Água de Texto Obrigatória

Políticas de conformidade costumam exigir uma frase específica (por exemplo, “CONFIDENTIAL”). O TextSearchCriteria com SkipUnreadableCharacters lida automaticamente com texto dividido ou rotacionado.

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

O método devolve true quando a frase aparece ao menos uma vez, fornecendo um sinal instantâneo de PASS/FAIL.

Etapa 3 – Verificar o Logotipo da Empresa

Logotipos são imagens raster, e sua aparência pode variar ligeiramente devido à compressão. ImageDctHashSearchCriteria cria um hash perceptual do logotipo de referência e o compara com uma tolerância configurável.

using (var wk = new Watermarker(filePath))
{
    var crit = new ImageDctHashSearchCriteria(logoPath);
    crit.MaxDifference = 0.9;   // tolera escala/modificação de cor moderada
    var matches = wk.Search(crit);
    bool ok = matches.Count > 0;
    Console.WriteLine($"  [{(ok ? "PASS" : "FAIL")}] " +
        $"logo instances: {matches.Count}");
    return ok;
}

Mesmo uma cópia de baixa resolução do logotipo será reconhecida.

Etapa 4 – Executar um Relatório Completo de Conformidade

Políticas reais combinam vários requisitos. O primeiro bloco verifica quatro regras de formatação — presença de texto, fonte, tamanho e estilo negrito — cada uma combinando TextSearchCriteria com 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++;

A quinta regra verifica a cobertura de páginas — a marca d’água deve aparecer em todas as páginas. Por fim, o veredicto agrega todos os resultados:

    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)");
}

O relatório está pronto para ser exportado como JSON, CSV ou alimentado diretamente a um sistema de tickets.


Lado a Lado: Antes vs. Depois

Revisão Manual Auditoria Automatizada
Tempo Horas por lote Segundos por arquivo
Precisão Propenso a erro humano API determinística
Escalabilidade Limitado a poucos documentos Lida com milhares
Código necessário Nenhum (mas intensivo em mão de obra) ~30 linhas de C#
Saída Apenas inspeção visual Relatório estruturado PASS/FAIL

O contraste é marcante: o que antes ocupava um dia inteiro de trabalho agora roda como um job em segundo plano.


Exemplo Real: Biblioteca de Contratos Legais

Um escritório de advocacia armazena 15 000 contratos em uma pasta compartilhada. Sua política exige a frase “CONFIDENTIAL – CLIENT XYZ” e o selo da empresa em cada página. Ao integrar os trechos acima em um script PowerShell noturno, o escritório alcançou:

  • 100 % de detecção de marcas ausentes (antes 8 % escapavam).
  • Zero horas manuais gastas na auditoria.
  • Um rastro de auditoria salvo em uma lista interna do SharePoint para revisões regulatórias futuras.
// Exemplo do ponto de entrada do job noturno
var folder = @"\\fileserver\Contracts";
foreach (var pdf in Directory.GetFiles(folder, "*.pdf", SearchOption.AllDirectories))
{
    // reutiliza os métodos das etapas 1‑4
    ScanAll(pdf);
    VerifyText(pdf, "CONFIDENTIAL – CLIENT XYZ");
    VerifyLogo(pdf, @"C:\Logos\firm-seal.png");
    RunReport(pdf);
}

O script roda sem supervisão e envia um resumo por e‑mail a cada manhã.


O Que Mais Você Pode Fazer com GroupDocs.Watermark?

Além da auditoria, o projeto de exemplo mostra como substituir e remover marcas d’água programaticamente. As capturas de tela abaixo demonstram ambas as operações em um PDF real:

Text replacement — the old watermark is updated with new text, font, and color

Targeted removal — only watermarks matching both text and formatting criteria are deleted

Outros cenários que você pode construir com a mesma API:

  • Adicionar marcas d’água invisíveis de rastreamento que incorporam um ID único para rastreamento de vazamentos.
  • Substituir em massa logotipos desatualizados em todo um arquivo.
  • Gerar certificados de conformidade prontos para PDF após uma auditoria bem‑sucedida.
  • Integrar com Azure Functions ou AWS Lambda para processamento serverless.

Cada cenário usa a mesma API central – basta trocar o critério de busca ou o tipo de marca d’água.


Conclusão

O que antes exigia que uma equipe folheasse páginas, anotasse observações e corresse o risco de marcas perdidas agora se resume a poucos segundos de código que produzem um relatório auditável PASS/FAIL. Com GroupDocs.Watermark for .NET você obtém:

  • Visibilidade total de cada marca d’água.
  • Detecção confiável de texto, texto estilizado e logotipos.
  • Relatórios automáticos de conformidade.
  • Capacidade de atualizar ou remover marcas d’água programaticamente.

Experimente e transforme seu processo de conformidade de marcas d’água de uma dor de cabeça em um serviço repetível.


Próximos Passos

  • Teste a versão de avaliação gratuita da API – obtenha uma licença temporária aqui: Temp License
  • Leia a documentação completa para opções avançadas: Docs
  • Explore a referência da API .NET para todas as classes e métodos: API Reference
  • Clone o projeto de exemplo no GitHub para ver um aplicativo console completo: GitHub Samples
  • Faça perguntas ou compartilhe seu caso de uso no fórum da comunidade: Forum