Эффективный способ создания PDF из множества изображений в командной строке

Вопрос или проблема

Самый простой способ создать 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

Пояснение кода:

  1. setopt extendedglob: Включает расширенное сопоставление шаблонов в zsh, что позволяет использовать ( #i ) для нечувствительного к регистру сопоставления.
  2. mkdir target: Создаёт временную папку target для хранения временных PDF-файлов.
  3. for file in …: Для каждого файла изображения с расширением JPG или JPEG в текущем каталоге и его подкаталогах, выполняется команда mutool draw, которая создаёт PDF-файл из изображения.
  4. counter: Используется для создания нумерации файлов в формате 001, 002 и так далее, что упрощает их последующее объединение.
  5. *mutool merge -o joined.pdf target/.pdf**: Объединяет все временные PDF-файлы в один файл joined.pdf.
  6. rm -rf target: Удаляет временную папку после завершения.

Заключение

Использование mutool для конвертации и объединения изображений в PDF является высокопроизводительным решением. Этот подход позволяет избежать значительных затрат ресурсов, связанных с загрузкой изображений в память и повторной компрессией.

Оцените материал
Добавить комментарий

Капча загружается...