วิธีเดิมทำให้เจ็บปวด

ลองนึกภาพเจ้าหน้าที่ปฏิบัติตามกฎระเบียบที่ต้องตรวจสอบว่าแต่ละสัญญาในไดรฟ์ที่ใช้ร่วมกันมีคำ “CONFIDENTIAL” และโลโก้ของบริษัทบนทุกหน้า กระบวนการปัจจุบันเป็นดังนี้

  1. เปิดไฟล์ในตัวดูไฟล์
  2. เลื่อนดูแต่ละหน้าเพื่อค้นหาคำหรือรูปภาพ
  3. จดบันทึกลงในสเปรดชีต
  4. ทำซ้ำสำหรับไฟล์ PDF, Word และงานนำเสนอหลายพันไฟล์

สัญลักษณ์ลายน้ำที่พลาดไปเพียงหนึ่งครั้งอาจทำให้ต้องตรวจทานใหม่ซึ่งมีค่าใช้จ่ายสูง และความพยายามแบบแมนนวลมักเกิน 8 ชั่วโมงต่อสัปดาห์ สำหรับทีมขนาดเล็ก นอกจากนี้ข้อความที่หมุน, คำที่แยกเป็นส่วน หรือโลโก้ที่บันทึกเป็นรูปภาพมักหลุดรอดจากสายตามนุษย์ ทำให้องค์กรเสี่ยงต่อการเปิดเผยข้อมูล

มีวิธีที่ดีกว่า

GroupDocs.Watermark for .NET ลบขั้นตอนที่ต้องคาดเดาออกไปทั้งหมด เครื่องยนต์ที่ไม่ขึ้นกับรูปแบบสามารถอ่านเอกสารได้มากกว่า 100 ประเภท ค้นหาข้อความ, รูปภาพและลายน้ำที่มีสไตล์ต่าง ๆ และเปิดเผยเมตาดาต้าที่เกี่ยวข้องทั้งหมดผ่าน API ที่เรียบง่าย บทแนะนำต่อไปนี้จะแสดงว่าชุดโค้ดสั้น ๆ สามบรรทัดสามารถแทนที่การทำงานแบบแมนนวลด้วยเวิร์กโฟลว์อัตโนมัติที่ทำซ้ำได้อย่างไร

ข้อกำหนดเบื้องต้น

  • .NET 6.0 หรือใหม่กว่า
  • แพ็กเกจ NuGet GroupDocs.Watermark (dotnet add package GroupDocs.Watermark)
  • (ไม่บังคับ) ใบอนุญาตชั่วคราว – ดูลิงก์ที่ส่วนท้ายของบทความนี้

วิธีใหม่: การตรวจสอบลายน้ำอัตโนมัติ

ด้านล่างเราจะเดินผ่านสี่การดำเนินการหลัก แต่ละบล็อกเป็นตัวอย่างที่ทำงานได้เองซึ่งคุณสามารถใส่ลงในแอปคอนโซล, ขั้นตอน CI หรือบริการพื้นหลังได้

ขั้นตอน 1 – สแกนลายน้ำทั้งหมด

ก่อนอื่นเราต้องทำรายการเต็ม Search() จะคืนคอลเลกชันที่แต่ละรายการมีข้อความ (หรือรูปภาพ), ตำแหน่ง, การหมุน, หมายเลขหน้าและขนาดภาพดิบ

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

จุดสำคัญ: ลูปนี้ทำงานภายในไม่ถึงหนึ่งวินาทีสำหรับ PDF 50‑หน้าทั่วไป

ขั้นตอน 2 – ตรวจสอบลายน้ำข้อความที่ต้องการ

นโยบายการปฏิบัติตามมักกำหนดวลีเฉพาะ (เช่น “CONFIDENTIAL”) TextSearchCriteria พร้อม SkipUnreadableCharacters จะจัดการกับข้อความที่แยกหรือหมุนโดยอัตโนมัติ

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

เมธอดจะคืนค่า true เมื่อวลีปรากฏอย่างน้อยหนึ่งครั้ง ให้คุณได้สัญญาณ PASS/FAIL ทันที

ขั้นตอน 3 – ตรวจสอบโลโก้บริษัท

โลโก้เป็นภาพแรสเตอร์และอาจมีการเปลี่ยนแปลงเล็กน้อยจากการบีบอัด ImageDctHashSearchCriteria สร้างแฮชเชิงรับรู้ของโลโก้อ้างอิงและเปรียบเทียบด้วยค่าความคลาดเคลื่อนที่กำหนดได้

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

แม้จะเป็นสำเนาคุณภาพต่ำของโลโก้ก็จะถูกตรวจจับได้

ขั้นตอน 4 – รันรายงานการปฏิบัติตามแบบเต็มรูปแบบ

นโยบายในโลกจริงมักรวมหลายข้อกำหนด บล็อกแรกตรวจสอบสี่กฎการจัดรูปแบบ — การมีข้อความ, ฟอนต์, ขนาดและสไตล์หนา — โดยผสาน TextSearchCriteria กับ TextFormattingSearchCriteria ผ่าน .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++;

กฎที่ห้าตรวจสอบการครอบคลุมหน้า — ลายน้ำต้องปรากฏบนทุกหน้า สุดท้ายผลสรุปจะรวมผลทั้งหมดเข้าด้วยกัน

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

