Можно ли удалить текстовые объекты из существующего PDF-файла и вывести его в новый PDF-файл с помощью iTextSharp? - PullRequest
0 голосов
/ 06 января 2019

Этот вопрос является еще одной версией моего старого вопроса: Я хочу получить все объекты, кроме текстового объекта в виде изображения из PDF, используя iTextSharp

Оригинальный вопрос

Я разрабатываю программу для преобразования PDF в PPTX по определенным причинам с использованием iTextSharp. Пока что я сделал, чтобы получить все текстовые объекты и графические объекты и местоположения. Но мне трудно получить векторные рисунки без текстов (например, таблиц). На самом деле было бы лучше, если бы я мог получить их в виде изображений. Мой план состоит в том, чтобы объединить все объекты, кроме текстовых, в качестве фонового изображения и разместить текстовые объекты в нужных местах. Я пытался найти подобные вопросы здесь, но безуспешно. Если кто-нибудь знает, как сделать эту конкретную работу, пожалуйста, ответьте. Спасибо.


Я читал много связанных вопросов и обсуждений и решил задать другую версию здесь. У меня осталось два плана следующим образом. Я был бы очень признателен, если бы разработчики / эксперты iText могли направлять меня.

Фрагмент кода, который я использую для получения объектов текста / изображения

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 для получения информации о пути является правильным способом?

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

Полагаю, @mkl, @Amine, @Bruno Lowagie могут мне помочь. Заранее спасибо.

1 Ответ

0 голосов
/ 07 января 2019

В моем ответе на ваш старый вопрос Я объяснил значения этих IExtRenderListener методов обратного вызова, так что, по сути, оставшийся вопрос здесь

1) Можно ли удалить все текстовые объекты из PDF-файла и вывести его на новый?

Вы можете использовать класс редактора потока общего контента 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 я использовал

original

создает следующий вывод:

all text removed

Остерегайтесь , как сказано выше, только непосредственные потоки содержимого страницы изменяются. Для полного решения нужно применить TextRemover также к XObjects и Patterns страниц, и рекурсивно так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...