【问题标题】:Can I remove text objects from an existing PDF and output to a new PDF using iTextSharp?我可以使用 iTextSharp 从现有 PDF 中删除文本对象并输出到新 PDF 吗?
【发布时间】:2019-01-06 06:59:46
【问题描述】:

这个问题是我的旧问题的另一个版本: I want to get all objects except text object as an image from PDF using iTextSharp

原问题

出于特定原因,我正在开发一个程序来使用 iTextSharp 将 PDF 转换为 PPTX。到目前为止,我所做的是获取所有文本对象和图像对象和位置。但我觉得很难得到没有文字的矢量图(比如表格)。实际上,如果我可以将它们作为图像获取会更好。我的计划是将文本对象以外的所有对象合并为背景图像,并将文本对象放在适当的位置。我试图在这里找到类似的问题,但到目前为止还没有运气。如果有人知道如何做这个特定的工作,请回答。谢谢。


我一直在阅读许多相关的问题和讨论,并决定在这里问另一个版本。 我有两个计划如下。如果 iText 开发人员/专家可以指导我,我将不胜感激。

我用于获取文本/图像对象的代码 sn-p

public class MyLocationTextExtractionStrategy: IExtRenderListener, ITextExtractionStrategy,IElementListener
{
    //Text 
    public List<RectAndText> myPoints_txt = new List<RectAndText>();
    public List<RectAndImage> myPoints_img = new List<RectAndImage>();
    public FieldInfo GsField = typeof(TextRenderInfo).GetField("gs", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    public FieldInfo MarkedContentInfosField = typeof(TextRenderInfo).GetField("markedContentInfos", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    public FieldInfo MarkedContentInfoTagField = typeof(MarkedContentInfo).GetField("tag", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    PdfName EMBEDDED_DOCUMENT = new PdfName("EmbeddedDocument");

    //Image 
    public List<byte[]> Images = new List<byte[]>();
    public List<string> ImageNames = new List<string>();

    public bool Add(IElement element)
    {
        element = element;
        return true;
    }

    public void BeginTextBlock()
    {

    }

    public void ClipPath(int rule)
    {

    }

    public void EndTextBlock()
    {

    }

    public string GetResultantText()
    {
        return "";
    }

    public void ModifyPath(PathConstructionRenderInfo renderInfo)
    {
        // ****************************************
        // I think this point I can get info on Path
        // ****************************************
    }

    public void RenderImage(ImageRenderInfo renderInfo)
    {

        PdfImageObject image = renderInfo.GetImage();
        try
        { 
            image = renderInfo.GetImage();
            if (image == null) return;

            ImageNames.Add(string.Format(
              "Image{0}.{1}", renderInfo.GetRef().Number, image.GetFileType()
            ));

            //Write Image to byte
            using (MemoryStream ms = new MemoryStream(image.GetImageAsBytes()))
            {
                Images.Add(ms.ToArray());
            }
            Matrix matrix = renderInfo.GetImageCTM();

            this.myPoints_img.Add(new RectAndImage(matrix[Matrix.I31], matrix[Matrix.I32], matrix[Matrix.I11], matrix[Matrix.I12], Images));
        }
        catch (Exception e)
        {

        }
    }



    public iTextSharp.text.pdf.parser.Path RenderPath(PathPaintingRenderInfo renderInfo)
    {
        // ****************************************
        // I think this point I can get info on Path
        // ****************************************
        return null;
    }

    public  void RenderText(TextRenderInfo renderInfo)
    {

        DocumentFont _font = renderInfo.GetFont();

        LineSegment descentLine = renderInfo.GetDescentLine();
        LineSegment ascentLine = renderInfo.GetAscentLine();
        float x0 = descentLine.GetStartPoint()[0];
        float x1 = ascentLine.GetEndPoint()[0];
        float y0 = descentLine.GetStartPoint()[1];
        float y1 = ascentLine.GetEndPoint()[1];

        Rectangle rect = new Rectangle(x0,y0,x1,y1);
        GraphicsState gs = (GraphicsState)GsField.GetValue(renderInfo);
        float fontSize = gs.FontSize;
        String font_color = gs.FillColor.ToString().Substring(14,6);

        IList<MarkedContentInfo> markedContentInfos = (IList<MarkedContentInfo>)MarkedContentInfosField.GetValue(renderInfo);

        if (markedContentInfos != null && markedContentInfos.Count > 0)
        {
            foreach (MarkedContentInfo info in markedContentInfos)
            {
                if (EMBEDDED_DOCUMENT.Equals(MarkedContentInfoTagField.GetValue(info)))
                    return;
            }
        }

        this.myPoints_txt.Add(new RectAndText(rect, renderInfo.GetText(), fontSize,renderInfo.GetFont().PostscriptFontName, font_color));
    } 
}

新问题

1) 我可以从 PDF 中删除所有文本对象并将其输出到新的吗? 如果是,我可以将输出的所有页面作为图像并将它们用作 PPTX 的背景。 然后我终于可以写文本了(已经使用上面的代码使用 ITextExtractionStrategy 检索到了)

2) 如果 1) 不可行,我将从原始 PDF 中检索所有路径信息(使用 IExtRenderListener)并将它们绘制在新的位图上。 最后我可以把它作为背景并在上面放置文本/图像。 在这种情况下使用 ModifyPath 和 RenderPath 来检索 Path 信息是正确的方法吗?

我知道这似乎有多个问题,但我认为最好将所有内容写在一个线程中以帮助理解。 我非常感谢任何关于我想法的提示或建议。

我相信@mkl、@Amine、@Bruno Lowagie 可以帮助我。 提前致谢。

【问题讨论】:

标签: c# pdf itext


【解决方案1】:

my answer to your old question我解释了那些IExtRenderListener回调方法的含义,所以本质上这里剩下的问题是

1) 我可以从 PDF 中删除所有文本对象并将其输出到新的吗?

您可以使用来自this answer 的通用内容流编辑器类PdfContentStreamEditor。像这样简单地从中派生出来

class TextRemover : PdfContentStreamEditor
{
    protected override void Write(PdfContentStreamProcessor processor, PdfLiteral operatorLit, List<PdfObject> operands)
    {
        if (!TEXT_SHOWING_OPERATORS.Contains(operatorLit.ToString()))
        {
            base.Write(processor, operatorLit, operands);
        }
    }
    List<string> TEXT_SHOWING_OPERATORS = new List<string> { "Tj", "'", "\"", "TJ" };
}

并像这样使用它

using (PdfReader pdfReader = new PdfReader(source))
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(dest, FileMode.Create, FileAccess.Write), (char)0, true))
{
    pdfStamper.RotateContents = false;
    PdfContentStreamEditor editor = new TextRemover();

    for (int i = 1; i <= pdfReader.NumberOfPages; i++)
    {
        editor.EditPage(pdfStamper, i);
    }
}

将从即时页面内容流中删除所有文本绘制指令,例如对于我使用的示例 PDF

它创建以下输出:

注意,如上所述,只有直接的页面内容流会发生变化。要获得完整的解决方案,还必须将TextRemover 应用于页面的 XObjects 和 Patterns,并且递归地如此。

【讨论】:

    猜你喜欢
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    • 2013-04-30
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 2012-02-04
    相关资源
    最近更新 更多