В этой заметке рассмотрим установку Ghostscript и конвертацию PDF файлов в JPG, напишем скрипт для массовой конвертации.
В примерах я буду использовать FreeBSD, но решение подойдет для любой платформы, главное обращайте внимание на пути.
Ghostscript — мультиплатформенное решение, дистрибутивы есть для всех основных платформ: Linux, BSD, MacOS и Windows.
По работе приходится сталкиваться с файлами формата PDF.
И их различной обработкой:
- Уменьшение размера
- Конвертации в растровый формат
- Объединением (Merge)
- Извлечением определенных страниц (Extract)
- Конвертацией в архивный формат PDF/A
Для этого есть всем известный продукт компании Adobe — Adobe Acrobat Pro и в рамках компании логично его использование, да он платный.
Но… Acrobat не предполагает какой-либо автоматизации, в отличии к примеру программ: Adobe PhotoShop в которой есть Actions, inDesign — где есть возможность писать свои скрипты на VBA(Windows Only), JavaScript.
Вообщем мне абсолютно не понятно — почему в продукт, который позиционируется как Профессиональный (Pro) производитель не добавил интерфейс CLI.
Поэтому приходится строить свои велосипеды:)
Установим:
FreeBSD:
# cd /usr/ports/print/ghostscript9-agpl-base/ && make install clean
Ubuntu:
sudo apt-get install ghostscript
CentOS:
sudo yum install ghostscript.x86_64
MacOS:
Вначале нужно установить Homebrew (пакетный менеджер), делаем все в терминале (Command+Space вбиваем Terminal, жмем Enter)
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/null brew install ghostscript
Windows:
Качаем со страницы https://www.ghostscript.com/download/gsdnld.html И устанавливаем
Проверим установку:
gs -v GPL Ghostscript 9.52 (2020-03-19) Copyright (C) 2020 Artifex Software, Inc. All rights reserved.
Базовая команда конвертации PDF в JPG:
gs -dBATCH -dNOPAUSE -dSAFER -sDEVICE=jpeg -dPDFFitPage=true -dFIXEDMEDIA -sOutputFile=/home/vladimir/pdfs/test.jpg /home/vladimir/jpgs/test.pdf
Получаем на выходе JPG с разрешением в 72 DPI, возможно для каких-то целей (Preview на сайте к примеру) этот файл подойдет, а мы с вами повысим разрешение, добавив соответствующий аргумент -r:
gs -dBATCH -dNOPAUSE -dSAFER -sDEVICE=jpeg -dPDFFitPage=true -dFIXEDMEDIA -r300 -sOutputFile=/home/vladimir/pdfs/test.jpg /home/vladimir/jpgs/test.pdf
Уже лучше, выходной jpg файл имеет разрешение в 300DPI, но хочется еще лучше:), добавим параметр качества сжатия JPG -dJPEGQ=100:
gs -dBATCH -dNOPAUSE -dSAFER -sDEVICE=jpeg -dPDFFitPage=true -dJPEGQ=100 -dFIXEDMEDIA -r300 -sOutputFile=/home/vladimir/pdfs/test.jpg /home/vladimir/jpgs/test.pdf
Какие еще ключи можно добавить:
- -sPAPERSIZE= (размер формата: A1-A4 и т.п., формат legal — выведет в правильной пропорции)
- -gwidthxheight (размер вывода в px, пример: -g240X400)
Это все хорошо, но строка вызова получается достаточно длинной, для частого использования, давайте создадим скрипт которому на вход мы будем давать два аргумента:
- Путь до файла PDF
- Путь до выходного файла, имя файла будет браться с имени PDF
Создадим скрипт:
vi ~pdf2jpg.sh
#!/bin/sh #Определим в переменную запуск Ghostscript со всеми нужными нам ключами pdf2jpg="gs -dBATCH -dNOPAUSE -dSAFER -sDEVICE=jpeg -r300 -dPDFFitPage=true -dJPEGQ=100 -sPAPERSIZE=legal -dFIXEDMEDIA -sOutputFile=" # Сделаем проверку на наличие двух обязательных аргументов if [ ! -n "$1" ] || [ ! -n "$2" ] then echo -e "Пожалуйста укажите входной файл PDF и директорию для сохранения jpg файла \nПример: $0 /indir/test.pdf /outdir/" else # Прибавим к выходной директории имя файла из PDF и заменим расширения на .jpg filename=${2}`basename ${1%.*}`.jpg # Запустим конвертацию ${pdf2jpg}${filename} ${1} # Вывод полного пути до jpg файла echo "Файл сохранен:" ${filename} fi
Сохраняем, делаем исполняемым:
chmod +x ~pdf2jpg.sh
Проверим:
~pdf2jpg.sh temp/test_marvins.pdf temp/jpg/ GPL Ghostscript 9.52 (2020-03-19) Copyright (C) 2020 Artifex Software, Inc. All rights reserved. This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY: see the file COPYING for details. Processing pages 1 through 1. Page 1 Файл сохранен: temp/jpg/test_marvins.jpg
Все вроде хорошо, но если потребуется преобразовать сотню файлов?
Давайте накидаем по быстрому скрипт пакетной обработки, смысл такой же, как и в предыдущем скрипте.
Будем передавать два аргумента: входная директория и директория для JPG (если указать одинаковые директории, то jpg файлы будут сохранены вместе с PDF).
Создаем скрипт:
vi ~pdfs2jpgs.sh
#!/bin/sh #Определим в переменную запуск Ghostscript со всеми нужными нам ключами, добавим ключ -q (для "тихого вывода") pdf2jpg="gs -dBATCH -dNOPAUSE -dSAFER -sDEVICE=jpeg -r300 -dPDFFitPage=true -dJPEGQ=100 -sPAPERSIZE=legal -dFIXEDMEDIA -q -sOutputFile=" # Сделаем проверку на наличие двух обязательных аргументов if [ ! -n "$1" ] || [ ! -n "$2" ] then echo -e "Пожалуйста укажите входной файл PDF и директорию для сохранения jpg файла \nПример: $0 /indir/ /outdir/" else #т.к. ниже будет функция, определим в переменные входную и выходную директорию input=${1} output=${2} #Объявим функцию pdfs2jpgs() { # Обойдем в цикле for входную директорию и файлы с расширением pdf for file in ${input}*.pdf; do #Определим в переменную выходную директорию с именем jpg файла jpgname=${output}`basename ${file%.*}`.jpg # Запустим конвертацию файлов ${pdf2jpg}${jpgname} ${file} #Сделаем вывод, что и куда сохранилось echo "Convert file:" ${file}", save as:" ${jpgname} done } # Вызовем функцию pdfs2jpgs fi
Сохраняем, делам файл исполняемым:
chmod +x ~pdfs2jpgs.sh
Проверим работу скрипта:
~pdfs2jpgs.sh /home/vladimir/temp/ /home/vladimir/temp/jpg/ Convert file: /home/vladimir/temp/001.pdf, save as: /home/vladimir/temp/jpg/001.jpg Convert file: /home/vladimir/temp/002.pdf, save as: /home/vladimir/temp/jpg/002.jpg Convert file: /home/vladimir/temp/003.pdf, save as: /home/vladimir/temp/jpg/003.jpg Convert file: /home/vladimir/temp/004.pdf, save as: /home/vladimir/temp/jpg/004.jpg Convert file: /home/vladimir/temp/005.pdf, save as: /home/vladimir/temp/jpg/005.jpg Convert file: /home/vladimir/temp/006.pdf, save as: /home/vladimir/temp/jpg/006.jpg Convert file: /home/vladimir/temp/007.pdf, save as: /home/vladimir/temp/jpg/007.jpg Convert file: /home/vladimir/temp/008.pdf, save as: /home/vladimir/temp/jpg/008.jpg Convert file: /home/vladimir/temp/009.pdf, save as: /home/vladimir/temp/jpg/009.jpg Convert file: /home/vladimir/temp/010.pdf, save as: /home/vladimir/temp/jpg/010.jpg Convert file: /home/vladimir/temp/011.pdf, save as: /home/vladimir/temp/jpg/011.jpg Convert file: /home/vladimir/temp/012.pdf, save as: /home/vladimir/temp/jpg/012.jpg
Все корректно работает при одностраничном PDF файле.
Давайте модифицируем скрипт, для обработки многостраничных файлов PDF:
vi ~pdfs2jpgs.sh
#!/bin/sh # Сделаем проверку на наличие двух обязательных аргументов if [ ! -n "$1" ] || [ ! -n "$2" ] then echo -e "Пожалуйста укажите входной файл PDF и директорию для сохранения jpg файла \nПример: $0 /indir/ /outdir/ Дополнительные ключи: 200 - разрешение в dpi -r - многостраничный документ (необходимо указать полный путь до файла) Пример: $0 /indir/test.pdf /outdir/ 300 -r" exit fi #т.к. ниже будет функция, определим в переменные входную и выходную директорию input=${1} output=${2} #Установим разрешение по умолчанию в 72dpi res="" # Если в третьем аргументе указано разрешение выходного файла # вносим значение в переменную $res if [ -n "${3}" ] then res="-r${3}" fi #Определим в переменную запуск Ghostscript со всеми нужными нам ключами, добавим ключ -q (для "тихого вывода") pdf2jpg="gs -dBATCH -dNOPAUSE -dSAFER -sDEVICE=jpeg ${res} -dPDFFitPage=true -dJPEGQ=100 -sPAPERSIZE=legal -dFIXEDMEDIA -q -sOutputFile=" # Если в четвертом аргументе установлен ключ -r #- считаем, что делаем многостраничный документ #здесь же его обрабатываем и выходим if [ "${4}" == "-r" ] then jpgname=${2}`basename ${input%.*}`"_%02d.jpg" ${pdf2jpg}${jpgname} ${input} exit fi #Объявим функцию pdfs2jpgs() { # Обойдем в цикле for входную директорию и файлы с расширением pdf for file in ${input}*.pdf; do #Определим в переменную выходную директорию с именем jpg файла jpgname=${output}`basename ${file%.*}`.jpg # Запустим конвертацию файлов ${pdf2jpg}${jpgname} ${file} #Сделаем вывод, что и куда сохранилось echo "Convert file:" ${file}", save as:" ${jpgname} done } # Вызовем функцию pdfs2jpgs
Теперь скрипт может обрабатывать многостраничный PDF — ключ -r (первым аргументом необходимо указать полный путь до файла).
На выходе мы получим JPG файлы с именем — namepdffile_01.jpg, где префикс _01 — указывает на номер страницы.
Так же четвертым аргументом можно указать выходное разрешение, если не указывать, то jpg файлы будут иметь разрешение в 72dpi.
Пример использования:
- Рекурсивная обработка одностраничных PDF файлов с разрешением в 300dpi — ./pdfs2jpgs.sh /indir/ /outdir/ 300
- Обработка единичного многостраничного PDF файла с разрешением в 200dpi — ./pdfs2jpgs.sh /indir/test.pdf /outdir/ 300 -r
На этом все, есть вопросы и пожелания — пишите комментарии:)