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:
- Abra um arquivo em um visualizador.
- Passe pelas páginas procurando a frase ou a imagem.
- Anote observações em uma planilha.
- 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:
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