Расширение замечательной библиотеки PDFRW, которая добавляет обработку потоков контента (и все ссылки на них объекты, например, изображения, шрифты и т. Д.) При сохранении его как можно просты.
Итак, зачем расширять PDFRW , когда есть полноценные библиотеки PDF, такие как PYPDF? Подумайте об этом таким образом: большинство библиотек PDF пытаются предоставить функции, которые упрощают общие задачи обработки PDF. Эти библиотеки очень хороши в том, что они делают, но время от времени возникает задача, которая требует новой функции. Теперь, если вы разработчик, который находится в такой ситуации, вы должны начать копаться в больших количествах исходного кода этих библиотек.
Подход PDFRW отличается: давайте разыгрываем PDF как можно больше, сохраняя при этом результат максимально простым. Не плохая идея, особенно учитывая тот факт, что модель объекта PDF (которая является всего лишь кучкой словарей, причем некоторые из их ценностей являются ссылками на другие словарные), очень хорошо подходит для картирования со стандартными словарными платами Python. Вдобавок ко всему, PDFRW реализует идею еще одного замечательного атрикта пакета, чтобы упростить обходные объекты PDF еще проще: например, доступ к страницам, например, теперь можно сделать так:
for fontName , fontDict in page . Resources . Font . items ():
( do something )Следующим шагом является попытка проанализировать потоки словаря-это специальные записи в словари, которые содержат интересные вещи: текст, изображения, векторная графика и т. Д. PDFRW ничего из этого не делает, и это не делает это в целях: в соответствии с его UNIX-подобной философией, он делает то, что делает очень хорошо, и не делает немного больше. Структура данных, которую он создает, завершена: она содержит весь PDF, достаточно для любой возможной задачи обработки. И это достаточно просто, чтобы разработчик мог сразу же начать кодировать, тратя больше времени на то, чтобы насладиться отрывками в Magnum Opus Adobe, и ни один из них - изучая еще одну сложную библиотеку. И, на самом деле, PDFRW является идеальным инструментом, чтобы помочь изучить синтаксис PDF, играя с ним!
Хорошо, если вы добрались до этого момента, скорее всего, вам интересно: Итак, куда мне пойти отсюда? В частности: как проанализировать потоки словаря? Именно здесь PDFRWX может помочь: он может проанализировать потоки словаря и делать другие полезные вещи. Но на первый взгляд:
PDFRWX в первую очередь пытается сохранить философию PDFRW , изложенную выше. К этому он добавляет наблюдение, что во многих задачах обработки PDF большую часть времени тратится на разработку программного решения, а не на его запуск. Это приводит к выбору дизайна:
Теперь мы готовы увидеть, что делает PDFRWX и как это достигает:
Вот примеры/example-pdfstream.py , который читает example.pdf, удаляет весь текстовый содержимое с каждой страницы и записывает результат на example-out.pdf:
from pdfrw import PdfReader , PdfWriter , PdfArray
from pdfrwx . pdffilter import PdfFilter
from pdfrwx . pdfstreamparser import PdfStream
toArray = lambda obj : obj if isinstance ( obj , PdfArray )
else PdfArray ([ obj ]) if obj != None else PdfArray ()
pdfIn = PdfReader ( 'example.pdf' )
pdfOut = PdfWriter ( 'example-out.pdf' )
for page in pdfIn . pages :
contentsArray = toArray ( page . Contents )
for contents in contentsArray :
stream = PdfFilter . uncompress ( contents ). stream
treeIn = PdfStream . stream_to_tree ( stream )
treeOut = []
for leaf in treeIn :
cmd , args = leaf [: 2 ]
if cmd != 'BT' : treeOut . append ( leaf )
contents . stream = PdfStream . tree_to_stream ( treeOut )
contents . Filter = None
pdfOut . addPage ( page )
pdfOut . write ()Как вы можете видеть, код запускается по страницам, затем над содержимым каждой страницы, а затем не расстраивает содержимое, так как его можно сжать, затем анализирует содержимое потока в дерево, удаляет текстовые блоки BT/ET, а затем анализирует полученное дерево обратно в поток. Значение каждой строки кода, выше, должно быть ясным, кроме, возможно, функции Toarray Lambda: она есть, потому что страница в PDF может иметь более одного словаря содержимого, в этом случае страница. Итак, функция Toarray Lambda делает ситуацию с содержанием страницы более равномерной, поворачивая страницу. Контента, которые не являются массивами в Pdfarray с одним элементом.
Необходимо также отметить несколько других вещей. Во -первых, обратите внимание, что для выполнения задачи код использует только два новых класса из PDFRWX : PDFFILTER и PDFSTREAM, с одной/двух вызовами функции из каждой. Во -вторых, проанализированное дерево Я просто вложенный стандартный список Python следующего тривиального формата:
[
['q', []],
['cm', ['1','0','0','1','0','0']],
...
['BT', [], [ /a tree list of text operators/ ]],
...
['Q', []]
]
Таким образом, каждый лист (элемент) списка деревьев сам по себе является списком из 2 или 3 элементов: первые два элемента - это команда и список аргументов (пустой список, если у команды нет аргументов), в то время как третий необязательный аргумент присутствует в случае, когда лист представляет собой блок команд, и в этом случае это список деревьев команд, которые составляют блок. По дизайну существует только два типа блоков: текстовый блок BT/ET, в котором используется имя команды «Bt» в разыгрываемом дереве, и встроенный блок изображения BI/ID/EI, в котором используется имя команды «Bi» в проанализированном дереве. Обратите внимание, что в исходном PDF -потоке есть только последовательность команд; Это анализатор PDFStream, который создает эти блоки в своем выходе для удобства. Чтобы дополнительно ознакомиться со структурой вывода анализатора потока, попробуйте вставить такую команду, как pprint (treein) сразу после вызова для анализатора.
Также обратите внимание, что функция Toarray , какими бы полезна не была реализована в модуле, и поэтому вам приходится кодировать ее каждый раз, когда вы делаете анализ. Это может показаться странным, но это результат тех же принципов дизайна: модуль просто анализирует поток; Разработчик зависит от разработчика.
Класс анализаторов PDFSTEAM реализован в Pure Python с использованием всего около 300 строк кода с помощью популярной (и чистого питона!) Библиотеки генератора Sly Parser от Дэвида Бизли. Посмотрите его лекции о YT, он потрясающий! Для любопытного: синтаксический анализатор использует два состояния синтаксического анализатора (то есть два разных анализатора с разными грамматиками, которые переключаются между собой во время работы), одно для анализа буквальных строк PDF (то есть строк, которые находятся в скобках), а другое - для всего остального. Да, для того, чтобы буквальные строки поддерживали скобки кодировки как часть струны, формат буквальных строк PDF был сделан настолько сложным, что ему потребовалось отдельный анализатор, чтобы разобрать их. Так что, если по какой -то причине (скорость?) Вы когда -нибудь захотите реализовать анализатор потока, используя другую библиотеку генераторов анализатора, убедитесь, что он поддерживает стек для состояний анализатора.
Решает ал шрифтов. Документы скоро появятся, следите за обновлениями.
Поддерживаемые фильтры:
Устали от собственных ошибок продуктов Adobe, когда дело доходит до точности в экспорте изображения? Тогда вы пришли в нужное место! Целью быть самым точным классом манипуляции с изображением PDF. Документы скоро появятся, следите за обновлениями.
Поддерживаемые кодеки (Encode/Decode):
Поддерживаемые цветные пространства:
Плюс:
Модуль в настоящее время используется в настоящее время, и проходил множество тестов, чтобы убедиться, что он делает то, что он обещает правильно. Однако это никоим образом не находится рядом с Альфа: интерфейсы еще не полностью завершены. Более того, обработка ошибок нарушена (вероятно, будет исправлена в ближайшее время и сделана аналогично тому, как ошибки обрабатываются в PDFRW ). Так, Играйте на свой риск Без риска, просто не ожидайте, что он пока будет качества производства.