Извлеките изображение и его название из pdf, используя iTextSharp - PullRequest
2 голосов
/ 16 марта 2019

Я использую iTextSharp c # для извлечения изображений и их имени из каталога pdf. Я могу извлечь изображения из PDF, но борюсь с извлечением соответствующего имени изображения в соответствии с приложенным снимком экрана и сохранить файл с этим именем. Пожалуйста, найдите код ниже и дайте мне знать ваши предложения. Образец PDF : https://docdro.id/PwBsNR9

Код:

private static List<System.Drawing.Image> ExtractImages(String PDFSourcePath)
{
    List<System.Drawing.Image> ImgList = new List<System.Drawing.Image>();

    iTextSharp.text.pdf.RandomAccessFileOrArray RAFObj = null;
    iTextSharp.text.pdf.PdfReader PDFReaderObj = null;
    iTextSharp.text.pdf.PdfObject PDFObj = null;
    iTextSharp.text.pdf.PdfStream PDFStremObj = null;

    try
    {
        RAFObj = new iTextSharp.text.pdf.RandomAccessFileOrArray(PDFSourcePath);
        PDFReaderObj = new iTextSharp.text.pdf.PdfReader(RAFObj, null);

        for (int i = 0; i <= PDFReaderObj.XrefSize - 1; i++)
        {
            PDFObj = PDFReaderObj.GetPdfObject(i);

            if ((PDFObj != null) && PDFObj.IsStream())
            {
                PDFStremObj = (iTextSharp.text.pdf.PdfStream)PDFObj;
                iTextSharp.text.pdf.PdfObject subtype = PDFStremObj.Get(iTextSharp.text.pdf.PdfName.SUBTYPE);
                if ((subtype != null) && subtype.ToString() == iTextSharp.text.pdf.PdfName.IMAGE.ToString())
                {
                }
                if ((subtype != null) && subtype.ToString() == iTextSharp.text.pdf.PdfName.IMAGE.ToString())
                {
                    try
                    {

                        iTextSharp.text.pdf.parser.PdfImageObject PdfImageObj =
                 new iTextSharp.text.pdf.parser.PdfImageObject((iTextSharp.text.pdf.PRStream)PDFStremObj);

                        System.Drawing.Image ImgPDF = PdfImageObj.GetDrawingImage();
                        ImgList.Add(ImgPDF);

                    }
                    catch (Exception)
                    {

                    }
                }
            }
        }
        PDFReaderObj.Close();
    }
    catch (Exception ex)
    {
        throw new Exception(ex.Message);
    }
    return ImgList;
}

Catalog

Ответы [ 2 ]

0 голосов
/ 19 марта 2019

К сожалению, пример PDF не помечен. Таким образом, в противном случае необходимо попытаться связать текст заголовка и изображение либо путем анализа местоположения относительно друг друга, либо путем использования шаблона в потоках контента.

В данном случае анализ местоположения относительно друг друга возможен, поскольку заголовок всегда (хотя бы частично) рисуется на соответствующем изображении или является текстом прямо под ним. Таким образом, можно в первом проходе извлечь текст с позицией со страницы, а во втором - изображения, одновременно ища заголовок в ранее извлеченном тексте в области изображения или прямо под ним. В качестве альтернативы можно сначала извлечь изображения с положением и размером, а затем извлечь текст в этих областях.

Но в потоках контента также есть определенный шаблон: титр всегда рисуется в одной инструкции рисования текста сразу после рисования соответствующего изображения. Таким образом, можно также пойти вперед и извлечь за один проход изображения и следующий нарисованный текст как связанный заголовок.

Любой подход может быть реализован с использованием API синтаксического анализатора iText. Например, в случае последнего подхода следующее: сначала реализуется слушатель рендеринга, который ведет себя так, как описано, т.е. сохраняет изображения и следующий текст:

internal class ImageWithTitleRenderListener : IRenderListener
{
    int imageNumber = 0;
    String format;
    bool expectingTitle = false;

    public ImageWithTitleRenderListener(String format)
    {
        this.format = format;
    }

    public void BeginTextBlock()
    { }

    public void EndTextBlock()
    { }

    public void RenderText(TextRenderInfo renderInfo)
    {
        if (expectingTitle)
        {
            expectingTitle = false;
            File.WriteAllText(string.Format(format, imageNumber, "txt"), renderInfo.GetText());
        }
    }

    public void RenderImage(ImageRenderInfo renderInfo)
    {
        imageNumber++;
        expectingTitle = true;

        PdfImageObject imageObject = renderInfo.GetImage();

        if (imageObject == null)
        {
            Console.WriteLine("Image {0} could not be read.", imageNumber);
        }
        else
        {
            File.WriteAllBytes(string.Format(format, imageNumber, imageObject.GetFileType()), imageObject.GetImageAsBytes());
        }
    }
}

Затем выполняется синтаксический анализ страниц документа с использованием этого обработчика визуализации:

using (PdfReader reader = new PdfReader(@"EVERMOTION ARCHMODELS VOL.78.pdf"))
{
    PdfReaderContentParser parser = new PdfReaderContentParser(reader);
    ImageWithTitleRenderListener listener = new ImageWithTitleRenderListener(@"EVERMOTION ARCHMODELS VOL.78-{0:D3}.{1}");
    for (var i = 1; i <= reader.NumberOfPages; i++)
    {
        parser.ProcessContent(i, listener);
    }
}
0 голосов
/ 16 марта 2019

Надеюсь, это поможет.Я делаю такие вещи, но если это поможет.

// existing pdf path
PdfReader reader = new PdfReader(path);
PRStream pst;
PdfImageObject pio;
PdfObject po;
// number of objects in pdf document
int n = reader.XrefSize;
//FileStream fs = null;
// set image file location
//String path = "E:/";
for (int i = 0; i < n; i++)
{
    // get the object at the index i in the objects collection
    po = reader.GetPdfObject(i);
    // object not found so continue
    if (po == null || !po.IsStream())
        continue;
    //cast object to stream
    pst = (PRStream)po;
    //get the object type
    PdfObject type = pst.Get(PdfName.SUBTYPE);
    //check if the object is the image type object
    if (type != null && type.ToString().Equals(PdfName.IMAGE.ToString()))
    {
        //get the image
        pio = new PdfImageObject(pst);
        // fs = new FileStream(path + "image" + i + ".jpg", FileMode.Create);
        //read bytes of image in to an array
        byte[] imgdata = pio.GetImageAsBytes();
        try
        {
            Stream stream = new MemoryStream(imgdata);
            FileStream fs = stream as FileStream;
            if (fs != null) Console.WriteLine(fs.Name);
        }
        catch
        {
        }
    }
}

Теперь вы можете сохранить свой поток.

public void SaveStreamToFile(string fileFullPath, Stream stream)
{
    if (stream.Length == 0) return;

    // Create a FileStream object to write a stream to a file
    using (FileStream fileStream = System.IO.File.Create(fileFullPath, (int)stream.Length))
    {
        // Fill the bytes[] array with the stream data
        byte[] bytesInStream = new byte[stream.Length];
        stream.Read(bytesInStream, 0, (int)bytesInStream.Length);

        // Use FileStream object to write to the specified file
        fileStream.Write(bytesInStream, 0, bytesInStream.Length);
     }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...