How to create and apply redactions?

Tags: annotationsredactionredaction annotationiText 7pdfSweeppdfSweep example

Is there any way to implement PDF redaction using iText? Working with the Acrobat SDK API I found that redactions also just seem to be annotations with the subtype "Redact".

With the Acrobat SDK the code would like simply like this: AcroPDAnnot annot = page.AddNewAnnot(-1, "Redact", rect) as AcroPDAnnot; Unfortunately, I haven't be able to apply them though as annot.Perform(avDoc) does not seem to work.

In iTextSharp I can create simple text annotations like this PdfAnnotation annotation = PdfAnnotation.CreateText(stamper.Writer, rect, "Title", "Content", false, null); but there's no method to create Redact annotations.

The only other option I found so was was to create black rectangles as explained here, but that doesn't remove the text (it can still be selected). I want to create redaction annotations and eventually apply redaction.

Posted on StackOverflow on Jun 4, 2014 by silent

Answer 1: Creating redaction annotations

iText is a toolbox that gives you the power to create any object you want. You are using a convenience method to create a Text annotation. That's scratching the surface.

You can use iText to create any type of annotation you want, because the PdfAnnotation class extends the PdfDictionary class.

Take a look at the GenericAnnotations is the example that illustrates this functionality.

Here is the code in Java:

private class AnnotatedTextRenderer extends TextRenderer {
    protected String text;
 
    public AnnotatedTextRenderer(Text textElement) {
        super(textElement);
        text = textElement.getText();
    }
 
    @Override
    public void draw(DrawContext drawContext) {
        super.draw(drawContext);
 
        Rectangle rect = getOccupiedAreaBBox();
        PdfAnnotation annotation = new PdfTextAnnotation(
                new Rectangle(
                        rect.getRight() + 10, rect.getBottom(),
                        rect.getWidth() + 20, rect.getHeight()));
        annotation.setTitle(new PdfString("Text annotation"));
        annotation.put(PdfName.Subtype, PdfName.Text);
        annotation.put(PdfName.Open, PdfBoolean.FALSE);
        annotation.put(PdfName.Contents,
                new PdfString(String.format("Icon: %s", text)));
        annotation.put(PdfName.Name, new PdfName(text));
     drawContext.getDocument().getLastPage().addAnnotation(annotation);
    }
}

This is a manual way to create a text annotation. You want a Redact annotations, so you'll need something like this:

PdfAnnotation annotation = new PdfRedactAnnotation(
                new Rectangle(
                        rect.getRight() + 10, rect.getBottom(),
                        rect.getWidth() + 20, rect.getHeight()));

You can use the put() method to add all the other keys you need for the annotation. As I finally got around to create a working example I wanted to share it here.

As I finally got around to create a working example I wanted to share it here.

public void createRedaction(String dest) throws IOException {
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    pdfDoc.addNewPage();
    float[] fillColor = { 0, 0, 0 };
    float[] fillColorRed = { 1, 0, 0 };
    PdfAnnotation redact = new PdfRedactAnnotation(new Rectangle(50, 700, 200, 100))
            .setTitle(new PdfString("My Author"))
            .put(PdfName.Subj, PdfName.Redact)
            .put(PdfName.IC, new PdfArray(fillColor))
            .put(PdfName.OC, new PdfArray(fillColorRed));
    pdfDoc.getFirstPage().addAnnotation(redact);
    pdfDoc.close();
}

Answer 2: Applying redaction

The second question requires at least iText 5.5.4. My sample is written in iText 7. The approach to add opaque rectangles doesn't apply redaction: the redacted content is merely covered, not removed. You can still select the text and copy/paste it. If you're not careful, you risk ending up with a so-called PDF Blackout Folly. See for instance the NSA / AT&T scandal.

Suppose that you have a file to which you added some redaction annotations: page229_redacted.pdf

A PDF with redaction annotations
A PDF with redaction annotations

We can now use this code to remove the content marked by the redaction annotations:

public void removeRedactedContent(String src, String dest) throws IOException {
    //Load the license file to use cleanup features
    LicenseKey.loadLicenseFile(System.getenv("ITEXT7_LICENSEKEY") + "/itextkey-multiple-products.xml");
    PdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(dest));
    PdfCleanUpTool cleaner = new PdfCleanUpTool(pdfDoc, true);
    cleaner.cleanUp();
    pdfDoc.close();
}

This results in the following PDF: page229_apply_redacted.pdf

A redacted PDF
A redacted PDF

As you can see, the red rectangle borders are replaced by filled black rectangles. If you try to select the original text, you'll notice that is is no longer present.

Click this link if you want to see how to answer this question in iText 5.