iTextSharp Read Text From Single Layer of PDF

孤者浪人 提交于 2021-02-08 06:32:06

问题


Currently I am using a custom LocationTextExtractionStrategy to extract text from a PDF that returns a TextRenderInfo[]. I would like to be able to determine if a TextRenderInfo object (or PDFString, child of TextRenderInfo) appears in a specific layer. I am not sure if this is possible. To get the layers in a PDF, I am using:

Dictionary<string,PdfLayer> layers;
using (var pdfReader = new PdfReader(src))
{
    var newSrc = Path.Combine(["new file location"]);
    using (var stream = new FileStream(newSrc, FileMode.Create))
    {       
        PdfStamper stamper = new PdfStamper(pdfReader, stream);
        layers = stamper.GetPdfLayers();
        stamper.Close();
    }
    pdfReader.Close();
    src = newSrc;
}

To extract the text, I am using:

var textExtractor = new TextExtractionStrategy();
PdfTextExtractor.GetTextFromPage(pdfReader, pdfPageNum,textExtractor);
List<TextRenderInfo> results = textExtractor.Results;

Is there any way that I can check if the individual TextRenderInfo results exist within the layers obtained in the first code snippet. Any help would be much appreciated.


回答1:


It is possible to get the contents from a single layer, but you'll have to jump through a few hoops to work it out. Specifically, you will have to recreate some of the logic that is provided by the PdfTextExtractor and PdfReaderContentParser.

public static String GetText(PdfReader reader, int pageNumber, int streamNumber) {
    var strategy = new LocationTextExtractionStrategy();
    var processor = new PdfContentStreamProcessor(strategy);

    var resourcesDic = pageDic.GetAsDict(PdfName.RESOURCES);

    // assuming you still need to extract the page bytes
    byte[] contents = GetContentBytesForPageStream(reader, pageNumber, streamNumber);

    processor.ProcessContent(contents, resourcesDic);
    return strategy.GetResultantText();
}

public static byte[] GetContentBytesForPageStream(PdfReader reader, int pageNumber, int streamNumber) {
    PdfDictionary pageDictionary = reader.GetPageN(pageNum);
    PdfObject contentObject = pageDictionary.Get(PdfName.CONTENTS);
    if (contentObject == null)
        return new byte[0];

    byte[] contentBytes = GetContentBytesFromContentObject(contentObject, streamNumber);
    return contentBytes;
}

public static byte[] GetContentBytesFromContentObject(PdfObject contentObject, int streamNumber) {
    // copy-paste logic from
    // ContentByteUtils.GetContentBytesFromContentObject(contentObject);
    // but in case PdfObject.ARRAY: only select the streamNumber you require
}

If you're specifically looking to just use PdfTextExtractor or PdfReaderContentParser, and ask the returned TextRenderInfo for the layer it's on, then I'm not sure it will be easily possible. There are a number of problems with that:

  • TextRenderInfo doesn't store that information, so you'd have to subclass it (which is possible)
  • you'd have to rewrite the logic that creates the TextRenderInfo objects. This is possible by registering custom IContentOperator objects for all text operators (Tj, TJ, ' and ") with the PdfTextExtractor or PdfReaderContentParser
  • the hardest part is that you have already lost layer information in ContentByteUtils.GetContentBytesFromContentObject - so you'd need to retain that somehow, which creates its own set of problems.


来源:https://stackoverflow.com/questions/49262618/itextsharp-read-text-from-single-layer-of-pdf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!