Материал из Eludia.
| Эта заметка не претендует на энциклопедичность. Она не отличается ни широтой охвата, ни строгостью формулировок. Это просто записочка на память. |
Содержание |
В этой заметке перечислен ряд сведений, которые могут оказаться полезными при работе с данными в формате PDF в WEB-приложениях. Здесь нет никакой специфики, связанной с Eludia.pm, однако упоминаются некоторые Perl-модули. Часть описанных решений может быть доступной не на всех программных платформах.
Общие соображения
Формат PDF занимает странное, так сказать, промежуточное положение между чисто бинарными (скажем, MS Word 97) и чисто текстовыми (как HTML). С одной стороны, он использует человекочитаемые текстовые инструкции ("начать страницу", "отобразить вот тут такой-то графический примитив"), с другой — там имеются не просто бинарные вставки ("потоки"), но и бинарные прошивки (текстовое оглавление, где номерам разделов сопоставляются сдвиги от начала файла, измеряемые в байтах).
Кроме того, текст и графика должны быть полностью привязаны к координатам на "электронной бумаге" на этапе генерации (в противоположность HTML, который графически обсчитывается во время показа). В частности, автор должен сам заботиться о переносах строк и разбиении на страницы.
Таким образом, нет никакой возможности напрямую генерировать по интерполируемым шаблонам PDF с (потенциально) длинными текстовыми вставками и произвольными изображениями. Неизбежно придётся применять некоторые специальные средства.
Таковые имеются и решают многие практические задачи, однако рано или поздно Вам всё же может понадобиться непосредственное знакомство со спецификацией формата. На момент написания этого текста актуальная версия доступна всем желающим за 380 швейцарских франков, однако, к счастью, в архиве достаточно полные документы имеются и в свободном доступе.
Сборка PDF
Несколько забегая вперёд, представим замечательный инструмент для работы с PDF: pdftk. В описании заявлено, что это "[анти]степлер для электронной бумаги". И действительно, при помощи pdftk необычайно легко как собрать один PDF из нескольких готовых файлов, так и, наоборот, разлущить монолитный файл на страницы. Кроме того, доступно ещё множество ценных операций, в том числе прикрепление/извлечение вложений и использование одних PDF как "водяных знаков" или, наоборот, надпечаток для других.
Наличие такого инструмента делает возможной следующую стратегию генерации PDF: вначале создаются отдельные компоненты, затем они, если требуется, проходят дополнительную обработку (например, добавление водяных знаков или прикрепление вложений) и, наконец, собирается итоговый файл. Описанный процесс может спровоцировать ощутимую задержку, по ходу которой стоит развлечь пользователя показом прогресс-индикатора.
Perl-модуль PDF::Reuse повторяет некоторые (к сожалению, далеко не все) функции pdftk. Впрочем, у него есть возможности, которые в pdftk отсутствуют: скажем, включение в PDF-документ JPEG-файла или вставка низкоуровневых PDF-команд. Однако это уже скорее относится к теме следующего раздела.
Генерация PDF
Создавать отдельные PDF-страницы можно с помощью вышеупомянутого PDF::Reuse или других подходящих Perl-модулей (PDF::API2, CAM::PDF). При использовании любого из них для создания документов с более-менее сложным форматированием придётся серьёзно разбираться с геометрией.
Однако есть отличный способ получить на выходе корректно нарезанный PDF, с правильно смасштабированными иллюстрациями, оглавлением, нумерацией страниц и прочими книгоиздательскими прелестями, самостоятельно сформировав всего лишь HTML по шаблону: это HTMLDOC.
Замечания о HTMLDOC
Используя HTMLDOC в пакетном режиме из-под mod_perl, не забудьте про строку
$ENV {HTMLDOC_NOCGI} = 1;
(иначе он будет считать себя запущенным как cgi-bin и не получит нужных параметров).
Кроме того, если вы применяете HTMLDOC для генерации файлов без оглавления, то есть в вашем HTML нет ни одного тега H1, H2,... то во избежание ошибки используйте параметр
--webpage
Работа с изображениями
JPEG
Растровые изображения представляются в PDF-файлах бинарными участками, каждый из которых превращается в 2-мерный массив пикселей, будучи распакован по определённому алгоритму или, выражаясь языком спецификации, "с применением одного из фильтров". Один из этих фильтров — DCTDecode — реализует алгоритм, заложенный в стандарт JPEG. Поэтому JPEG-файлы могут включаться в PDF практически открытым текстом, что используется несложными модулями типа вышеупомянутого PDF::Reuse.
Зачастую имеет смысл наладить массовое преобразование иллюстраций из разнообразных графических форматов в JPEG. Если Вы используете HTMLDOC, то с форматами BMP, GIF, и PNG проблем не возникнет, но, скажем, TIFF будет недоступен. У PDF::API2 свои ограничения по форматам (можно TIFF, но нельзя BMP), CAM::PDF вообще читает картинки только из других PDF-файлов.
В любом случае приятно, что есть такой пакет, как ImageMagick, утилита convert из которого осуществляет преобразования между несколькими десятками форматов растровой графики (и это её использование практически вхолостую, поскольку вообще-то она представляет собой пакетный фотошоп).
При использовании PDF::Reuse нелишне помнить, что его процедура prJPEG корректно обрабатывает только файлы с палитрой RGB. Что можно компенсировать следующим образом:
`convert -colorspace RGB $file_in $file_out`
Замечание об ImageMagick
Может показаться странным, что здесь рекомендуется внешний вызов пакетной утилиты в то время, как у ImageMagick есть полнофункциональный Perl API PerlMagick. Однако не стоит забывать, что ImageMagick — весьма объёмная библиотека, так что если Вы не используете её в большинстве запросов, то действительно стоит потерять немного времени на вызов стороннего процесса, но существенно сэкономить при этом оперативную память.
CCITT-факсы
Другой "фильтр" в PDF — CCITTFaxDecode — соответствует алгоритму, используемому при факсимильной связи. Факсовые аппараты могут сохранять сообщения в специальных форматах (.c3 .c4), однако для совместимости с большинством графических пакетов обычно применяется один из вариантов TIFF.
Если Вам требуется преобразовать такой TIFF в PDF-документ (то есть привести факс к "электронной бумаге"), Вы, конечно, можете, как было описано выше, сначала преобразовать его ImageMagick'ом в доступный растровый формат, а потом воспользоваться одним из модулей для создания PDF. Но именно для факса такой PDF окажется чрезмерно объёмным.
В этом конкретном случае гораздо эффективнее воспользоваться утилитой tiff2pdf.
TIFF от Microsoft Office Document Imaging
Не все TIFF — то, чем они кажутся. Сканирование документа с использованием Microsoft Office Document Imaging даёт на выходе файл с расширением .tif, который может быть прочтён и отображён как TIFF мало какой графической утилитой.
По счастью, какая-то добрая душа из отдела спецрасследований ВВС США выпустила утилитку foremost, которая позволяет выбить ценные данные даже из таких файлов.
Конкретно для TIFF означенного вида на выходе получается директория, содержащая, в частности, отчёт (output/audit.txt) и поддиректорию с JPEG-файлами (output/jpg). Среди JPEG полноразмерные изображения чередуются с previews, но на фоне всего пройденного это уже не смотрится как проблема.
Разное
В отношении файлов-вложений в PDF Adobe Reader ведёт себя в точности как почтальон Печкин: "ZIP-то я вам принёс, только открыть я его вам не дам. И сохранить тоже". ZIP — не единственный, а просто самый вопиющий пример дискриминированного типа файлов.
Обращаться к Edit / Preferences / Trust Manager'у бессмысленно: не положено — и всё тут. Но, как выясняется, заполучить нужный документ до смешного просто: зайти в Registry по ключу (8.0 — версия Reader'а, у кого 9.0 — поменять соответственно).
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Adobe\Acrobat Reader\8.0\FeatureLockdown\cDefaultLaunchAttachmentPerms
и покопаться в содержимом tBuiltInPermList. Там постфикс ":3" соответствует полному запрещению, его можно поменять на ":1".

