コンテンツにスキップ

pymupdf からの移行

pylopdf は pymupdf「風」であって、ドロップイン互換ではありません。ただし移行 コストを決めるデータ形状 — "words" タプルの並び・"dict" の構造・ search_for → list[Rect]・TOC の 1 始まりページ番号 — は pymupdf に合わせて いるため、抽出やページ操作のコードは小さな修正で移植できます。このページでは 「そのまま動くもの」「変わったもの」「あえて実装せず連携で解決するもの」を まとめます。

Note

pylopdf が扱うのは PDF のみです。pymupdf の XPS / EPUB / 画像を開く 機能は対象外です。

対応表

pymupdf pylopdf 備考
import pymupdffitz は旧名) import pylopdf
pymupdf.open(path) / open(stream=…) pylopdf.open(path) / open(stream=…) password=も同じ。UTF-8 127 byte上限
doc[i]len(doc)・イテレーション 同じ 0 始まり・負数可
doc.metadata / set_metadata 同じ キー名も同じ
page.get_text() 同じ オプションは text / words / blocks / dict
page.search_for(t) 同じ。加えてmax_hits=4096 上限付きlist[Rect]。検索語は4,096 byte、max_hits=Noneで解除、quads=は無い
page.get_pixmap(matrix=pymupdf.Matrix(2, 2)) page.get_pixmap(scale=2) dpi=144 でも。Matrix クラスは無い
pix.samples / width / height / stride / save() 同じ 常にストレートアルファ RGBA8。pylopdfの上限付きtobytes(max_size=64 MiB)とstreaming save(path)はPNGを生成し、saveには.pngが必要
page.get_images() page.get_images() 描画位置 bbox 付き。JPEG はパススルー
page.get_drawings() 同じ 型付きpath辞書。line/cubicと主要paint/stroke属性。extended=のclip/group階層は非対応
doc.rewrite_images(dpi_target=, quality=) doc.compress_images(dpi=, quality=) maskのない安全なDeviceGray/DeviceRGB DCT/Flate rasterをJPEGへ変換。dpiは最大配置を直接制限し、lossless変換は非対応
doc.selectdelete_page(s)copy_pagenew_page 同じ select の重複指定は複製になる
doc.insert_pdf(src, from_page=, to_page=, start_at=) 同じ
doc.get_toc() / set_toc() 同じ ページ番号は両者とも 1 始まり
doc.save(garbage=4, deflate=True) doc.save(garbage=True, deflate=True, object_streams=True) garbage は bool
doc.save(encryption=…, user_pw=…) doc.save(user_pw=…, owner_pw=…, permissions=…) AES-256のみ。各passwordはUTF-8 127 byte上限
doc.needs_pass / authenticate() 同じ 戻り値の意味(0/1/2/4/6)も同じ
page.rect / rotation / set_rotation 同じ
page.insert_image(rect, filename= / stream= / pixmap=, rotate=) 同じ JPEGパススルー、PNG透過、RGBA Pixmapの直接再利用、時計回りの右角回転。その他の符号化形式はPillowで変換
page.show_pdf_page(rect, src, pno) 同じ 同一文書はネイティブな編集前snapshotから取り込むため、serialize/openによる複製は不要
page.insert_text(point, text, fontsize=, fontname=, fontfile=) 同じ。加えて fontbuffer= / fontindex= sourceなしは標準14 / WinAnsi、またはpylopdf[cjk]による日本語・漢字のJP subset自動選択。その他は明示fontを字形処理してsubset埋め込み
page.insert_textbox(rect, text, align=, lineheight=) 同じ。任意の fontfile= / fontbuffer= に対応 同じJP font自動選択とUAX #14のCJK折り返し。負の戻り値なら描画しない
page.add_highlight_annot(...) 同じ 外観ストリームを常に生成
doc.embfile_add / names / get / del 同じ
doc.get_page_labels / set_page_labelspage.get_label 同じ
page.widgets() / Widget オブジェクト doc.get_form_fields() / doc.set_form_field(name, value, fontfile=) ドキュメント単位。テキスト/選択/checkbox/radioのネイティブ外観
page.get_textpage_ocr(...) page.get_text_ocr(...) / page.apply_ocr(...) pylopdf[ocr]によるオフライン純Rust PP-OCR。任意の位置付き結果にはinsert_ocr_text_layerも利用可能
pymupdf4llm.to_markdown(doc) doc.to_markdown() 内蔵・MIT

