// ===========================================================================
// ©2013-2026 WebSupergoo. All rights reserved.
//
// This source code is for use exclusively with the ABCpdf product with
// which it is distributed, under the terms of the license for that
// product. Details can be found at
//
// http://www.websupergoo.com/
//
// This copyright notice must not be deleted and must be reproduced alongside
// any sections of code extracted from this module.
// ===========================================================================
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Reflection;
using WebSupergoo.ABCpdf14;
using WebSupergoo.ABCpdf14.Objects;
using WebSupergoo.ABCpdf14.Atoms;
using WebSupergoo.ABCpdf14.Operations;
namespace Redaction
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form {
private System.Windows.Forms.Button button1;
private Button button2;
private Button button4;
private Button button5;
private PictureBox pictureBox1;
private GroupBox groupBox1;
private TextBox textBoxFind;
private RadioButton radioButtonFine;
private RadioButton radioButtonCoarse;
private GroupBox groupBox2;
private Label label1;
private TextBox textBoxRect;
private GroupBox groupBox3;
private Label label2;
private TextBox textBoxFont;
private Button button3;
private Button button6;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public Form1() {
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing) {
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.button5 = new System.Windows.Forms.Button();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.textBoxFind = new System.Windows.Forms.TextBox();
this.radioButtonFine = new System.Windows.Forms.RadioButton();
this.radioButtonCoarse = new System.Windows.Forms.RadioButton();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.label1 = new System.Windows.Forms.Label();
this.textBoxRect = new System.Windows.Forms.TextBox();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.label2 = new System.Windows.Forms.Label();
this.textBoxFont = new System.Windows.Forms.TextBox();
this.button3 = new System.Windows.Forms.Button();
this.button6 = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.SuspendLayout();
//
// button1
//
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.button1.Location = new System.Drawing.Point(517, 491);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(323, 34);
this.button1.TabIndex = 0;
this.button1.Text = "Redact Text Area";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.button2.Location = new System.Drawing.Point(517, 533);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(321, 34);
this.button2.TabIndex = 1;
this.button2.Text = "Redact Text Words";
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// button4
//
this.button4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.button4.Location = new System.Drawing.Point(515, 576);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(322, 33);
this.button4.TabIndex = 3;
this.button4.Text = "Redact Text Fonts";
this.button4.Click += new System.EventHandler(this.button4_Click);
//
// button5
//
this.button5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.button5.Location = new System.Drawing.Point(514, 618);
this.button5.Name = "button5";
this.button5.Size = new System.Drawing.Size(323, 34);
this.button5.TabIndex = 4;
this.button5.Text = "Redact Image Area";
this.button5.Click += new System.EventHandler(this.button5_Click);
//
// pictureBox1
//
this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pictureBox1.Location = new System.Drawing.Point(24, 19);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(480, 853);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBox1.TabIndex = 5;
this.pictureBox1.TabStop = false;
//
// groupBox1
//
this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.groupBox1.Controls.Add(this.textBoxFind);
this.groupBox1.Controls.Add(this.radioButtonFine);
this.groupBox1.Controls.Add(this.radioButtonCoarse);
this.groupBox1.Location = new System.Drawing.Point(514, 18);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(321, 268);
this.groupBox1.TabIndex = 10;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Text Selection - Marked in Blue";
//
// textBoxFind
//
this.textBoxFind.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.textBoxFind.Location = new System.Drawing.Point(26, 96);
this.textBoxFind.Multiline = true;
this.textBoxFind.Name = "textBoxFind";
this.textBoxFind.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.textBoxFind.Size = new System.Drawing.Size(275, 148);
this.textBoxFind.TabIndex = 12;
this.textBoxFind.Text = "plant\r\nflower";
this.textBoxFind.TextChanged += new System.EventHandler(this.textBoxFind_TextChanged);
//
// radioButtonFine
//
this.radioButtonFine.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.radioButtonFine.AutoSize = true;
this.radioButtonFine.Checked = true;
this.radioButtonFine.Location = new System.Drawing.Point(34, 28);
this.radioButtonFine.Name = "radioButtonFine";
this.radioButtonFine.Size = new System.Drawing.Size(126, 24);
this.radioButtonFine.TabIndex = 11;
this.radioButtonFine.TabStop = true;
this.radioButtonFine.Text = "Fine Grained";
this.radioButtonFine.UseVisualStyleBackColor = true;
//
// radioButtonCoarse
//
this.radioButtonCoarse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.radioButtonCoarse.AutoSize = true;
this.radioButtonCoarse.Location = new System.Drawing.Point(35, 63);
this.radioButtonCoarse.Name = "radioButtonCoarse";
this.radioButtonCoarse.Size = new System.Drawing.Size(146, 24);
this.radioButtonCoarse.TabIndex = 10;
this.radioButtonCoarse.Text = "Coarse Grained";
this.radioButtonCoarse.UseVisualStyleBackColor = true;
//
// groupBox2
//
this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.groupBox2.Controls.Add(this.label1);
this.groupBox2.Controls.Add(this.textBoxRect);
this.groupBox2.Location = new System.Drawing.Point(514, 295);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(320, 89);
this.groupBox2.TabIndex = 12;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Area Selection - Marked in Green";
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(21, 37);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(43, 20);
this.label1.TabIndex = 16;
this.label1.Text = "Rect";
//
// textBoxRect
//
this.textBoxRect.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.textBoxRect.Location = new System.Drawing.Point(78, 32);
this.textBoxRect.Name = "textBoxRect";
this.textBoxRect.Size = new System.Drawing.Size(223, 26);
this.textBoxRect.TabIndex = 15;
this.textBoxRect.Text = "5 5 400 80";
this.textBoxRect.TextChanged += new System.EventHandler(this.textBoxRect_TextChanged);
//
// groupBox3
//
this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.groupBox3.Controls.Add(this.label2);
this.groupBox3.Controls.Add(this.textBoxFont);
this.groupBox3.Location = new System.Drawing.Point(517, 393);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(320, 89);
this.groupBox3.TabIndex = 17;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Font Selection - Marked in Red";
//
// label2
//
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(19, 37);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(51, 20);
this.label2.TabIndex = 16;
this.label2.Text = "Name";
//
// textBoxFont
//
this.textBoxFont.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.textBoxFont.Location = new System.Drawing.Point(78, 32);
this.textBoxFont.Name = "textBoxFont";
this.textBoxFont.Size = new System.Drawing.Size(223, 26);
this.textBoxFont.TabIndex = 15;
this.textBoxFont.Text = "Helvetica-Bold";
this.textBoxFont.TextChanged += new System.EventHandler(this.textBoxFont_TextChanged);
//
// button3
//
this.button3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.button3.Location = new System.Drawing.Point(517, 728);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(323, 34);
this.button3.TabIndex = 18;
this.button3.Text = "Reload Document";
this.button3.Click += new System.EventHandler(this.button3_Click);
//
// button6
//
this.button6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.button6.Location = new System.Drawing.Point(517, 661);
this.button6.Name = "button6";
this.button6.Size = new System.Drawing.Size(321, 34);
this.button6.TabIndex = 19;
this.button6.Text = "ReplaceText Words";
this.button6.Click += new System.EventHandler(this.button6_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(8, 19);
this.ClientSize = new System.Drawing.Size(854, 890);
this.Controls.Add(this.button6);
this.Controls.Add(this.button3);
this.Controls.Add(this.groupBox3);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.pictureBox1);
this.Controls.Add(this.button5);
this.Controls.Add(this.button4);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
Application.Run(new Form1());
}
string _src = "";
private void Form1_Load(object sender, EventArgs e) {
Reload();
}
private void textBoxRect_TextChanged(object sender, EventArgs e) {
UpdateDoc();
}
private void textBoxFont_TextChanged(object sender, EventArgs e) {
UpdateDoc();
}
private void textBoxFind_TextChanged(object sender, EventArgs e) {
UpdateDoc();
}
private void Reload() {
string theBase = Directory.GetCurrentDirectory();
string theRez = Directory.GetParent(theBase).Parent.FullName + "\\";
foreach (string file in Directory.GetFiles(theRez, "*.pdf")) {
if (!Path.GetFileName(file).StartsWith("_")) {
_src = file;
UpdateDoc();
break;
}
}
}
private void UpdateDoc() {
using (Doc doc = LoadDoc()) {
} // do nothing
}
private void button1_Click(object sender, System.EventArgs e) {
// Here we look at an area on the page and redact the text in it
XRect toRedact = new XRect(textBoxRect.Text);
using (Doc doc = new Doc()) {
doc.Read(_src);
TextOperation op = new TextOperation(doc);
op.PageContents.AddPages(1);
string text = op.GetText(toRedact, 1);
IList<TextFragment> fragments = op.Select(0, text.Length);
if (radioButtonCoarse.Checked)
SimpleRedaction.RedactTextOps(doc, fragments);
else
FineRedaction.RedactCharacters(doc, fragments);
doc.Flatten();
string dst = Path.Combine(Directory.GetParent(_src).FullName, "_" + Path.GetRandomFileName() + ".pdf");
doc.Save(dst);
_src = dst;
UpdateDoc();
}
}
private void button2_Click(object sender, EventArgs e) {
// here we search for some text on the page and then redact it
using (Doc doc = new Doc()) {
doc.Read(_src);
List<TextFragment> fragments = FindText(doc);
if (radioButtonCoarse.Checked)
SimpleRedaction.RedactTextOps(doc, fragments);
else
FineRedaction.RedactCharacters(doc, fragments);
doc.Flatten();
string dst = Path.Combine(Directory.GetParent(_src).FullName, "_" + Path.GetRandomFileName() + ".pdf");
doc.Save(dst);
_src = dst;
UpdateDoc();
}
}
private void button3_Click(object sender, EventArgs e) {
Reload();
}
private void button4_Click(object sender, EventArgs e) {
// Here we look at specific style - fonts - that we don't want.
// However the crucial difference between this and the other examples is
// that we purge the unused fonts to remove all references from the document.
using (Doc doc = new Doc()) {
doc.Read(_src);
FontTracker tracker = new FontTracker(doc);
for (int i = 0; i < doc.PageNumber; i++) {
doc.PageNumber = i + 1;
using (XRect rect = doc.Rect) {
List<TextFragment> toKeep = new List<TextFragment>();
List<TextFragment> fragments = FindFont(doc, toKeep);
foreach (TextFragment fragment in toKeep)
tracker.Keep(fragment);
SimpleRedaction.RedactTextOps(doc, fragments);
doc.Flatten();
}
}
tracker.PurgeForm();
tracker.Purge();
string dst = Path.Combine(Directory.GetParent(_src).FullName, "_" + Path.GetRandomFileName() + ".pdf");
doc.Save(dst);
_src = dst;
UpdateDoc();
}
}
private void button5_Click(object sender, EventArgs e) {
// here we find and remove images which overlap with our area of interest
XRect toRedact = new XRect(textBoxRect.Text);
using (Doc doc = new Doc()) {
doc.Read(_src);
ImageOperation op = new ImageOperation(doc);
op.PageContents.AddPages(1);
ICollection<ImageProperties> images = op.GetImageProperties();
ImageRedaction redaction = new ImageRedaction(doc, images, doc.PageCount == 1);
foreach (ImageProperties image in images)
foreach (ImageRendition rendition in image.Renditions)
if (rendition.BoundingBox.IntersectsWith(toRedact))
redaction.MarkForRedaction(rendition);
redaction.Redact();
string dst = Path.Combine(Directory.GetParent(_src).FullName, "_" + Path.GetRandomFileName() + ".pdf");
doc.Save(dst);
_src = dst;
UpdateDoc();
}
}
private Doc LoadDoc() {
Doc doc = null;
Bitmap bitmap = null;
try {
if (File.Exists(_src)) {
// NB It's a bit inefficient calling both FindText and FindFont
// but it makes the code a good deal easier to understand.
doc = new Doc();
doc.Read(_src);
doc.Color.SetRgb(0, 255, 0); // green
// show where rect is
doc.Rect.String = textBoxRect.Text;
doc.FrameRect();
// show where text is
doc.Color.SetRgb(0, 0, 255); // blue
doc.Width = 0; // hairlines
foreach (TextFragment fragment in FindText(doc)) {
fragment.Focus();
doc.FrameRect(); // show where fragments have been found
}
// show where fonts are
doc.Color.SetRgb(255, 0, 0); // red
foreach (TextFragment fragment in FindFont(doc, null)) {
fragment.Focus();
doc.FrameRect(); // show where fragments have been found
}
// render
doc.Rect.String = doc.CropBox.String;
bitmap = doc.Rendering.GetBitmap();
}
}
catch {
}
pictureBox1.Image = bitmap;
return doc;
}
private List<TextFragment> FindText(Doc doc) {
TextOperation op = new TextOperation(doc);
op.PageContents.AddPages(1); // hardwired to page one for these examples
string text = op.GetText();
List<TextFragment> fragments = new List<TextFragment>();
foreach (string candidate in textBoxFind.Lines) {
if (candidate.Length == 0)
continue;
int pos = -1;
while (true) {
pos = text.IndexOf(candidate, pos + 1);
if (pos < 0)
break;
fragments.AddRange(op.Select(pos, candidate.Length));
}
}
return fragments;
}
private List<TextFragment> FindFont(Doc doc, List<TextFragment> others) {
TextOperation op = new TextOperation(doc);
op.PageContents.AddPages(1); // hardwired to page one for these examples
string text = op.GetText();
List<TextFragment> fragments = new List<TextFragment>();
if (text.Length > 0) {
IList<TextFragment> candidates = op.Select(0, text.Length);
foreach (TextFragment candidate in candidates) {
if (candidate.Font.BaseFont.Contains(textBoxFont.Text))
fragments.Add(candidate);
else if (others != null)
others.Add(candidate);
}
}
return fragments;
}
private void button6_Click(object sender, EventArgs e) {
// here we search for some text on the page and then replace it
string find = textBoxFind.Lines.Length > 0 ? textBoxFind.Lines[0] : "";
string replace = textBoxFind.Lines.Length > 1 ? textBoxFind.Lines[1] : "";
if (find.Length == 0)
return;
using (Doc doc = new Doc()) {
doc.Read(_src);
var op = new TextOperation(doc);
op.PageContents.IncludeColor = true;
op.PageContents.AddPages(1); // hardwired to page one for these examples
string text = op.GetText();
var pos = text.IndexOf(find, 0);
if (pos < 0)
return; // nothing found
var fragments = op.Select(pos, find.Length);
Debug.Assert(fragments.Count > 0);
if (radioButtonCoarse.Checked)
SimpleRedaction.RedactTextOps(doc, fragments);
else
FineRedaction.RedactCharacters(doc, fragments);
if (!string.IsNullOrEmpty(replace)) {
XRect rect = new XRect();
foreach (var fragment in fragments)
rect.Union(fragment.Rect);
var first = fragments[0];
if (FontSupportsText(first.Font, replace))
doc.Font = first.Font.ID;
else {
doc.Font = doc.EmbedFont(first.Font.BaseFont, LanguageType.Unicode);
var font = (FontObject)doc.ObjectSoup[doc.Font];
if (FontSupportsText(first.Font, replace) == false)
throw new Exception("Text contains glyphs which do not exist in font.");
}
doc.TextStyle.Size = first.FontSize;
doc.ColorSpace = first.FontColorSpace != null ? first.FontColorSpace.ID : 0;
doc.Color.String = first.FontColor.String;
doc.Rect.String = rect.String;
doc.AddText(replace);
}
doc.Flatten();
string dst = Path.Combine(Directory.GetParent(_src).FullName, "_" + Path.GetRandomFileName() + ".pdf");
doc.Save(dst);
_src = dst;
UpdateDoc();
}
}
private static bool FontSupportsText(FontObject font, string replace) {
var chars = font.CharToEncoding;
foreach (var c in replace)
if (!chars.ContainsKey(c))
return false;
return true;
}
}
}