Python + PyPdf: обрезать область страницы и вставить ее на другую страницу

Допустим, у вас есть страница в формате PDF с различными сложными элементами внутри. Цель состоит в том, чтобы обрезать область страницы (чтобы извлечь только один из элементов), а затем вставить ее на другую страницу PDF.

Python + PyPdf: обрезать область страницы и вставить ее на другую страницу

Вот упрощенная версия моего кода:

import PyPDF2
import PyPdf

def extract_tree(in_file, out_file):
    with open(in_file, 'rb') as infp:
        # Read the document that contains the tree (in its first page)
        reader = pyPdf.PdfFileReader(infp)
        page = reader.getPage(0)

        # Crop the tree. Coordinates below are only referential
        page.cropBox.lowerLeft = [100,200]
        page.cropBox.upperRight = [250,300]

        # Create an empty document and add a single page containing only the cropped page
        writer = pyPdf.PdfFileWriter()
        writer.addPage(page)
        with open(out_file, 'wb') as outfp:
            writer.write(outfp)

def insert_tree_into_page(tree_document, text_document):
    # Load the first page of the document containing 'text text text text...'
    text_page = PyPDF2.PdfFileReader(file(text_document,'rb')).getPage(0)

    # Load the previously cropped tree (cropped using 'extract_tree')
    tree_page = PyPDF2.PdfFileReader(file(tree_document,'rb')).getPage(0)

    # Overlay the text-page and the tree-crop   
    text_page.mergeScaledTranslatedPage(page2=tree_page,scale='1.0',tx='100',ty='200')

    # Save the result into a new empty document
    output = PyPDF2.PdfFileWriter()
    output.addPage(text_page)
    outputStream = file('merged_document.pdf','wb')
    output.write(outputStream)



# First, crop the tree and save it into cropped_document.pdf
extract_tree('document1.pdf', 'cropped_document.pdf')

# Now merge document2.pdf with cropped_document.pdf
insert_tree_into_page('cropped_document.pdf', 'document2.pdf')

Метод "extract_tree", кажется, работает. Он генерирует файл PDF, содержащий только обрезанную область (в примере дерево). Проблема в том, что когда я пытаюсь вставить дерево в новую страницу, то звезда и дом исходного изображения все равно вклеиваются

Как вы определили границы обрезки деревьев? Любые примеры PDF-файлов, на которые вы можете указать? Я предполагаю, что кадрирование все еще захватывает эти изображения.

Edeki Okoh 26.02.2019 19:06

Привет, Эдеки... Код, который я разместил, является упрощенной версией моего кода. Я реализовал интерфейс для определения границ урожая, но в приведенном выше коде я жестко закодировал некоторые случайные значения в качестве ссылки. Я почти уверен, что проблема не в границах, потому что файл "cropped_document.pdf" кажется идеально обрезанным, но когда я пытаюсь объединить его с целевой страницей, обрезка игнорируется и вставляется вся страница (вместо только обрезать). Я предполагаю, что, может быть, я неправильно понимаю цель урожая Box

caspillaga 26.02.2019 19:14

Попробуйте сохранить само обрезанное изображение и не использовать писатель.addPage(страница). Похоже, что этот метод добавляет страницу в существующий PDF-файл, но вы все еще вызываете страницу 1 PDF-файла в функции insert_tree. Но обрезанное изображение находится на второй странице из-за этого метода, поэтому оно также объединит дом и звезду.

Edeki Okoh 26.02.2019 19:22

В качестве примера я использовал исследовательскую работу, содержащую график (пример: arxiv.org/pdf/1807.03819.pdf). Я обрезал график, а затем попытался наложить его в произвольном месте первой страницы.

caspillaga 26.02.2019 19:26

Внес правку в свой предыдущий комментарий. Обрезанное изображение находится на странице 1 или странице 2 файлаcropped_document.pdf? Я думаю, что проблема может заключаться в использовании write.addPage(page) и выполнении слияния на первой странице документа с помощью getPage(0).

Edeki Okoh 26.02.2019 19:28

В моем примере кода я предполагаю, что все файлы PDF имеют только одну страницу. Writer.addPage(page) добавляет страницу в новый пустой документ, поэтому у него будет только одна страница. Как сохранить само обрезанное изображение без write.addPage(page)?

caspillaga 26.02.2019 19:30

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

Edeki Okoh 26.02.2019 19:34

Спасибо Эдеки. Я добавил дополнительные комментарии к коду, чтобы сделать его более понятным

caspillaga 26.02.2019 19:39

Давайте продолжить обсуждение в чате.

Edeki Okoh 26.02.2019 19:44

Просто на случай, если это кому-то поможет: в итоге я обрезал области PDF, затем преобразовал в формат SVG, затем обратно в PDF и, наконец, объединил. Это решило мою проблему. Я предполагаю, что в этом случае pypdf2 редактирует только метаданные страницы, а не фактическое содержимое, поэтому нежелательные области сохраняются и снова появляются при окончательном слиянии. Вместо этого SVG сохраняет только нужный регион и отбрасывает остальные. Единственное неудобство в том, что текст больше не редактируется, так как он будет преобразован в векторные рисунки, но в моем случае это не было проблемой.

caspillaga 23.02.2021 14:47
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
10
3 221
2

Ответы 2

Я попробовал кое-что, что действительно сработало. Попробуйте преобразовать свой первый вывод (pdf, содержащий только дерево) в docx, а затем преобразовать его еще раз из docx в pdf, прежде чем объединять его с другими страницами pdf. Это будет работать (только дерево будет объединено).

Разрешите спросить, как вы реализовали интерфейс, определяющий границы кропа Au.

У меня была точно такая же проблема. В конце концов, решение для меня состояло в том, чтобы внести небольшую правку в исходный код pyPDF2 (из этот пул реквест, который так и не попал в основную ветку). Что вам нужно сделать, так это вставить эти строки в метод _mergePage класса PageObject внутри файла pdf.py:

page2Content = ContentStream(page2Content, self.pdf)
page2Content.operations.insert(0, [map(FloatObject, [page2.trimBox.getLowerLeft_x(), page2.trimBox.getLowerLeft_y(), page2.trimBox.getWidth(), page2.trimBox.getHeight()]), "re"])
page2Content.operations.insert(1, [[], "W"])
page2Content.operations.insert(2, [[], "n"])

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

from PyPDF2 import PdfFileReader, PdfFileWriter

tree_page = PdfFileReader(open('document1.pdf','rb')).getPage(0)
text_page = PdfFileReader(open('document2.pdf','rb')).getPage(0)

tree_page.cropBox.lowerLeft = [100,200]
tree_page.cropBox.upperRight = [250, 300]

text_page.mergeScaledTranslatedPage(page2=tree_page, scale='1.0', tx='100', ty='200')
output = PdfFileWriter()
output.addPage(text_page)
output.write(open('merged_document.pdf', 'wb'))

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

Другие вопросы по теме