Получить расположение (X, Y, ширина, высота) изображений в PDF с помощью ITextSharp - PullRequest
0 голосов
/ 14 декабря 2018

У меня есть проблема: нарисовать прямоугольник, чтобы покрыть все изображения в PDF.Я уже знаю, что изображение может быть записано как изображение, но оно также может быть записано как графические векторы.

Я хочу получить местоположения (X, Y, Ширина, Высота) нормальных изображений (сохраненных, например, какрастровое изображение) и нарисуйте прямоугольник поверх них, чтобы не покрывать другие элементы на странице, например текст под этим изображением (я не хочу охватывать всю страницу, если изображение занимает только 30% от нее).До сих пор я написал две функции для получения изображений:

  public List<Image> GetImagesFromPdf(string path)
    {
        List<Image> imageList = new List<Image>();
        PdfReader reader = new PdfReader(path);
        for (int i=1;i<reader.NumberOfPages;i++)
        {
            PdfDictionary pdfDict = reader.GetPageN(i);
            imageList.AddRange(GetImagesFromDocument(pdfDict, reader));
        }
        return imageList;
    }

private List<Image> GetImagesFromDocument(PdfDictionary dict, PdfReader doc)
    {
        List<Image> imageList = new List<Image>();
        PdfDictionary resources = (PdfReader.GetPdfObject(dict.Get(PdfName.RESOURCES))) as PdfDictionary;
        PdfDictionary objects = (PdfReader.GetPdfObject(resources.Get(PdfName.XOBJECT))) as PdfDictionary;
        if (objects != null)
        {
            foreach (PdfName objKey in objects.Keys)
            {
                PdfObject obj = objects.Get(objKey);
                if (obj.IsIndirect())
                {
                    PdfDictionary tg = (PdfDictionary)(PdfReader.GetPdfObject(obj));
                    PdfName objectType = (PdfName)(PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE)));
                    if (
                            PdfName.IMAGE.Equals(objectType) 
                            ||PdfName.IMAGEB.Equals(objectType) 
                            || PdfName.IMAGEC.Equals(objectType) 
                            || PdfName.IMAGEI.Equals(objectType)
                        )
                    {
                        int xrefIdx = ((PRIndirectReference)obj).Number;
                        PdfObject pdfObj = doc.GetPdfObject(xrefIdx);
                        PdfStream str = (PdfStream)(pdfObj);

                        iTextSharp.text.pdf.parser.PdfImageObject pdfImage =
                            new iTextSharp.text.pdf.parser.PdfImageObject((PRStream)str);
                        System.Drawing.Image img = pdfImage.GetDrawingImage();

                        imageList.Add(img);
                    }
                    else if (PdfName.FORM.Equals(objectType) || PdfName.GROUP.Equals(objectType))
                    {
                        imageList.AddRange(GetImagesFromDocument(tg, doc));
                    }
                }
            }
        }
        return imageList;
    }

Я вызываю функцию GetImagesFromPdf, а затем для каждой страницы я запускаю функцию: GetImagesFromDocument.Это приводит к правильному количеству изображений в pdf, но я действительно не знаю, как получить местоположения (X, Y, Ширина, Высота) .... Что-нибудь еще, что я могу использовать?Или я должен использовать другой механизм для этого?

Любая помощь будет оценена.PS.я кое-что заметил ... Я также попытался реализовать интерфейс IExtRenderListener и заметил, что при наличии изображения в pdf вызывается функция RenderImage.Есть одна функция, которую я могу вызвать на объекте renderInfo, и результат инстерецирует, я получаю эти значения (функция называется GetImageCTM ()):

The function is called GetImageCTM()

Когда я пытался покрыть изображения, записанные в виде графических векторов, у меня не получилось.Ни одно изображение не было покрыто, но я получил около 15 000 очень маленьких прямоугольников, к сожалению, ни один не был виден.Я использовал этот код:

  public void ModifyPath(PathConstructionRenderInfo renderInfo)
    {
        if (renderInfo.Operation == PathConstructionRenderInfo.RECT)
        {
            float x = renderInfo.SegmentData[0];
            float y = renderInfo.SegmentData[1];
            float w = renderInfo.SegmentData[2];
            float h = renderInfo.SegmentData[3];
            Vector a = new Vector(x, y, 1).Cross(renderInfo.Ctm);
            Vector b = new Vector(x + w, y, 1).Cross(renderInfo.Ctm);
            Vector c = new Vector(x + w, y + h, 1).Cross(renderInfo.Ctm);
            Vector d = new Vector(x, y + h, 1).Cross(renderInfo.Ctm);

            Rectangle rect = new Rectangle(x,y,x+w, y+h); //is that correct ?
        }
        else
        {
            for (int i = 0; i < renderInfo.SegmentData.Count - 1; i += 2)
            {
                float x = renderInfo.SegmentData[i];
                float y = renderInfo.SegmentData[i + 1];
                Vector a = new Vector(x, y, 1).Cross(renderInfo.Ctm);
              //  Rectangle rect = new Rectangle(x, y, x + ..., y + ...); What to do here ?
            }
        }
        modifyPathCounter++;
    }

ОК, его уже решили, решение здесь:

 if (renderInfo.Operation == PathConstructionRenderInfo.RECT)
        {
            float x = renderInfo.SegmentData[0];
            float y = renderInfo.SegmentData[1];
            float w = renderInfo.SegmentData[2];
            float h = renderInfo.SegmentData[3];
            Vector a = new Vector(x, y, 1).Cross(renderInfo.Ctm);
            Vector b = new Vector(x + w, y, 1).Cross(renderInfo.Ctm);
            Vector c = new Vector(x + w, y + h, 1).Cross(renderInfo.Ctm);
            Vector d = new Vector(x, y + h, 1).Cross(renderInfo.Ctm);

            Rectangle rect = new Rectangle(a[0],a[1],c[0], c[1]); 
            //SquaresToDraw image = new SquaresToDraw(0, rect.Left, rect.Bottom, rect.Right, rect.Top);
          //  squaresToDraw.Add(image);
        }
        else
        {
            if (renderInfo.SegmentData!=null)
            {
                for (int i = 0; i < renderInfo.SegmentData.Count - 1; i += 2)
                {
                    float x = renderInfo.SegmentData[i];
                    float y = renderInfo.SegmentData[i + 1];
                    Vector a = new Vector(x, y, 1).Cross(renderInfo.Ctm);
                    Rectangle rect = new Rectangle(x, y, a[0], a[1]); 
                    SquaresToDraw image = new SquaresToDraw(0, rect.Left, rect.Bottom, rect.Right, rect.Top);
                      squaresToDraw.Add(image);
                                                                      //  Rectangle rect = new Rectangle(x, y, x + ..., y + ...); What to do here ?
                }
            }

        }

1 Ответ

0 голосов
/ 15 декабря 2018

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

Но ваш IExtRenderListener подход - это действительно ваш путь.И ваше наблюдение верно, ImageCtm - это матрица, представляющая аффинное преобразование, примененное к исходному изображению по сравнению с квадратом 1x1 в начале координат.

Просто примените это преобразование к углам квадрата единицы 1x1 дляполучить углы изображения на вашей странице.

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