Преобразование PDF в PNG
На этой неделе передо мной стала новая задача — из PDF сделать картинку вменяемого формата — JPG, PNG или GIF.
Задача на первый взгляд достаточно тривиальная и часто встаёт в самых разнообразных проектах. Обычно конвертируют только первую страницу — для создание превью PDF на php. Моя задача несколько отличалась — дать возможность клиентам скачивать платёжные документы не только в общепринятом PDF, но и формате обычной картинки.
Первое же решение, которое я нашёл погуглив, оказалось с серьёзным изъяном. Но давайте по-порядку.
Imagick
При слове «конвертация» на ум сразу приходит пакет ImageMagick и его реализация для php — Imagick. Точнее это обёртка над консольной утилитой convert. Imagick документирован средне, но при желании разобраться достаточно не сложно.
Вот и решение, очень простое и понятное:
-
<?php
-
$obPdf = new Imagick( ‘act.pdf[0]‘ ); #Открываем наш PDF и указываем обработчику на первую страницу
-
$obPdf->setImageColorspace(255); #устанавливаем цветовую палитру
-
$obPdf->setCompression(Imagick::COMPRESSION_JPEG); #Устанавливаем компрессор
-
$obPdf->setCompressionQuality(60); #И уровень сжатия
-
$obPdf->setImageFormat(‘jpeg’); #С форматом не заморачиваемся — пусть будет JPEG.
-
#При необходимости сделать превью ресайзим изображение
-
$obPdf->resizeImage(250, 250, imagick::FILTER_LANCZOS, 1);
-
#Ну и конечно же пишем в jpg-файл.
-
$obPdf->writeImage(‘act_preview.jpg’);
-
$obPdf->clear();
-
$obPdf->destroy();
-
?>
Решение действительно хорошее и в целом с задачей справляется. Но в моём случаем возникли проблемы со шрифтами. Хотя в pdf был зашит Times New Roman, стандартный даже для *nix-осей шрифт, картинка получилась корявая, шрифт расползся из-за чрезмерного кернинга — расстояния между буквами были в хороших 5 пикселей.
Я потратил на копание в настройках иксов, convert, imagick, ghostscript и прочих частей преобразовательного хозяйства почти целый день, но кроме локализации проблемы сделать ничего не удалось. Устройство ImageMagick’a — тема отдельной статьи, которая появится в ближайшее время. Пока же вывод печален — пришлось переключится на поиски другого решения.
XPDF
После непродолжительных поисков была найдена замена — пакет xpdf, который тут же завёлся прямо из репозитария debian:
-
sudo apt-get install xpdf
Пакет содержит целый ряд утилит и прямо после установки я воспользовался простой командой:
-
pdftoppm act.pdf -png /path/to/image
И на выходе получил чудесный, прекрасно конвертированный файл формата pdf и разрешения в полторы сотни dpi. Правда c названием image-1.png — но это не беда. Утилита прописывает номер страницы файла в постфиксе имени.
Собственно pdftoppm изначально преобразовывала в формат ppm (Portable Bitmap — немного пожатый аналог bmp), но мне не хотелось возится с промежуточным файлом и использованием ppmtojpeg. Выручил ключ «-png». По мануалам в сети он отсутствует, но мой баш подсказал, что ключик есть.
Дальнейшее было делом техники.
-
<?php
-
$realFileName = ‘/uploads/act.pdf’;
-
$fileName = ‘/path/to/preview/act’;
-
$fileName .= ‘-1.png’;#Добавляем постфикс к имени-пути файла
-
LL(‘File’)->createFileFromReal(‘file1′, $fileName);
