Perpanjangan perpustakaan PDFRW yang luar biasa yang menambahkan penanganan aliran konten (dan semua objek yang dirujuk di dalamnya, misalnya gambar, font dll.) Sambil menjaganya sesederhana mungkin.
Jadi, mengapa memperluas PDFRW ketika ada pustaka PDF penuh seperti PYPDF? Pikirkan seperti ini: Sebagian besar perpustakaan PDF mencoba menyediakan fungsi yang menyederhanakan tugas pemrosesan PDF umum. Perpustakaan ini sangat baik dalam apa yang mereka lakukan, tetapi sesekali tugas muncul yang membutuhkan fungsi baru. Sekarang, jika Anda seorang pengembang yang berada dalam situasi seperti itu, Anda harus mulai menggali sejumlah besar kode sumber perpustakaan ini.
Pendekatan PDFRW berbeda: mari kita purf sebanyak mungkin, sambil menjaga hasilnya sesederhana mungkin. Bukan ide yang buruk, terutama mengingat fakta bahwa model objek PDF (yang hanya sekelompok kamus dengan beberapa nilai mereka menjadi referensi ke kamus lain) sangat cocok untuk pemetaan ke kamus Python standar. On top of that, pdfrw implements an idea behind another wonderful package attrdict to make traversing PDF objects even simpler: accessing page fonts, for example, can now be done like this:
for fontName , fontDict in page . Resources . Font . items ():
( do something )Langkah selanjutnya adalah mencoba mengurai aliran kamus-ini adalah entri khusus dalam kamus yang berisi hal-hal menarik: teks, gambar, grafik vektor dll. PDFRW tidak melakukan semua itu, dan tidak dilakukan dengan sengaja: sesuai dengan filosofi seperti Unix, ia melakukan apa yang dilakukan dengan sangat baik, dan tidak melakukan sedikit tambahan. Struktur data yang dihasilkannya lengkap: berisi semua PDF, cukup untuk setiap tugas pemrosesan yang mungkin. And it is simple enough so the developer could start coding right away, spending more time enjoying the passages in the Adobe's magnum opus, and none — learning another complicated library. Dan, pada kenyataannya, PDFRW adalah alat yang ideal untuk membantu mempelajari sintaks PDF dengan bermain dengannya!
Oke, jika Anda sampai pada titik ini maka kemungkinan Anda bertanya -tanya: Jadi, ke mana saya pergi dari sini? Secara khusus: Bagaimana cara mengurai aliran kamus? Di sinilah PDFRWX dapat membantu: Ini dapat menguraikan aliran kamus dan melakukan hal -hal bermanfaat lainnya. Tapi hal pertama yang pertama:
PDFRWX Pertama dan terpenting mencoba untuk tetap dengan filosofi PDFRW yang diuraikan di atas. Untuk ini menambahkan pengamatan bahwa dalam banyak tugas pemrosesan PDF sebagian besar waktu dihabiskan untuk mengembangkan solusi perangkat lunak, dan tidak menjalankannya. Ini mengarah pada pilihan desain:
Sekarang kita siap untuk melihat apa yang dilakukan PDFRWX dan bagaimana hal itu mencapainya:
Berikut contoh/contoh-pdfstream.py yang membaca contoh.pdf, menghapus semua konten teks dari setiap halaman dan menulis hasilnya ke 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 ()As you can see, the code runs over pages, then over contents of every page, then uncompresses the contents, as it may be compressed, then parses the contents stream into a tree, removes the BT/ET text blocks, and then parses the resulting tree back to stream. The meaning of each line of code above should be clear apart from, possibly, the toArray lambda function: it's there because a page in PDF can have more than one Contents dictionary, in which case page.Contents is a PdfArray, and each of its elements has to be processed separately. And so, the toArray lambda function makes the situation with page contents more uniform by turning page.Contents that are not arrays into PdfArray with one element.
Beberapa hal lain juga harus dicatat. Pertama, perhatikan bahwa untuk menyetujui tugas ini, kode hanya menggunakan dua kelas baru dari PDFRWX : PDFFILTER dan PDFStream, dengan satu/dua panggilan fungsi dari masing -masing. Kedua, pohon parsed saya hanya daftar python standar bersarang dari format sepele berikut:
[
['q', []],
['cm', ['1','0','0','1','0','0']],
...
['BT', [], [ /a tree list of text operators/ ]],
...
['Q', []]
]
Jadi, setiap daun (elemen) dari daftar pohon itu sendiri merupakan daftar elemen 2 atau 3: dua elemen pertama adalah perintah dan daftar argumen (daftar kosong jika perintah tidak memiliki argumen), sedangkan argumen opsional ketiga hadir dalam kasus di mana daun merupakan blok perintah, dalam hal ini adalah daftar pohon dari perintah yang membentuk blok. By design, there are just two types of blocks: the BT/ET text block, which uses command name 'BT' in the parsed tree, and the BI/ID/EI inline image block, which uses the command name 'BI' in the parsed tree. Perhatikan, bahwa dalam aliran PDF asli hanya ada urutan perintah; Parser PDFStream yang membuat blok -blok ini dalam outputnya untuk kenyamanan. Untuk lebih membiasakan diri dengan struktur output parser stream, coba masukkan perintah seperti pprint (Treein) tepat setelah panggilan ke parser.
Note also that the toArray function, however useful, has not been implemented in the module, and so you have to code it every time you do the parsing. Ini mungkin terdengar aneh, tetapi ini adalah hasil dari prinsip -prinsip desain yang sama: modul ini hanya mem -parsing aliran; Terserah pengembang untuk membuat kode yang lainnya.
The PdfStream parser class is implemented in pure Python using just about 300 lines of code with the help of the popular (and pure Python!) SLY parser generator library by David Beazley — check out his lectures on YT, he is terrific! Untuk penasaran: parser menggunakan dua status parser (yaitu dua parser berbeda dengan tata bahasa berbeda yang beralih di antara mereka sendiri saat mereka beroperasi), satu untuk parsing string literal PDF (yaitu string yang ada dalam tanda kurung), dan yang lainnya - untuk yang lainnya. Yep, in order for the literal strings to support encoding parentheses as part of the string the format of the PDF literal strings has been made so intricate that it required a separate parser just to parse those. So, if for some reason (speed?) you will ever want to implement the stream parser using another parser generator library make sure it supports a stack for parser states.
Memecahkan neraka font. Dokumen segera hadir, nantikan.
Filter yang Didukung:
Bosan dengan bug produk Adobe sendiri ketika datang ke akurasi warna dalam ekspor gambar? Kemudian Anda datang ke tempat yang tepat! Bertujuan untuk menjadi kelas manipulasi gambar PDF yang paling akurat. Dokumen segera hadir, nantikan.
Codec yang didukung (Encode/Decode):
Ruang warna yang didukung:
Plus:
Modul ini sangat dapat digunakan saat ini, dan telah dijalankan melalui banyak tes untuk memastikan hal itu melakukan apa yang dijanjikan untuk dilakukan dengan benar. Namun itu sama sekali tidak dekat Alpha: Antarmuka belum sepenuhnya selesai. Selain itu, penanganan kesalahan rusak (mungkin akan segera diperbaiki dan dibuat mirip dengan bagaimana kesalahan ditangani dalam PDFRW ). Jadi, bermain dengan risiko Anda sendiri Tidak ada risiko, jangan berharap itu kualitas produksi.