Столкнулся с небольшой, но интересной задачкой – необходимо разбить PDF-файл, который состоит из нескольких страниц, на отдельные листы. Разобрать pdf необходимо так, чтобы каждый ее лист стал картинкой. Задачка не часто встречается, поэтому про нее стоит написать заметку, вдруг кому-нибудь еще пригодится.
Как с помощью ImageMagick разбить PDF на страницы
Для этой задачи отлично подходит программа ImageMagick, которая в основном используется для работы с графикой. ImageMagick установлена по умолчанию, практически, на всех хостингах. А если не установлена, то служба поддержки без проблем может ее добавить для вашего сайта. Если же у вас не хостинг, а свой сервер, то можете сами добавить программу, это занимает всего пару минут.
После того, как программа установлена, достаточно всего одной команды, чтобы разбить pdf на отдельные страницы:
// Разбить всю PDF на отдельные листы convert test.pdf -quality 100 page-%3d.png
// Взять только вторую страницу из PDF 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 на отдельные листы. Каждая строка прокомментирована, чтобы было проще понять логику.
// полный путь к PDF $pdf = __DIR__ . "/test.pdf"; // открытие PDF $im = new imagick($pdf); // определение количества листов в PDF $count_pages = $im->getNumberImages(); // если есть хотя бы один лист if ($count_pages) { for ($i = 0; $i < $count_pages; $i++) { // вытаскиваем одну страницу // номер страницы(от 0 до $count_pages) $page = $pdf.'['.$i.']'; // создание холста из одной страницы PDF $image = new Imagick($page); // формат картинок $image->setImageFormat("png"); // отключение прозрачности, чтобы пустые места на картинках страниц стали белыми $image->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE); // качества картинок(0-100) $image->setImageCompressionQuality(100); // сохранение картинки с именем НОМЕР-page.png $image->writeImage(__DIR__."/".($i+1).'-page.png'); } }
Как с помощью php вытащить один лист PDF
Не всегда нужно разбирать всю PDF на отдельные страницы. Чтобы взять одну конкретную страницу, не обязательно разбивать всю пдф на листы и выбирать требуемый. Можно сразу вытащить нужный лист. Код примера приведен ниже, в нем из всего PDF-файла извлекается только вторая страница.
// вытащить одну страницу // нумерация страниц начинается с нуля $pdf = __DIR__ . "/test.pdf"; $page = $pdf.'[1]'; // [1] - номер страницы $image = new Imagick($page); $image->setImageFormat("png"); $image->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE); $image->setImageCompressionQuality(100); $image->writeImage(__DIR__."/2-page.png");
Послесловие
Во всех примерах pdf конвертировалось в png картинки. Но листы можно сохранить и в формате pdf. Ниже приведен пример кода.
// Сохранить одну страницу в формате pdf // Путь к pdf и в квадратных скобках номер страницы // Нумерация страниц начинается с нуля $page = __DIR__ . "/test.pdf[1]"; $image = new Imagick($page); $image->setImageFormat("pdf"); $image->setImageCompressionQuality(100); $image->writeImage(__DIR__."/2-page.pdf");