Как с помощью php и ImageMagick разбить PDF на отдельные листы

Столкнулся с небольшой, но интересной задачкой – необходимо разбить PDF-файл, который состоит из нескольких страниц, на отдельные листы. Разобрать pdf необходимо так, чтобы каждый ее лист стал картинкой. Задачка не часто встречается, поэтому про нее стоит написать заметку, вдруг кому-нибудь еще пригодится.

Как с помощью ImageMagick разбить PDF на страницы

Для этой задачи отлично подходит программа ImageMagick, которая в основном используется для работы с графикой. ImageMagick установлена по умолчанию, практически, на всех хостингах. А если не установлена, то служба поддержки без проблем может ее добавить для вашего сайта. Если же у вас не хостинг, а свой сервер, то можете сами добавить программу, это занимает всего пару минут.
После того, как программа установлена, достаточно всего одной команды, чтобы разбить pdf на отдельные страницы:

  1. // Разбить всю PDF на отдельные листы
  2. convert test.pdf -quality 100 page-%3d.png
  3. // Взять только вторую страницу из PDF
  4. convert test.pdf[1] -quality 100 page-2.png


Разбивка PDF с помощью ImageMagick в php

Работать с ImageMagick в php так же просто, как и через консоль. Но есть несколько нюансов, про которые стоит упомянуть.
При обращении к файлам, лучше использовать абсолютный путь. Относительные пути к файлам не всегда определяются ImageMagick и часто вылетают ошибки. Для указания полного пути к файлу удобно использовать константу __DIR__.
Второе. При сохранении картинок в формате jpeg качество листов сильно отличается от оригинала. Даже если задавать максимальное качество и отключать оптимизацию, то искажения картинок все равно видны на глаз. Лучше сохранять в формате png, тогда качество листов-картинок будет, как в исходном файле.
Третий важный момент заключается в том, что если PDF не имеет заданного фона, то png картинки будут создаваться с прозрачностью. Если прозрачность не нужна, то нужно ее отключить перед сохранением картинки. Сделать это можно с помощью флага setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE).
Далее приведен код разбивки PDF на отдельные листы. Каждая строка прокомментирована, чтобы было проще понять логику.

  1. // полный путь к PDF
  2. $pdf = __DIR__ . "/test.pdf";
  3. // открытие PDF
  4. $im = new imagick($pdf);
  5. // определение количества листов в PDF
  6. $count_pages = $im->getNumberImages();
  7. // если есть хотя бы один лист
  8. if ($count_pages) {
  9. for ($i = 0; $i < $count_pages; $i++) {
  10. // вытаскиваем одну страницу
  11. // номер страницы(от 0 до $count_pages)
  12. $page = $pdf.'['.$i.']';
  13. // создание холста из одной страницы PDF
  14. $image = new Imagick($page);
  15. // формат картинок
  16. $image->setImageFormat("png");
  17. // отключение прозрачности, чтобы пустые места на картинках страниц стали белыми
  18. $image->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
  19. // качества картинок(0-100)
  20. $image->setImageCompressionQuality(100);
  21. // сохранение картинки с именем НОМЕР-page.png
  22. $image->writeImage(__DIR__."/".($i+1).'-page.png');
  23. }
  24. }


Как с помощью php вытащить один лист PDF
Не всегда нужно разбирать всю PDF на отдельные страницы. Чтобы взять одну конкретную страницу, не обязательно разбивать всю пдф на листы и выбирать требуемый. Можно сразу вытащить нужный лист. Код примера приведен ниже, в нем из всего PDF-файла извлекается только вторая страница.
  1. // вытащить одну страницу
  2. // нумерация страниц начинается с нуля
  3. $pdf = __DIR__ . "/test.pdf";
  4. $page = $pdf.'[1]'; // [1] - номер страницы
  5. $image = new Imagick($page);
  6. $image->setImageFormat("png");
  7. $image->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
  8. $image->setImageCompressionQuality(100);
  9. $image->writeImage(__DIR__."/2-page.png");


Послесловие
Во всех примерах pdf конвертировалось в png картинки. Но листы можно сохранить и в формате pdf. Ниже приведен пример кода.
  1. // Сохранить одну страницу в формате pdf
  2. // Путь к pdf и в квадратных скобках номер страницы
  3. // Нумерация страниц начинается с нуля
  4. $page = __DIR__ . "/test.pdf[1]";
  5. $image = new Imagick($page);
  6. $image->setImageFormat("pdf");
  7. $image->setImageCompressionQuality(100);
  8. $image->writeImage(__DIR__."/2-page.pdf");


  31.05.24 / 22:46 | PHP |   175 | 6   0