Open28

PDF 関連

nassynassy

PyMuPDF

https://github.com/pymupdf/pymupdf

PyMuPDFは、軽量なPDF、XPS、電子書籍のビューア、レンダラー、ツールキットであるMuPDFにPythonバインディングと抽象化機能を追加します。PyMuPDFとMuPDFの両方はArtifex Software, Inc.によって保守・開発されています。

MuPDFは、PDF、XPS、OpenXPS、CBZ、EPUB、FB2(電子書籍)形式のファイルにアクセスでき、最高のパフォーマンスと優れたレンダリング品質で知られています。

PyMuPDFでは、.pdf, .xps, .oxps, .cbz, .fb2, .epubといった拡張子を持つファイルにアクセスできます。さらに、.png, .jpg, .bmp, .tiff など、約10種類の一般的な画像フォーマットも文書のように扱うことができます。

レイアウトも取れるみたい。

https://qiita.com/mima_ita/items/3f698050196d4af3a46d#pdfのテキスト情報はどうやって取得しているのか

https://needtec.sakura.ne.jp/wod07672/2020/05/04/pdfの点線を実線におきかえるpymupdf/

https://qiita.com/alice37308108/items/c9859a66981956e1dad1

rect の書き方に関して

https://github.com/pymupdf/PyMuPDF/issues/348

nassynassy

pdfrw

pdfrwで日本語フォントの入ったpdfが読み込めないのがいくつかありました
-> 日本語フォントが入ったPDFが真っ白になった

メンテが止まっているぽい
https://github.com/pmaupin/pdfrw

nassynassy

96dpi で吐き出されるらしく、綺麗に見せようとしたらファイルサイズを変える必要があります。

https://pymupdf.readthedocs.io/en/latest/recipes-images.html#how-to-make-images-from-document-pages

https://github.com/pymupdf/PyMuPDF/issues/181

get_pixmap をした時点で pdf そのものを画像として取り込むことになる。
PDF は72dpiなので get_pixmap したものは解像度が落ちてしまう。
元になったファイルが綺麗なのは、72dpi 以上で埋まっているからと考えられる。

nassynassy

既存のPDFに何か書き加える選択肢

  • pypdf の page.merge_page で reportlab で作ったレイヤーを重ねる
  • reportlab のcanvas に makerl で pdfrw の pagexobj を渡す方法
    • pdfrw はサイズが誤るとPDFが真っ白になってしまう
nassynassy

ポジション確認のスニペット

import io

from pypdf import PdfReader, PdfWriter
from reportlab.lib.colors import Color
from reportlab.lib.pagesizes import letter
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas


def replace_pdf(input_pdf, output_pdf):
    # テキスト変換器の設定
    outfp = io.StringIO()

    pdfmetrics.registerFont(TTFont("TakaoGothic", "/usr/share/fonts/truetype/takao-gothic/TakaoGothic.ttf"))

    # ページ単位でテキスト変換

    reader = PdfReader(input_pdf)
    page_number = len(reader.pages)
    output = PdfWriter()

    for page_num in range(page_number):
        page = reader.pages[page_num]
        packet = io.BytesIO()
        can = canvas.Canvas(packet, pagesize=letter)

        # todo
        print(f"{page.mediabox.width=}")
        print(f"{page.mediabox.height=}")
        print(f"{page.mediabox.top=}")

        font_size = 16
        can.setFont("TakaoGothic", font_size)
        can.setFillColor(Color(0, 0, 0, alpha=1))
        can.drawString(
            0,
            0,
            "こんにちは世界!",
        )
        can.save()

        packet.seek(0)
        new_pdf = PdfReader(packet)
        page.merge_page(new_pdf.pages[0])

        output.add_page(page)

    with open(output_pdf, "wb") as f:
        output.write(f)


replace_pdf("tests/sample.pdf", "data/output1.pdf")
nassynassy

回転をマージするやつ

# transformation = Transformation().rotate(90)
# new_pdf.pages[0].add_transformation(transformation, expand=True)
# page.merge_translated_page(new_pdf.pages[0], tx=page.mediabox.width, ty=0, expand=True)