挙動の違い

  • 座標系はどちらも左上原点の表示空間。pylopdf では回転ページでも 抽出・検索・描き込み・レンダリングが一貫して同じ座標になります。
  • : Rect は不変の NamedTuplex0, y0, x1, y1 + width / height)。 Point / Matrix / Quad クラスは無く、API は素のタプルと scale= / dpi= を受けます。
  • 古い Page: 構造変更(削除・挿入・並べ替え)後に古い Page を使うと、 黙って別ページを指す代わりに StalePageError になります。doc[i] で 取得し直してください。
  • 例外: 基底は PdfErrorValueError のサブクラス)。PasswordError / DocumentClosedError / EncryptedDocumentError / StalePageError が それを細分化します。except ValueError は動き続けます。
  • 資源ポリシー: DocumentLimits.web()はrendering/extractionへ渡す完全な PDF snapshotを64 MiB、累積位置付きtextを65,536 glyph recordに制限します。 独自ポリシーではmax_interpretation_sizemax_text_glyphsを指定でき、Noneは 互換性のある無制限動作です。
  • get_text のオプションtext / words / blocks / dict のみ (html / rawdict / xml は無し)。スパン辞書は埋め込みフォントについて font と pymupdf 互換の flags(bold/italic/serif/mono)を持ちます。
  • 複数カラムのテキストは、決定的な空白ガター検出により、各カラム内を 上から下へ、カラム間を左から右へ読みます。1 em未満の狭いガターは、両側に 十分な本文を持つ行が密に反復するときだけ採用します。整列したラベル、 ドットリーダー、区切りが複数ある密な行は行優先の順序を保ちます。確定した 境界は、scan/OCR text layerの小さな水平方向のずれに追従します。
  • Page.find_tables() は線または細い塗り矩形から軸平行の罫線グリッドを 再構築し、矩形の結合セルにも対応します。strategy="text" を指定すると、 高信頼な罫線なし表を検出します(整列した複数カラム本文との幾何的な曖昧さは 残ります)。既知の表示座標領域に完全に収まる表だけを返すにはclip=を使い、 罫線なし結果の順位付けにはTable.confidence / Table.diagnosticsを確認します。
  • to_markdown() は完全な罫線表を読み順に挿入し、周囲の本文からセル文字を 除外します。table_strategy="text" で保守的な罫線なし候補を追加でき、 None で表変換を無効にできます。
  • フォーム記入は値とネイティブ外観を書き込み、pylopdfと外部ビューアの両方で 描画されます。WinAnsiはHelveticaで自動縮小され、UnicodeはOpenTypeフォントを 指定するかpylopdf[cjk]のJP subset自動選択を使えます。Hangulや中国語地域に合う 字形は対応fontを指定します。combテキスト欄は継承されたMaxLenと 整列を尊重します。リッチテキスト、pushbutton、署名は対象外です。
  • CJK 縦書きは保守的に検出し、列内を上から下、列間を右から左へ読みます。 ルビ、割注、縦中横などの混在組版は解釈しません。

あえて実装しないもの — エコシステムで解決

pymupdf の機能 pylopdf での答え
Story API / insert_htmlbox(組版) typst(typst-py 経由)— レシピ
電子署名 pyHanko(MIT)— レシピ
インクリメンタル保存 現在は非対応。全体を書き直し、将来候補として監視中。署名用途はpyHankoが担う
XPS / EPUB / CBZ / 画像を開く 対象外 — PDF 専用

移植例

# pymupdf
import pymupdf
doc = pymupdf.open("in.pdf")
page = doc[0]
for rect in page.search_for("合計"):
    page.add_highlight_annot(rect)
pix = page.get_pixmap(matrix=pymupdf.Matrix(2, 2))
pix.save("page.png")
doc.save("out.pdf", garbage=4, deflate=True)
# pylopdf
import pylopdf
doc = pylopdf.open("in.pdf")
page = doc[0]
page.add_highlight_annot(page.search_for("合計"))   # リストごと渡せる
page.get_pixmap(scale=2).save("page.png")
doc.save("out.pdf", garbage=True, deflate=True)