รายงานพร้อมส่งออกเป็น JSON, CSV หรือส่งต่อโดยตรงไปยังระบบตั๋ว


การเปรียบเทียบแบบเคียงข้าง: ก่อน vs. หลัง

การตรวจสอบแบบแมนนวล การตรวจสอบอัตโนมัติ
เวลา ชั่วโมงต่อชุด วินาทีต่อไฟล์
ความแม่นยำ มีความผิดพลาดของมนุษย์ API เชิงกำหนด
ความสามารถขยาย จำกัดจำนวนเอกสาร รองรับหลายพันไฟล์
โค้ดที่ต้องใช้ ไม่มี (แต่ใช้แรงงานมาก) ประมาณ 30 บรรทัด C#
ผลลัพธ์ ตรวจสอบด้วยสายตาเท่านั้น รายงาน PASS/FAIL แบบโครงสร้าง

ความแตกต่างชัดเจน: สิ่งที่เคยใช้เวลาทั้งวันทำงานเต็มวัน ตอนนี้ทำเป็นงานเบื้องหลังได้ในพริบตา


ตัวอย่างจากโลกจริง: ห้องสมุดสัญญากฎหมาย

บริษัทกฎหมายเก็บ 15 000 สัญญาไว้ในโฟลเดอร์ที่ใช้ร่วมกัน นโยบายของพวกเขาต้องการวลี “CONFIDENTIAL – CLIENT XYZ” และตราประทับของบริษัทบนทุกหน้า โดยการรวมสคริปต์ข้างต้นเข้าไปในสคริปต์ PowerShell ที่ทำงานทุกคืน บริษัทบรรลุผลดังนี้

  • การตรวจจับ 100 % ของลายน้ำที่หายไป (ก่อนหน้านี้หลุดผ่าน 8 %)
  • ศูนย์ชั่วโมงทำงานแมนนวล สำหรับการตรวจสอบ
  • บันทึกการตรวจสอบ ถูกบันทึกลงในรายการ SharePoint ภายในเพื่อการตรวจสอบตามกฎระเบียบในอนาคต
// 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);
}

สคริปต์ทำงานโดยไม่ต้องดูแลและส่งอีเมลสรุปทุกเช้า


คุณสามารถทำอะไรได้อีกกับ GroupDocs.Watermark?

นอกเหนือจากการตรวจสอบ ตัวอย่างโปรเจกต์ยังแสดงวิธี replace และ remove ลายน้ำโดยโปรแกรม ภาพหน้าจอด้านล่างแสดงการทำงานทั้งสองบน PDF จริง

การแทนที่ข้อความ — ลายน้ำเก่าถูกอัปเดตด้วยข้อความใหม่, ฟอนต์และสี

การลบแบบเจาะจง — ลายน้ำที่ตรงกับทั้งข้อความและเกณฑ์การจัดรูปแบบเท่านั้นที่ถูกลบ

สถานการณ์อื่น ๆ ที่คุณสามารถสร้างด้วย API เดียวกัน

  • เพิ่มลายน้ำติดตามที่มองไม่เห็น ที่ฝังรหัส ID เฉพาะสำหรับการติดตามการรั่วไหล
  • แทนที่โลโก้ล้าสมัยเป็นจำนวนมาก ทั่วคลังข้อมูลทั้งหมด
  • สร้างใบรับรองการปฏิบัติตามที่พร้อม PDF หลังจากการตรวจสอบสำเร็จ
  • ผสานกับ Azure Functions หรือ AWS Lambda เพื่อประมวลผลแบบ serverless

แต่ละสถานการณ์ใช้ API แกนเดียวกัน – เพียงสลับเกณฑ์การค้นหาหรือประเภทลายน้ำ


สรุป

สิ่งที่เคยต้องใช้ทีมคนพลิกหน้า, จดบันทึกและเสี่ยงต่อการพลาดลายน้ำ ตอนนี้เป็น ไม่กี่วินาทีของโค้ด ที่สร้างรายงาน PASS/FAIL ที่ตรวจสอบได้ ด้วย GroupDocs.Watermark for .NET คุณจะได้:

  • การมองเห็นเต็มรูปแบบของลายน้ำทุกตัว
  • การตรวจจับข้อความ, ข้อความที่มีสไตล์และโลโก้อย่างเชื่อถือได้
  • รายงานการปฏิบัติตามอัตโนมัติ
  • ความสามารถในการอัปเดตหรือเอาลายน้ำออกโดยโปรแกรม

ลองใช้และเปลี่ยนกระบวนการตรวจสอบลายน้ำจากอาการปวดหัวให้เป็นบริการที่ทำซ้ำได้


ขั้นตอนต่อไป

  • ลองใช้การทดลอง API ฟรี – รับใบอนุญาตชั่วคราวได้ที่นี่: Temp License
  • อ่านเอกสารเต็ม สำหรับตัวเลือกขั้นสูง: Docs
  • สำรวจอ้างอิง API .NET สำหรับคลาสและเมธอดทั้งหมด: API Reference
  • โคลนโปรเจกต์ตัวอย่าง บน GitHub เพื่อดูแอปคอนโซลเต็มรูปแบบ: GitHub Samples
  • ตั้งคำถาม หรือแบ่งปันกรณีการใช้งานของคุณในฟอรั่มชุมชน: Forum