c# - 使用 iTextSharp 从 PDF 中删除水印

标签 c# pdf itext

我使用 Pdfstamper 在 pdf 上添加了水印。这是代码:

for (int pageIndex = 1; pageIndex <= pageCount; pageIndex++)
{
    iTextSharp.text.Rectangle pageRectangle = reader.GetPageSizeWithRotation(pageIndex);
    PdfContentByte pdfData = stamper.GetUnderContent(pageIndex);
    pdfData.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, 
        BaseFont.NOT_EMBEDDED), watermarkFontSize);
    PdfGState graphicsState = new PdfGState();
    graphicsState.FillOpacity = watermarkFontOpacity;
    pdfData.SetGState(graphicsState);
    pdfData.SetColorFill(iTextSharp.text.BaseColor.BLACK);
    pdfData.BeginText();
    pdfData.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "LipikaChatterjee", 
        pageRectangle.Width / 2, pageRectangle.Height / 2, watermarkRotation);
    pdfData.EndText();
}

这很好用。现在我想从我的 pdf 中删除这个水印。我查看了 iTextSharp 但无法获得任何帮助。我什至尝试添加水印作为图层,然后删除该图层,但无法从pdf中删除图层的内容。我研究了 iText 的图层移除功能,发现了一个类 OCGRemover,但我无法在 iTextsharp 中获得等效的类。

最佳答案

我将根据“我什至尝试将水印添加为图层”这一说法,对您进行无罪推定,并假设您正在处理自己正在创建的内容,而不是试图取消其他人的内容的水印。

PDF 使用可选内容组 (OCG) 将对象存储为图层。如果您将水印文本添加到图层中,以后可以很容易地将其删除。

下面的代码是面向 iTextSharp 5.1.1.0 的完整工作 C# 2010 WinForms 应用程序。它使用基于 Bruno's original Java code found here 的代码。该代码分为三部分。第 1 部分创建了一个示例 PDF 供我们使用。第 2 部分从第一个部分创建一个新的 PDF,并将水印应用到单独图层上的每个页面。第 3 部分根据第二个 PDF 创建最终 PDF,但删除带有水印文本的图层。有关更多详细信息,请参阅代码注释。

当您创建 PdfLayer 对象时,您可以为其指定一个名称以显示在 PDF 阅读器中。不幸的是,我找不到访问该名称的方法,因此下面的代码会查找图层内的实际水印文本。如果您没有使用其他 PDF 图层,我建议您在内容流中查找 /OC,而不是浪费时间查找实际的水印文本。如果您找到了按名称查找 /OC 组的方法,请告诉我!

using System;
using System.Windows.Forms;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            string workingFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            string startFile = Path.Combine(workingFolder, "StartFile.pdf");
            string watermarkedFile = Path.Combine(workingFolder, "Watermarked.pdf");
            string unwatermarkedFile = Path.Combine(workingFolder, "Un-watermarked.pdf");
            string watermarkText = "This is a test";

            //SECTION 1
            //Create a 5 page PDF, nothing special here
            using (FileStream fs = new FileStream(startFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
                using (Document doc = new Document(PageSize.LETTER)) {
                    using (PdfWriter witier = PdfWriter.GetInstance(doc, fs)) {
                        doc.Open();

                        for (int i = 1; i <= 5; i++) {
                            doc.NewPage();
                            doc.Add(new Paragraph(String.Format("This is page {0}", i)));
                        }

                        doc.Close();
                    }
                }
            }

            //SECTION 2
            //Create our watermark on a separate layer. The only different here is that we are adding the watermark to a PdfLayer which is an OCG or Optional Content Group
            PdfReader reader1 = new PdfReader(startFile);
            using (FileStream fs = new FileStream(watermarkedFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
                using (PdfStamper stamper = new PdfStamper(reader1, fs)) {
                    int pageCount1 = reader1.NumberOfPages;
                    //Create a new layer
                    PdfLayer layer = new PdfLayer("WatermarkLayer", stamper.Writer);
                    for (int i = 1; i <= pageCount1; i++) {
                        iTextSharp.text.Rectangle rect = reader1.GetPageSize(i);
                        //Get the ContentByte object
                        PdfContentByte cb = stamper.GetUnderContent(i);
                        //Tell the CB that the next commands should be "bound" to this new layer
                        cb.BeginLayer(layer);
                        cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 50);
                        PdfGState gState = new PdfGState();
                        gState.FillOpacity = 0.25f;
                        cb.SetGState(gState);
                        cb.SetColorFill(BaseColor.BLACK);
                        cb.BeginText();
                        cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, rect.Width / 2, rect.Height / 2, 45f);
                        cb.EndText();
                        //"Close" the layer
                        cb.EndLayer();
                    }
                }
            }

            //SECTION 3
            //Remove the layer created above
            //First we bind a reader to the watermarked file, then strip out a bunch of things, and finally use a simple stamper to write out the edited reader
            PdfReader reader2 = new PdfReader(watermarkedFile);

            //NOTE, This will destroy all layers in the document, only use if you don't have additional layers
            //Remove the OCG group completely from the document.
            //reader2.Catalog.Remove(PdfName.OCPROPERTIES);

            //Clean up the reader, optional
            reader2.RemoveUnusedObjects();

            //Placeholder variables
            PRStream stream;
            String content;
            PdfDictionary page;
            PdfArray contentarray;

            //Get the page count
            int pageCount2 = reader2.NumberOfPages;
            //Loop through each page
            for (int i = 1; i <= pageCount2; i++) {
                //Get the page
                page = reader2.GetPageN(i);
                //Get the raw content
                contentarray = page.GetAsArray(PdfName.CONTENTS);
                if (contentarray != null) {
                    //Loop through content
                    for (int j = 0; j < contentarray.Size; j++) {
                        //Get the raw byte stream
                        stream = (PRStream)contentarray.GetAsStream(j);
                        //Convert to a string. NOTE, you might need a different encoding here
                        content = System.Text.Encoding.ASCII.GetString(PdfReader.GetStreamBytes(stream));
                        //Look for the OCG token in the stream as well as our watermarked text
                        if (content.IndexOf("/OC") >= 0 && content.IndexOf(watermarkText) >= 0) {
                            //Remove it by giving it zero length and zero data
                            stream.Put(PdfName.LENGTH, new PdfNumber(0));
                            stream.SetData(new byte[0]);
                        }
                    }
                }
            }

            //Write the content out
            using (FileStream fs = new FileStream(unwatermarkedFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
                using (PdfStamper stamper = new PdfStamper(reader2, fs)) {

                }
            }
            this.Close();
        }
    }
}

关于c# - 使用 iTextSharp 从 PDF 中删除水印,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8125296/

相关文章:

c# - out 参数 - 为什么它不起作用

javascript - 创建 Web 应用程序的可打印/可下载 PDF

c# - 如何使用 asp.net c# 直接打印使用 iTextSharp 动态创建的 PDF?

java - PDFTable Itext 阿拉伯语

java - 旋转 pdf 页面时书签不平衡

c# - WPF C# 项目的 sql server 登录失败

c# - C# .NET 标签中的多种颜色

c# - 正则表达式将字符串中的日期与 where 子句匹配

ruby - 在rails应用程序中生成pdf时如何用Prawn定义行高?

java - JFreeChart setTickLabelFont() 和 setLabelFont() 不适用于 iText PDF