Вопрос или проблема
Мне нужно обработать несколько PDF-файлов. Задача состоит в том, чтобы заменить один заданный файл изображения на другой. Моя первая проблема заключается в том, как заменить изображение в PDF через командную строку в пакетной обработке. Затем я постараюсь решить другие проблемы, такие как то, как определить, какое изображение мне нужно заменить (потому что в PDF-файлах может быть больше одного изображения). Но сначала я хочу решить первую проблему: как заменить изображение в PDF на другое.
Я прочитал о poppler-utils и pdftk, но насколько я знаю, ни один из этих инструментов не позволяет заменять изображения в PDF.
Хорошо… Я думаю, что здесь недостает pdflatex
.
Автор вопроса сказал, что он рассматривал poppler-utils
и pdftk
. Позвольте мне добавить к этому pdfimages
. Эти инструменты вместе с pdflatex
являются частями решения.
pdfimages -f 4 -l 20 -j -png target.pdf imageroot
В приведенном выше примере код pdfimages
просматривает страницы с 4 по 20 в target.pdf
и извлекает все изображения в файлы с именами, начинающимися с imageroot
.
poppler-utils
предоставляет pdftotext
. Я рекомендую использовать параметр -layout
, который отлично сохраняет документ в читабельном виде.
pdftotext -layout $1.pdf $1.txt
Возражение автора вопроса против решения imagemagick
, предложенного pidosaurus, заключается в том, что изображение не имеет извлекаемого текста. Используя утилиты, которые я описал, автор вопроса теперь будет иметь все изображения, а также весь извлеченный текст, и номера страниц и содержание сохраняются благодаря параметру -layout
. Автор может определить правильную страницу текста и вставить его в файл .tex
, который заканчивается директивой %includegraphics
и ссылается на заменяемое изображение по имени файла. Затем вы используете pdflatex
и получаете новый одностраничный .pdf, который можно вставить в остальную часть вашего документа с помощью pdftk
. Если вы знаете, где в тексте оригинальной страницы находилось изображение, вы можете использовать %includegraphics [h]
и поместить изображение в точно нужное место.
Если вам достаточно простого python-скрипта, то решение простое с помощью библиотеки pdfrw.
Простой рабочий пример:
#!/bin/python
import pdfrw
# Читаем пример файла pdf, который был загружен с:
# https://getsamplefiles.com/download/pdf/sample-3.pdf
reader = pdfrw.PdfReader('sample-3.pdf')
# Открываем новый файл изображения, который был загружен с:
# https://www.picserver.org/assets/library/2020-10-31/originals/example1.jpg
with open('example1.jpg', 'rb') as f:
# Перезаписываем нужное изображение в оригинальной структуре pdf.
reader.Root.Pages.Kids[0].Resources.XObject['/X9'].stream = f.read().decode('latin')
# Записываем измененный pdf файл.
pdfrw.PdfWriter('sample-3_out.pdf', trailer=reader).write()
Использованы примерные файлы с здесь (pdf) и здесь (jpg).
Найти правильный элемент изображения в структуре pdf может быть немного сложно, но есть очень полезный инструмент для инспекции структуры pdf под названием pdfalyzer.
Используйте pdfalyze с флагом -t для древовидного представления или -r для расширенного древовидного представления, например так:
pdfalyze --maximize-width -r sample-3.pdf | less -R
Как я узнал, /Filter /DCTDecode
в структуре pdf означает данные изображения jpg, а /Filter /FlateDecode
означает сжатые данные gzip. Может быть несколько фильтров для потока данных, и существует больше фильтров, чем эти двое.
Чтобы немного прояснить, у вас есть огромный набор .pdf файлов и список названий изображений в некоторых из этих файлов, которые необходимо заменить, но вам нужен быстрый способ найти каждое изображение, которое нужно заменить, не открывая каждый .pdf файл в каталоге?
Если бы я оказался на вашем месте и не смог бы выделить достаточно времени для поиска/разработки кода, я бы попробовал некоторые пакетные процессы в Inkscape. Это просто первая мысль, но…
- Сделайте копию всех pdf файлов, с которыми вы работаете.
- Откройте pdf в Inkscape и используйте команду Преобразовать/Масштабировать, чтобы уменьшить размеры (и уменьшить размер файла). Проверьте, насколько малым вы можете сделать страницу pdf и при этом распознавать изображения.
- Используйте пакетную команду, чтобы преобразовать / изменить размер всех pdf в скопированном каталоге. Возможно, вы также сможете использовать пакетный процесс для включения какого-либо вида оптимизации изображений или другого процесса для уменьшения каждого размера файла.
- Откройте группу из 20 или около того за раз в Inkscape (перетаскивайте и бросайте?), и визуально просмотрите изображения, которые необходимо заменить.
- Нажимая на pdf в Inkscape, вы должны получить имя файла или определить его на основании его расположения по порядку, а затем открыть и заменить изображения в оригинальном файле.
В худшем случае: рутинная работа = время для подкаста.
Существует ряд потенциальных проблем при замене изображений в PDF. Это может быть легко в одних случаях и трудно в других.
Что нам известно, так это то, что мы не знаем, состоит ли существующее изображение из нескольких изображений (что более распространено, чем вы могли ожидать). Однако давайте оставим это на данный момент и просто предположим, что мы заменяем одно изображение на другое.
Это также поднимает необходимость исследования, но снова предположим, что мы хотим заменить одно данное изображение с тем же соотношением.
В этом случае это может быть так же просто, как одна команда для замены и, возможно, другая для извлечения для редактирования.
Например, скажем, у нас есть шаблонное изображение, которое мы хотим перезаписать и вернуть на страницу PDF. Мы можем сделать что-то подобное, используя pdfcpu.
Сначала нам нужно знать номер изображения, которое нужно заменить.
pdfcpu images list cert.pdf
pages: all
cert.pdf:
1 images available (1.2 MB)
Page Obj# │ Id │ Type SoftMask ImgMask │ Width │ Height │ ColorSpace Comp bpc Interp │ Size │ Filters
━━━━━━━━━━┿━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━┿━━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━━┿━━━━━━━━━━━━
1 6 │ FXX1 │ изображение │ 3508 │ 2480 │ DeviceRGB 3 8 │ 1.2 MB │ FlateDecode
Ограничение на данный момент (может измениться в будущем?) состоит в том, что новое изображение должно соответствовать исходной ширине и высоте 3508 px X 2480 px
, иначе в этом случае оно будет отклонено.
pdfcpu images update cert.pdf recert.png recert.pdf 6
writing recert.pdf...
optimizing...
Обратите внимание, что мы можем заменить источник высококачественного растрового изображения на JPEG и тем самым гарантировать, что файл будет меньше за счет небольшой потери качества.
pdfcpu images update cert.pdf recert.jpg recert.pdf 6
writing recert.pdf...
optimizing...
Если вы хотите извлечь изображение для редактирования, используйте сначала:
pdfcpu images extract [-p(ages) selectedPages] -- inFile outDir
Ответ или решение
Замена изображения в PDF с помощью командной строки на русском языке
Заменить изображение в PDF-файле с помощью командной строки может показаться сложной задачей, но с использованием подходящих инструментов это можно сделать эффективно и даже в пакетном режиме. В этом ответе мы рассмотрим основные шаги, включая выбор инструмента, процесс замены изображения и другие важные моменты.
Шаг 1: Выбор инструмента
Существует несколько инструментов, которые могут помочь в замене изображений в PDF:
- pdfrw – это библиотека Python, которая позволяет редактировать PDF-файлы. Она проста в использовании и позволяет заменять изображения.
- pdfcpu – мощный инструмент для работы с PDF, который позволяет извлекать, редактировать и заменять изображения прямо из командной строки.
- pdfimages из
poppler-utils
– полезен для извлечения изображений из PDF-файлов. - ImageMagick – также может быть использован для обработки изображений, но его применение может быть не всегда оптимальным для работы с PDF.
Шаг 2: Извлечение изображения
Перед заменой изображения необходимо знать, какое именно изображение требуется заменить. Используем pdfimages
для извлечения изображений из PDF:
pdfimages -f 1 -l 10 source.pdf image
Эта команда извлечет все изображения с первой по десятую страницу и сохранит их с именами, начинающимися на "image".
Шаг 3: Замена изображения
Использование pdfrw
Если вы решили использовать библиотеку pdfrw
, вот простой пример Python-скрипта. Этот скрипт заменяет изображение в PDF:
#!/bin/python
import pdfrw
# Чтение исходного PDF файла
reader = pdfrw.PdfReader('source.pdf')
# Открытие нового изображения, которое будет заменять старое
with open('new_image.jpg', 'rb') as f:
# Замена изображения в первой странице (может потребоваться изменить индексы)
reader.Root.Pages.Kids[0].Resources.XObject['/X1'].stream = f.read()
# Запись измененного PDF файла
pdfrw.PdfWriter('output.pdf', trailer=reader).write()
Шаг 4: Подбор правильного изображения
Чтобы найти, какое именно изображение нужно заменить, можно использовать pdfcpu
для анализа структуры PDF:
pdfcpu images list source.pdf
Эта команда выведет список изображений с их атрибутами, включая размеры. Убедитесь, что новое изображение соответствует размеру оригинального.
Шаг 5: Обновление и сохранение PDF
Для замены изображения с помощью pdfcpu
, используйте следующую команду, указав номер изображения, которое нужно заменить:
pdfcpu images update source.pdf new_image.jpg output.pdf <image_number>
Заключение
Замена изображений в PDF через командную строку может быть довольно простой задачей, если использовать правильные инструменты. Выбор инструмента зависит от вашего предпочтения и объема работ. Для пакетной обработки вы можете написать скрипт, который будет автоматизировать процесс извлечения и замены изображений. Не забывайте проверять соответствие размеров изображений и учитывать возможные исключения.
Если у вас есть много PDF-файлов и вам нужно заменить изображения в них, использование скриптов и командной строки может значительно сэкономить ваше время и усилия.