0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

pythonでPDFのフォント埋め込みの有無を確認する

Posted at

PDFへのフォント埋め込みの有無の確認

PDFはテキスト、フォント、画像などが記述されたファイルであり、アプリケーションで開くたびにレンダリングがなされています。そのため、PDFで指定されたフォントがPDFをレンダリングする環境に存在しないと、文書をうまく表示できず、文字化けしてしまいます。このように、PDFを開く環境によって文字化けしてしまうと困るので、環境に依存せず等しく表示できるようにPDFにフォントが埋め込まれていることがあります。pythonでPDFへのフォント埋め込みの有無を確認することができるのでその方法をまとめます。

環境

Goole colabratory

実装

使用する際はPDF_PATHを実際のPATHに書き換えてください。

# モジュールのインストール
!pip -q install PyPDF2
from PyPDF2 import PdfReader

# PATHを自分のPDFに合わせて置き換え
PDF_PATH = "/content/****.pdf"

def list_fonts_with_embedding(pdf_path: str):
    reader = PdfReader(pdf_path)
    seen = {}
    for page in reader.pages:
        resources = page.get("/Resources")
        if not resources:
            continue
        resources = resources.get_object()
        fonts = resources.get("/Font")
        if not fonts:
            continue
        fonts = fonts.get_object()
        for name, fref in fonts.items():
            f = fref.get_object()
            base = str(f.get("/BaseFont", ""))
            subtype = str(f.get("/Subtype", ""))
            embedded = False
            embed_key = None

            # まずは直下の FontDescriptor を見る
            fd = f.get("/FontDescriptor")
            if fd:
                fd = fd.get_object()
                for k in ("/FontFile", "/FontFile2", "/FontFile3"):
                    if k in fd:
                        embedded = True
                        embed_key = k
                        break

            # Type0 (CID) の場合は DescendantFonts を辿る
            if not embedded and subtype == "/Type0":
                desc = f.get("/DescendantFonts")
                if desc:
                    try:
                        df = desc[0].get_object()
                        base = str(df.get("/BaseFont", base))
                        fd2 = df.get("/FontDescriptor")
                        if fd2:
                            fd2 = fd2.get_object()
                            for k in ("/FontFile", "/FontFile2", "/FontFile3"):
                                if k in fd2:
                                    embedded = True
                                    embed_key = k
                                    break
                    except Exception:
                        pass

            seen[(base, subtype)] = (embedded, embed_key)

    rows = []
    for (base, subtype), (embedded, embed_key) in sorted(seen.items()):
        rows.append({
            "使用フォント名": base,
            "フォント形式": subtype,
            "埋め込み有無": embedded,        # ← ここが True なら埋め込み
            "格納ストリーム": embed_key # /FontFile /FontFile2 /FontFile3 のどれか
        })
    return rows

rows = list_fonts_with_embedding(PDF_PATH)
for r in rows:
    print(r)

実行例

実際に実行すると、以下のような出力になります。

{'使用フォント名': '/CTNVZN+CMBX12', 'フォント形式': '/Type1', '埋め込み有無': True, '格納ストリーム': '/FontFile3'}
{'使用フォント名': '/EBDEKI+CMMI9', 'フォント形式': '/Type1', '埋め込み有無': True, '格納ストリーム': '/FontFile3'}
{'使用フォント名': '/FHMYDA+CMR7', 'フォント形式': '/Type1', '埋め込み有無': True, '格納ストリーム': '/FontFile3'}
{'使用フォント名': '/FJZRGE+CMMI10', 'フォント形式': '/Type1', '埋め込み有無': True, '格納ストリーム': '/FontFile3'}
{'使用フォント名': '/HGLWXW+CMBX9', 'フォント形式': '/Type1', '埋め込み有無': True, '格納ストリーム': '/FontFile3'}
{'使用フォント名': '/IJGBIV+CMR9', 'フォント形式': '/Type1', '埋め込み有無': True, '格納ストリーム': '/FontFile3'}

フォントの種類ごとに結果が表示され、'埋め込み有無'がTrueになっていれば埋め込みがなされています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?