Вопрос или проблема
Самый простой способ создать PDF из изображений — это, безусловно, использовать ImageMagick:
convert --compress JPEG *.jpg out.pdf
Результаты полностью удовлетворительные: для каждого изображения есть страница в PDF, размер страницы устанавливается правильно в зависимости от размеров и разрешения.
Однако обработка нескольких сотен изображений в PDF занимает невероятно много времени, буквально часами (на сервере с 16 ГБ ОЗУ и 3 ядрами). Н Насколько я понимаю, это связано с тем, как работает ImageMagick, который каким-то образом разжимает все изображения в память (с последующей сортировкой на жесткий диск), и только после этого создает PDF из многопостраничного растрового изображения, снова сжимая все изображения (или нет, в зависимости от параметров).
В этом случае изображения уже корректны сами по себе, они JPEG, и встраивание JPEG допускается в PDF. Все, что нужно сделать, это создать оберточный PDF, по одной странице на изображение в размерах изображения и вставить на нее изображение, не касаясь данных изображения. Как программист, я быстро думаю, что могу написать инструмент для этого с помощью нескольких библиотек, но сначала хотел бы спросить:
Можно ли добиться такого же результата быстро, используя команды командной строки?
Да, imagemagick
известен своей медленностью. Попробуйте graphicsmagick
, у которого слегка более удобная командная строка, но в остальном он достаточно похож, но не обязательно использует такое же количество ОЗУ для простых задач, подобных той, что вы описали.
Для довольно быстрых конвертаций в PDF существует инструментальная цепочка mutool/mupdf:
mutool draw -o outputfilename.pdf inputfilename.jpeg
но это подходит только для конвертации изображений по одному. Однако затем вы могли бы mutool merge
их. Что-то вроде этой не протестированной конструкции:
#!/usr/bin/zsh
setopt extendedglob
counter=1
mkdir target
for file in **/*.(#i)(jpg|jpeg); do
mutool draw -o "target/$(printf '%03d' $counter).pdf" "${file}"
counter=$(( counter + 1 ))
done
mutool -o joined.pdf target/*.pdf
rm -rf target
или так
Ответ или решение
Создание PDF-документа из множества изображений в командной строке – это распространённая задача, особенно при работе с большим количеством изображений. Ваша проблема с производительностью при использовании ImageMagick хорошо известна, так как этот инструмент может потреблять значительное количество ресурсов, загружая все изображения в память. Существуют более эффективные способы выполнения этой задачи.
Одним из наиболее производительных решений является использование GraphicsMagick
, который во многом схож с ImageMagick
, но обычно работает быстрее и использует меньше памяти. Для создания PDF-документа из изображений в GraphicsMagick
можно использовать следующую команду:
gm convert -compress JPEG *.jpg out.pdf
Однако, если производительность всё ещё оставляет желать лучшего, вы можете рассмотреть использование инструмента mutool
из пакета mupdf
. Эта утилита работает быстрее при обработке изображений и позволяет создавать PDF-документы, используя уже сжатые данные JPEG.
Вот пример скрипта на zsh
, который конвертирует все изображения в папке в PDF-файлы, а затем объединяет их в один файл:
#!/usr/bin/zsh
setopt extendedglob
counter=1
mkdir target
for file in **/*.(#i)(jpg|jpeg); do
mutool draw -o "target/$(printf '%03d' $counter).pdf" "${file}"
counter=$(( counter + 1 ))
done
mutool merge -o joined.pdf target/*.pdf
rm -rf target
Пояснение кода:
- setopt extendedglob: Включает расширенное сопоставление шаблонов в
zsh
, что позволяет использовать( #i )
для нечувствительного к регистру сопоставления. - mkdir target: Создаёт временную папку
target
для хранения временных PDF-файлов. - for file in …: Для каждого файла изображения с расширением JPG или JPEG в текущем каталоге и его подкаталогах, выполняется команда
mutool draw
, которая создаёт PDF-файл из изображения. - counter: Используется для создания нумерации файлов в формате 001, 002 и так далее, что упрощает их последующее объединение.
- *mutool merge -o joined.pdf target/.pdf**: Объединяет все временные PDF-файлы в один файл
joined.pdf
. - rm -rf target: Удаляет временную папку после завершения.
Заключение
Использование mutool
для конвертации и объединения изображений в PDF является высокопроизводительным решением. Этот подход позволяет избежать значительных затрат ресурсов, связанных с загрузкой изображений в память и повторной компрессией.