【簡単Python】PDFに電子スタンプを押す方法

アフィリエイト広告を利用しています。
【QRコード】PC<--->スマホの切り替えにご利用ください
運営者・ポテ

いつもありがとうございます。

「ノンプログラマー向けPython解説シリーズ」へようこそ。

本稿では、「PDFに電子スタンプを押す方法」を解説いたします。

電子スタンプとは、次の図に示す「参考」のように、電子的に押されたスタンプのことを指します。これは、紙にハンコとインクで物理的に押すスタンプではなく、PDFファイル上に直接電子的に描画されたものです。

電子スタンプのイメージ図

市販の有料アプリケーションソフトウェアでは、高度なPDF編集が可能ですが、費用がかさむのが難点です。一方、Pythonでアプリを自作すれば、コストを抑えつつ、目的に合わせた柔軟なツールを作成できます。

Pythonで自分に合ったアプリを作成し、仕事量は半分に、成果は2倍にしていきましょう。

初心者でも理解しやすいように、分かりやすく解説していきます。ぜひ、ご覧ください。


Pythonで「PDFに電子スタンプを押す方法」

アプリの仕様

次のようなディレクトリ構成です。

program/
  ├── main.py
  ├── input.pdf
  ├── output.pdf
  └── fonts/
    └── YuGothB.ttc

main.pyがPythonコードが記述されたプログラムです。このプログラムが、input.pdfを読み込み、スタンプを押したものをoutput.pdfとして出力します。

fontsディレクトリ内にある YuGothB.ttcはフォントファイルです。main.pyがスタンプのテキストを生成する際に使用します。なお、フォントファイルは、Windowsであれば通常次のディレクトリに保存されています。ここから、必要なフォントファイルをfontsディレクトリにコピーして使うと良いでしょう。

C:\Windows\Fonts

どのようなスタンプを押すか(たとえば「参考」や「社外秘」など)は、コード内で指定します。このスタンプの内容は、GUI(グラフィカル・ユーザー・インターフェース)を作成して、その中で指定するようなアプリにすることもできますが、本稿ではその部分は省略します。

ことばの意味

  • ディレクトリ
    ディレクトリとフォルダは、どちらもコンピュータ上でファイルを整理・管理するための「入れ物」を指します。ディレクトリは、技術的な用語で、プログラミングやコマンドライン操作など専門的な場面で使われます。フォルダは、一般的な用語で、パソコンの画面上でファイルを整理する際に使われます。デスクトップやエクスプローラーで見かける「フォルダ」のことです。ディレクトリとフォルダは基本的に同じものです。違いは呼び方や使われる場面だけで、役割や機能に大きな差はありません。
  • GUI(グラフィカルユーザーインターフェース)
    ユーザーとコンピューターがコミュニケーションするための視覚的なインターフェースです。インターフェースとは接点のことです。ウィンドウ、ボタン等のグラフィカルな要素を使用してユーザーとコンピューターがコミュニケーションできるようにします。

コード全文

上述の仕様のアプリを作成するためのコードと、その実行結果を示します。

# 標準ライブラリのインポート
import io                                    # バイトストリームを扱うために使用

# 外部ライブラリのインポート
from reportlab.pdfgen.canvas import Canvas   # PDFの描画を行うためのモジュール
from reportlab.lib.colors import Color       # 色を扱うためのモジュール
from reportlab.pdfbase.ttfonts import TTFont # TrueTypeフォントを使用するためのモジュール
from reportlab.pdfbase import pdfmetrics     # フォントの登録やメトリクスを扱うためのモジュール
import PyPDF2                                # PDFの読み書きを行うためのモジュール


class PDFHandler:
    """
    PDFの作成、および既存のPDFにテキストを重ねる処理を行うクラス。

    主な機能:
    - フォントを登録する
    - 新しいPDFレイヤーを作成する
    - 新しいPDFレイヤーにテキストを描画する
    - テキストを描画したPDFレイヤーと既存のPDFを重ねる
    """

    def __init__(self, source_pdf_path, destination_pdf_path, font_file_path):
        """
        クラスを初期化し、入力PDF、出力PDF、フォントのパスを設定する。

        :param source_pdf_path: 入力用のPDFファイルパス
        :param destination_pdf_path: 出力用のPDFファイルパス
        :param font_file_path: フォントファイルのパス
        """
        self.source_pdf_path = source_pdf_path              # 入力元のPDFファイルパスを記憶
        self.destination_pdf_path = destination_pdf_path    # 出力先のPDFファイルパスを記憶
        self.font_file_path = font_file_path                # フォントファイルのパスを記憶

    def register_font(self, font_name):
        """
        フォントを登録する。

        :param font_name: 登録するフォントの名前
        """
        pdfmetrics.registerFont(TTFont(font_name, self.font_file_path))  # フォントをReportLabに登録


    @staticmethod
    def draw_text_with_border(canvas_obj, content, font_name, font_size,
                              font_color, text_padding, transparency):
        """
        キャンバスにテキストとその周囲の枠線を描画する。

        :param canvas_obj: ReportLabのCanvasオブジェクト
        :param content: 描画するテキスト
        :param font_name: フォントの名前
        :param font_size: フォントサイズ
        :param font_color: テキストと枠線の色(RGBタプル)
        :param text_padding: テキストと枠線間の余白
        :param transparency: テキストと枠線の透明度(0.0〜1.0)
        """

        # 色と透明度を設定
        text_color = Color(
            font_color[0] / 255.0,   # 赤色の値を0〜1に正規化
            font_color[1] / 255.0,   # 緑色の値を0〜1に正規化
            font_color[2] / 255.0,   # 青色の値を0〜1に正規化
            alpha=transparency       # 透明度を設定
        )
        canvas_obj.setFillColor(text_color)         # テキストの塗りつぶし色を設定
        canvas_obj.setStrokeColor(text_color)       # 枠線の色を設定
        canvas_obj.setStrokeColor(text_color)       # 枠線の色を設定
        canvas_obj.setFont(font_name, font_size)    # フォントとサイズを設定

        # テキストの描画
        canvas_obj.drawString(0, 0, content)   # 原点(0,0)にテキストを描画

        # 枠線の描画
        text_width = pdfmetrics.stringWidth(content, font_name, font_size)  # テキストの幅を計算
        text_height = font_size                # テキストの高さはフォントサイズと同じ
        canvas_obj.setLineWidth(1)             # 枠線の太さを設定
        canvas_obj.rect(
            -text_padding,                     # 左側の余白
            -text_padding,                     # 下側の余白
            text_width + 2 * text_padding,     # 枠線の幅
            text_height + 2 * text_padding     # 枠線の高さ
        )


    def create_text_layer_for_page(self, content, font_name, font_size, font_color,
                                   text_x, text_y, text_padding, page_width, page_height,
                                   text_rotation_angle=0, transparency=0.5):
        """
        指定したテキストを含むPDFのページを作成する。

        :param content: 描画するテキスト
        :param font_name: フォントの名前
        :param font_size: フォントサイズ
        :param font_color: テキストと枠線の色(RGBタプル)
        :param text_x: 描画位置のX座標
        :param text_y: 描画位置のY座標
        :param text_padding: テキストと枠線間の余白
        :param page_width: ページの幅
        :param page_height: ページの高さ
        :param text_rotation_angle: テキストの回転角度(度単位)
        :param transparency: テキストと枠線の透明度(0.0〜1.0)
        :return: 作成したPDFページを含むBytesIOオブジェクト
        """

        self.register_font(font_name)   # フォントを登録

        packet = io.BytesIO()           # バイナリストリームを作成(メモリ内でPDFデータを一時的に保存)
        canvas_obj = Canvas(packet, pagesize=(page_width, page_height))  # キャンバスを作成

        canvas_obj.saveState()          # キャンバスの現在の状態を保存
        try:
            canvas_obj.translate(text_x, text_y)        # 描画位置に移動
            canvas_obj.rotate(text_rotation_angle)      # テキストを回転
            self.draw_text_with_border(                 # テキストと枠線を描画
                canvas_obj, content, font_name, font_size,
                font_color, text_padding, transparency
            )
        except Exception as e:
            raise RuntimeError(f"Failed to draw text or border: {e}")  # エラーが発生した場合
        finally:
            canvas_obj.restoreState()   # キャンバスの状態を復元する。
                                        # ここで復元されるのは座標系や色、フォント設定などの状態であり、
                                        # すでに描画された内容(テキストや図形)は消えない。

        canvas_obj.showPage()  # ページの描画を確定
        canvas_obj.save()      # PDFを保存
        packet.seek(0)         # バイナリストリームの先頭に戻す(後続の処理で読み込むため)
        return packet          # 作成したPDFページを含むバイナリストリームを返す


    @staticmethod
    def get_page_dimensions(page):
        """
        ページの幅、高さ、回転角度を取得する。

        :param page: PyPDF2のページオブジェクト
        :return: (幅, 高さ, 回転角度)のタプル
        """

        rotation = page.get("/Rotate", 0)  # 回転角度を取得(デフォルトは0)
        rotation = rotation % 360          # 回転角度を0〜359度に正規化
        media_box = page.mediabox          # ページのサイズ情報を取得
        width = float(media_box.width)     # ページの幅を取得
        height = float(media_box.height)   # ページの高さを取得
        return width, height, rotation     # 幅、高さ、回転角度を返す


    def add_text_layer_to_page(self, page, content, font_name, font_size,
                               font_color, text_x, text_y, text_padding,
                               text_rotation_angle, transparency,
                               page_width, page_height):
        """
        既存のPDFページにテキストレイヤーを重ねる。

        :param page: PyPDF2のページオブジェクト
        :param content: 描画するテキスト
        :param font_name: フォントの名前
        :param font_size: フォントサイズ
        :param font_color: テキストと枠線の色(RGBタプル)
        :param text_x: 描画位置のX座標
        :param text_y: 描画位置のY座標
        :param text_padding: テキストと枠線間の余白
        :param text_rotation_angle: テキストの回転角度(度単位)
        :param transparency: テキストと枠線の透明度(0.0〜1.0)
        :param page_width: ページの幅
        :param page_height: ページの高さ
        """

        # 新しいテキストレイヤーを作成
        text_layer_pdf = self.create_text_layer_for_page(
            content, font_name, font_size, font_color,
            text_x, text_y, text_padding, page_width, page_height,
            text_rotation_angle, transparency
        )
        text_layer_reader = PyPDF2.PdfReader(text_layer_pdf)    # テキストレイヤーを読み込む
        text_page = text_layer_reader.pages[0]                  # 最初のページを取得
        page.merge_page(text_page)                              # テキストレイヤーを既存のページに重ねる

    def merge_pdfs(self, content, font_name='CustomFonts', font_size=12,
                   font_color=(0, 0, 0), text_x=0, text_y=0, text_padding=10,
                   specific_page=None, apply_to_all_pages=False,
                   text_rotation_angle=0, transparency=0.5):
        """
        既存のPDFにテキストを重ね、新しいPDFを作成する。

        :param content: 追加するテキスト
        :param font_name: フォントの名前
        :param font_size: フォントサイズ
        :param font_color: テキストと枠線の色(RGBタプル)
        :param text_x: 描画位置のX座標(左上原点)
        :param text_y: 描画位置のY座標(左上原点)
        :param text_padding: テキストと枠線間の余白
        :param specific_page: テキストを追加する特定のページ番号(0基準)。
                              apply_to_all_pages が True の場合、この値は無視される。
        :param apply_to_all_pages: 全ページに適用するか(Trueなら全ページ)
        :param text_rotation_angle: テキストの回転角度(度単位)
        :param transparency: テキストと枠線の透明度(0.0〜1.0)
        """

        with open(self.source_pdf_path, "rb") as f_input:
            reader = PyPDF2.PdfReader(f_input)  # 入力PDFを読み込む
            writer = PyPDF2.PdfWriter()         # 出力PDFのライターを作成

            # PDFの各ページを処理
            for i, page in enumerate(reader.pages):
                # ページの幅、高さ、回転角度を取得
                page_width, page_height, rotation = self.get_page_dimensions(page)

                # 対象ページかどうかを判定
                if apply_to_all_pages or (specific_page is not None and i == specific_page):
                    rotation = rotation % 360  # 回転角度を正規化

                    # 回転角度に応じて座標と回転を調整
                    if rotation == 0:
                        adjusted_x = text_x
                        adjusted_y = page_height - text_y - font_size
                        adjusted_rotation_angle = text_rotation_angle
                    elif rotation == 90:
                        adjusted_x = text_y + font_size
                        adjusted_y = text_x
                        adjusted_rotation_angle = text_rotation_angle + 90
                    elif rotation == 180:
                        adjusted_x = page_width - text_x
                        adjusted_y = text_y + font_size
                        adjusted_rotation_angle = text_rotation_angle + 180
                    elif rotation == 270:
                        adjusted_x = page_width - text_y - font_size
                        adjusted_y = page_height - text_x
                        adjusted_rotation_angle = text_rotation_angle + 270
                    else:
                        adjusted_x = text_x
                        adjusted_y = page_height - text_y - font_size
                        adjusted_rotation_angle = text_rotation_angle

                    # テキストレイヤーをページに追加
                    self.add_text_layer_to_page(
                        page, content, font_name, font_size,
                        font_color, adjusted_x, adjusted_y, text_padding,
                        adjusted_rotation_angle, transparency,
                        page_width, page_height
                    )

                # ページを出力PDFに追加
                writer.add_page(page)

            # 出力PDFを保存
            with open(self.destination_pdf_path, "wb") as f_output:
                writer.write(f_output)

        # 処理完了のメッセージを表示
        print("Text added to PDF successfully.")


def main():
    """
    既存のPDFにテキストと枠線を重ねる処理を行う。

    この関数では、PDFHandlerクラスを利用して次の処理を実行する:
    - 入力PDFと出力PDFの指定
    - テキストの内容、位置、フォント、サイズ、透明度の設定
    - 指定されたページまたは全ページにテキストを重ねる処理
    """
    # PDF編集に必要な設定を指定
    source_pdf_path = 'input.pdf'                       # 入力元のPDFファイルパス
    destination_pdf_path = 'output.pdf'                 # 出力先のPDFファイルパス
    content = '参考'                                     # PDFに描画するテキスト
    font_size = 22                                      # テキストのフォントサイズ
    font_color = (255, 0, 0)                            # テキストの色(RGB形式)
    font_file_path = 'fonts/YuGothB.ttc'                # 使用するフォントファイルのパス
    specific_page = 0                                   # テキストを追加するページ番号(0基準)
                                                        # apply_to_all_pages が True の場合、この値は無視される
    apply_to_all_pages = True                           # 全ページに適用するか(Trueなら全ページ)
    text_rotation_angle = 5                             # テキストの回転角度(度単位)

    text_x = 50                                         # テキスト描画位置のX座標(左上原点)
    text_y = 50                                         # テキスト描画位置のY座標(左上原点)

    text_padding=10                                     # テキストの余白を指定

    # PDF操作クラスのインスタンスを作成
    pdf_handler = PDFHandler(
        source_pdf_path,
        destination_pdf_path,
        font_file_path
    )

    # PDFにテキストを重ねる処理を実行
    pdf_handler.merge_pdfs(
        content,                                        # 追加するテキスト
        font_name="YuGothB",                            # 使用するフォント名
        font_size=font_size,                            # フォントサイズ
        font_color=font_color,                          # フォントの色
        text_x=text_x,                                  # テキストのX座標
        text_y=text_y,                                  # テキストのY座標
        text_padding=text_padding,                      # テキストの余白を指定
        specific_page=specific_page,                    # 特定のページ番号
        apply_to_all_pages=apply_to_all_pages,          # 全ページに適用するか
        text_rotation_angle=text_rotation_angle,        # テキストの回転角度
        transparency=0.3                                # 透明度
    )


if __name__ == "__main__":
    main()

マクロ実行前
マクロ実行後のディレクトリ
マクロ実行後
input.pdf(入力PDF)
output.pdf(出力PDF)
運営者・ポテ

解説していきます。

コードの全体像の解説

概要

このコードは、既存のPDFにテキストや枠線を重ねる処理を実現するものです。中心にあるのは、PDFHandler というカスタムクラスで、このクラスを利用することで、次のような操作を簡単に行えるようにしています。

  1. フォントの登録
    任意のフォントファイルを読み込み、PDF内で使用できるようにします。これにより、カスタムフォントを活用して独自のデザインを反映できます。
  2. 新しいPDFレイヤーの作成
    テキストとその枠線を含む新規PDFレイヤーを作成し、透明度や位置、回転角度といった細かい設定も反映可能です。
  3. 既存のPDFへのレイヤー合成
    作成したPDFレイヤーを、指定したページや全ページに重ね合わせ、加工したPDFを新しいファイルとして保存します。

使用するライブラリ

  • reportlab
    PDFファイルにテキストや図形を描画するライブラリです。このコードでは、キャンバスオブジェクトを使用してテキストや枠線を描画する役割を担います。
  • PyPDF2
    PDFファイルの読み取りや編集を行うライブラリです。このコードでは、既存のPDFファイルに新しいレイヤーを合成するために使用します。

クラス設計の特徴

このコードは、以下の2つの観点を重視して設計しています。

  1. 柔軟性
    描画するテキストの位置、色、サイズ、透明度、回転角度を細かく設定できます。また、全ページまたは特定のページへの適用を選択可能です。
  2. 効率性
    PDF操作の主要なタスク(フォント登録、新しいPDFレイヤーの作成、レイヤーの合成)がモジュール化されており、追加の設定や操作を簡単に拡張できます。

クラス内の各メソッドの使われ方

このコードでは、上部に記述されたメソッドが、その下に記述されたメソッド内で順次呼び出され、処理が進むように設計されています。なお、メソッドとは、クラス内に記述された関数のことを指します。つまり、def で記述されたブロックのことです。

  1. register_font
    カスタムフォントを登録するメソッドです。指定されたフォントファイルをPDFで使用可能な形式で登録します。他のメソッドでテキストを描画する際に必要です。
  2. draw_text_with_border
    キャンバス上にテキストとその枠線を描画するメソッドです。create_text_layer_for_page で使用され、テキストの描画と、その周囲に余白を持つ枠線を描画する処理を実行します。
  3. create_text_layer_for_page
    テキストを描画するためのPDFレイヤーを作成するメソッドです。このメソッドでは、register_font を利用してフォントを登録し、draw_text_with_border を使用してテキストと枠線を描画します。作成したPDFレイヤーはメモリ内のバイトストリームとして保持されます。
  4. add_text_layer_to_page
    特定のページにテキストを追加するメソッドです。merge_pdfs内で使用され 、create_text_layer_for_page を呼び出して新しいテキストレイヤーを作成し、それを既存のPDFページに重ねます。
  5. get_page_dimensions
    PDFページの幅、高さ、回転角度を取得する補助メソッドです。merge_pdfs 内で使用され、ページ情報を取得してテキスト描画時の座標や回転角度の調整に利用されます。
  6. merge_pdfs
    アプリケーション全体の制御を行う主要なメソッドです。このメソッドは、入力PDFを読み込み、各ページにテキストを追加し、結果を新しいPDFとして保存します。他のメソッドを呼び出して処理を分割し、最終的なPDFを出力する役割を担います。

想定される利用シーン

このコードは、次のようシーンで活用できます。

  • 書類に電子的にスタンプを押
    「参考」や「承認済み」といったスタンプを透かし付きでPDFに追加することができます。
  • PDFに注釈を追加する
    PDFの特定の位置にコメントやメモを追加することができます。
  • カスタムPDFの生成
    新しいテキストやデザインを加えたPDFを作成すことができます。

コードの詳細な解説

ここから、コードの解詳細な説をしていきます。

# 標準ライブラリのインポート
import io                                    # バイトストリームを扱うために使用

# 外部ライブラリのインポート
from reportlab.pdfgen.canvas import Canvas   # PDFの描画を行うためのモジュール
from reportlab.lib.colors import Color       # 色を扱うためのモジュール
from reportlab.pdfbase.ttfonts import TTFont # TrueTypeフォントを使用するためのモジュール
from reportlab.pdfbase import pdfmetrics     # フォントの登録やメトリクスを扱うためのモジュール
import PyPDF2                                # PDFの読み書きを行うためのモジュール

ここでは、このコードで使用するライブラリをインストールしています。各ライブラリの役割は下表の通りです。

ことばの意味

  • ライブラリ
    特定の機能をもったコードの集合体です。ソフトウェア作成における部品のようなものです。新しいアプリケーションを作成する際、ライブラリを使用することで、プログラマーは複雑なコードを自分で書く必要がなくなります。
  • 外部ライブラリ
    Pythonの標準ライブラリに含まれていないライブラリです。外部ライブラリを使うためにはインストールをする必要があります。
ライブラリ 役割 主な使用箇所
import io メモリ内でファイル操作を行うためのモジュールです。 一時的に新しいPDFデータを保持するBytesIOオブジェクトの作成に使用します。
from reportlab.pdfgen.canvas import Canvas PDFの描画領域(キャンバス)を作成します。テキストや図形を描画することが可能です。 新しいPDFレイヤーを作成し、テキストや枠線、図形などを描画する際に使用します。
from reportlab.lib.colors import Color RGB値や透明度を設定して色を指定します。 テキストや枠線の色、透明度を設定する際に使用します。
from reportlab.pdfbase.ttfonts import TTFont TrueTypeフォントを登録します。 カスタムフォント(例: YuGothB)をPDFで使用可能にするために登録する際に使用します。
from reportlab.pdfbase import pdfmetrics フォントの登録やメトリクス(文字幅の計算)を提供します。 テキストの幅を計算して、枠線や描画位置を調整する際に使用します。
import PyPDF2 PDFの読み取り、編集、合成、出力を行います。 既存のPDFファイルを読み込んだり、新しいレイヤーを重ねたり、編集済みPDFを保存する際に使用します。

このように、reportlabは新しいPDFの描画を、PyPDF2は既存PDFの編集を担当しています。それぞれの役割を組み合わせることで、PDFにテキストや枠線を簡単に追加できる仕組みを構築しています。

なお、コマンドプロンプトにて外部ライブラリをインストールする方法については、こちらの記事で解説しております。もしよろしければ、合わせてご覧ください。

【簡単Python】開発環境に外部ライブラリをインストールする2つの方法

いつもありがとうございます。 「ノンプログラマー向けPython解説シリーズ」へようこそ。 本稿では、「開発環境に外部ライブラリをインストールする方法」を解説いたしま…

PyhonのIDLE(Pythonに付属している標準の統合開発環境)ではなく、サードパーティー製の統合開発環境(IDE: Integrated Development Environment)を使用している場合は、その統合開発環境に外部ライブラリをインストールする機能があります。例えば、筆者が使用しているPyCharmでは、コード作成画面にカーソルを置いて「Ctrl + Alt+ S」を押すと次のような外部ライブラリインストールのダイアログが表示されるので、コマンドではなく「+」ボタンからGUIで外部ライブラリをインストールすることができます。

ことばの意味

  • 統合開発環境
    プログラムを作成・実行するために必要なソフトウェアやツールが揃っている環境のことです。

なお、PyCharmは筆者の愛読書「独学プログラマー」の著者が、自身が使用している統合開発環境として紹介しています。もしよろしければ、合わせてご覧ください。

【Python書籍紹介】独学プログラマー【一冊で全体像が分かる】

いつもありがとうございます。 たくさんのプログラミングの本を読みましたが、入門書としてだけでなく、現役のプログラマーにとっても素晴らしい本があります。 「独学プ…


class PDFHandler:
    """
    PDFの作成、および既存のPDFにテキストを重ねる処理を行うクラス。

    主な機能:
    - フォントを登録する
    - 新しいPDFレイヤーを作成する
    - 新しいPDFレイヤーにテキストを描画する
    - テキストを描画したPDFレイヤーと既存のPDFを重ねる
    """

    def __init__(self, source_pdf_path, destination_pdf_path, font_file_path):
        """
        クラスを初期化し、入力PDF、出力PDF、フォントのパスを設定する。

        :param source_pdf_path: 入力用のPDFファイルパス
        :param destination_pdf_path: 出力用のPDFファイルパス
        :param font_file_path: フォントファイルのパス
        """
        self.source_pdf_path = source_pdf_path              # 入力元のPDFファイルパスを記憶
        self.destination_pdf_path = destination_pdf_path    # 出力先のPDFファイルパスを記憶
        self.font_file_path = font_file_path                # フォントファイルのパスを記憶

ここでは、PDFの操作を簡潔にまとめるためのクラス PDFHandler が定義されています。このクラスは、PDFの作成や既存のPDFにテキストを重ねるための一連の処理を提供します。

クラスの冒頭に記載されたドキュメンテーション文字列(docstring)では、このクラスの主な機能が示されています。

続いて、クラスの初期化部分(「コンストラクタ」となる init メソッド)では、入力PDF、出力PDF、フォントのパスを指定します。これにより、クラス全体でこれらの設定を共有し、各処理で一貫して利用できるようにしています。

    def register_font(self, font_name):
        """
        フォントを登録する。

        :param font_name: 登録するフォントの名前
        """
        pdfmetrics.registerFont(TTFont(font_name, self.font_file_path))  # フォントをReportLabに登録

ここでは、PDFで使用するフォントを登録するためのメソッド register_font を定義しています。このメソッドを使うことで、カスタムフォントをPDF内で利用可能にします。

具体的には、font_name を引数として受け取り、ReportLabのフォント管理システムに登録します。内部では、TTFont を用いてフォントファイル(self.font_file_path)を読み込み、pdfmetrics.registerFont を呼び出すことで登録を完了します。

これにより、テキスト描画時に登録したフォント名を指定するだけで、PDFにカスタムフォントを反映できるようになります。たとえば、「YuGothB」などの名前でフォントを登録することが可能です。

    @staticmethod
    def draw_text_with_border(canvas_obj, content, font_name, font_size,
                              font_color, text_padding, transparency):
        """
        キャンバスにテキストとその周囲の枠線を描画する。

        :param canvas_obj: ReportLabのCanvasオブジェクト
        :param content: 描画するテキスト
        :param font_name: フォントの名前
        :param font_size: フォントサイズ
        :param font_color: テキストと枠線の色(RGBタプル)
        :param text_padding: テキストと枠線間の余白
        :param transparency: テキストと枠線の透明度(0.0〜1.0)
        """

        # 色と透明度を設定
        text_color = Color(
            font_color[0] / 255.0,   # 赤色の値を0〜1に正規化
            font_color[1] / 255.0,   # 緑色の値を0〜1に正規化
            font_color[2] / 255.0,   # 青色の値を0〜1に正規化
            alpha=transparency       # 透明度を設定
        )
        canvas_obj.setFillColor(text_color)         # テキストの塗りつぶし色を設定
        canvas_obj.setStrokeColor(text_color)       # 枠線の色を設定
        canvas_obj.setStrokeColor(text_color)       # 枠線の色を設定
        canvas_obj.setFont(font_name, font_size)    # フォントとサイズを設定

        # テキストの描画
        canvas_obj.drawString(0, 0, content)   # 原点(0,0)にテキストを描画

        # 枠線の描画
        text_width = pdfmetrics.stringWidth(content, font_name, font_size)  # テキストの幅を計算
        text_height = font_size                # テキストの高さはフォントサイズと同じ
        canvas_obj.setLineWidth(1)             # 枠線の太さを設定
        canvas_obj.rect(
            -text_padding,                     # 左側の余白
            -text_padding,                     # 下側の余白
            text_width + 2 * text_padding,     # 枠線の幅
            text_height + 2 * text_padding     # 枠線の高さ
        )

ここでは、キャンバス上にテキストとその周囲の枠線を描画するためのメソッド draw_text_with_border を定義しています。このメソッドは @staticmethod として定義されており、クラスのインスタンスを必要とせずに汎用的に利用できます。

このメソッドは、指定されたフォントや色でテキストを描画し、そのテキストを囲む枠線を描画します。また、透明度や余白といった細かい調整も可能で、PDFのデザインを柔軟に制御するための基本機能を提供しています。

引数の詳細は、下表の通りです。

引数 説明
canvas_obj ReportLabのCanvasオブジェクトを指定します。描画の基盤となるキャンバスです。
content 描画するテキスト内容を指定します。
font_name テキスト描画に使用するフォントの名前を指定します。
font_size テキストのフォントサイズを指定します。
font_color テキストと枠線の色をRGB値(0~255)で指定します。
text_padding 枠線とテキストの間の余白を指定します。
transparency テキストと枠線の透明度を指定します(0.0~1.0の範囲)。

処理の流れは次のようになっています。

  1. 描画色と透明度の設定
    RGB値を0〜1の範囲に変換し、透明度を反映させた色を設定します。
  2. テキストの描画
    指定されたフォントとサイズでキャンバス上にテキストを描画します。
  3. 枠線の描画
    テキストの幅を計算し、その幅と高さに余白(text_padding)を加えた矩形を描画します。
    def create_text_layer_for_page(self, content, font_name, font_size, font_color,
                                   text_x, text_y, text_padding, page_width, page_height,
                                   text_rotation_angle=0, transparency=0.5):
        """
        指定したテキストを含むPDFのページを作成する。

        :param content: 描画するテキスト
        :param font_name: フォントの名前
        :param font_size: フォントサイズ
        :param font_color: テキストと枠線の色(RGBタプル)
        :param text_x: 描画位置のX座標
        :param text_y: 描画位置のY座標
        :param text_padding: テキストと枠線間の余白
        :param page_width: ページの幅
        :param page_height: ページの高さ
        :param text_rotation_angle: テキストの回転角度(度単位)
        :param transparency: テキストと枠線の透明度(0.0〜1.0)
        :return: 作成したPDFページを含むBytesIOオブジェクト
        """

        self.register_font(font_name)   # フォントを登録

        packet = io.BytesIO()           # バイナリストリームを作成(メモリ内でPDFデータを一時的に保存)
        canvas_obj = Canvas(packet, pagesize=(page_width, page_height))  # キャンバスを作成

        canvas_obj.saveState()          # キャンバスの現在の状態を保存
        try:
            canvas_obj.translate(text_x, text_y)        # 描画位置に移動
            canvas_obj.rotate(text_rotation_angle)      # テキストを回転
            self.draw_text_with_border(                 # テキストと枠線を描画
                canvas_obj, content, font_name, font_size,
                font_color, text_padding, transparency
            )
        except Exception as e:
            raise RuntimeError(f"Failed to draw text or border: {e}")  # エラーが発生した場合
        finally:
            canvas_obj.restoreState()   # キャンバスの状態を復元する。
                                        # ここで復元されるのは座標系や色、フォント設定などの状態であり、
                                        # すでに描画された内容(テキストや図形)は消えない。

        canvas_obj.showPage()  # ページの描画を確定
        canvas_obj.save()      # PDFを保存
        packet.seek(0)         # バイナリストリームの先頭に戻す(後続の処理で読み込むため)
        return packet          # 作成したPDFページを含むバイナリストリームを返す

ここでは、指定したテキストを描画する新しいPDFレイヤーを生成するためのメソッド create_text_layer_for_page を定義しています。このメソッドは、指定されたテキストを描画した単一のPDFページを作成し、メモリ内で保持します。生成されたPDFは、後続の処理で既存のPDFに重ねて使用されます。

ことばの意味

  • メソッド
    クラスの一部として定義される関数で、特定のオブジェクトに関連する処理や操作を行います。オブジェクトの状態を変更したり、その情報を基に動作を実行します。
  • オブジェクト
    プログラムで「何かを表現するための具体的な実体」です。データ(プロパティ)と動作(メソッド)を持ち、これらを組み合わせることで、複雑なシステムを柔軟に設計できます。
  • バイナリデータ
    コンピュータが処理する0と1の組み合わせで表現されたデータのことです。画像やPDFなどのファイル形式も含まれ、人間が視覚的に認識できる形に変換される前のコンピュータ内部での表現形式を指します。
  • バイナリストリーム
    画像や音声、動画、PDFなどのバイナリデータをビットやバイト単位で連続的に処理する仕組みを指します。例えば、PDFファイルを読み込む際、一括でメモリに読み込むのではなく、順番に少しずつデータを処理する際に利用されます。

引数の詳細は下表の通りです。

引数名 解説
content 描画するテキストを指定します。
font_name 使用するフォントの名前を指定します(事前に登録されている必要があります)。
font_size テキストのフォントサイズを指定します。
font_color テキストと枠線の色をRGB形式(タプル)で指定します(例: (255, 0, 0))。
text_x 描画位置のX座標(左上原点)を指定します。
text_y 描画位置のY座標(左上原点)を指定します。
text_padding テキストと枠線の間に設ける余白の幅を指定します。
page_width PDFページの幅を指定します。
page_height PDFページの高さを指定します。
text_rotation_angle テキストを回転させる角度(度単位)を指定します(デフォルトは0)。
transparency テキストと枠線の透明度を指定します(0.0~1.0、デフォルトは0.5)。

処理の流れは、次の通りです。

  1. フォントの登録
    register_font メソッドを呼び出し、指定されたフォントをPDFで使用可能にします。
  2. キャンバスの作成
    io.BytesIO を使用してメモリ内でPDFデータを保持するストリームを作成し、その後、Canvas オブジェクトを作成してページサイズを指定し、キャンバスを初期化します。
  3. キャンバス状態の保存
    saveState メソッドを使用して現在のキャンバス状態を保存します。この操作により、その後の変更があっても状態を復元可能になります。
  4. テキストの描画
    描画位置をtranslateメソッドで指定し、rotateメソッドを使って指定された角度分テキストを回転させます。その後、draw_text_with_borderメソッドを呼び出して、テキストとその枠線を描画します。
  5. エラーハンドリング
    描画中にエラーが発生した場合、例外を発生させて原因を明示します。
  6. キャンバス状態の復元
    restoreState メソッドを使用して、saveState メソッドで保存されたキャンバスの設定(座標系、色、フォントなど)を元に戻します。これにより、描画位置や回転などの変更をリセットできますが、すでに描画された内容はそのまま保持されます。
  7. ページの確定と保存
    showPage メソッドで現在のページを確定し、次にsaveメソッドを使用してPDFデータをバイトストリームに書き込みます。
  8. ストリームのリセット
    seek(0) を使用してストリームの位置を先頭に戻します。
  9. 結果の返却
    作成されたPDFデータを保持するBytesIOオブジェクトを返します。

このメソッドは、PDFに追加する要素を柔軟にカスタマイズし、複数ページや異なるレイアウトのPDF編集に対応するための基本的な仕組みを提供しています。

    @staticmethod
    def get_page_dimensions(page):
        """
        ページの幅、高さ、回転角度を取得する。

        :param page: PyPDF2のページオブジェクト
        :return: (幅, 高さ, 回転角度)のタプル
        """

        rotation = page.get("/Rotate", 0)  # 回転角度を取得(デフォルトは0)
        rotation = rotation % 360          # 回転角度を0〜359度に正規化
        media_box = page.mediabox          # ページのサイズ情報を取得
        width = float(media_box.width)     # ページの幅を取得
        height = float(media_box.height)   # ページの高さを取得
        return width, height, rotation     # 幅、高さ、回転角度を返す

ここでは、PDFのページサイズと回転角度を取得するための静的メソッド get_page_dimensions を定義しています。このメソッドは、PyPDF2 のページオブジェクトを入力として受け取り、ページの幅、高さ、回転角度を取得して返します。

このメソッドは、PDFページのレイアウトを動的に調整するために必要な基本的な情報(幅、高さ、回転角度)を提供します。取得した情報は、テキストや枠線の描画位置を正確に決定するために利用されます。

引数の詳細は、下表の通りです。

引数 説明
page PyPDF2 のページオブジェクトを指定します。このオブジェクトは、対象とするPDFのページを指します。

戻り値の詳細は、下表の通りです。

戻り値説明
widthページの幅(浮動小数点数で返されます)。
heightページの高さ(浮動小数点数で返されます)。
rotationページの回転角度(0~359度の範囲で正規化されて返されます)。

主要な処理の流れは、次の通りです。

  1. 回転角度の取得
    ページオブジェクトから/Rotateキーを取得し、ページの回転角度を取得します。回転角度が指定されていない場合は、デフォルト値として0を使用します。
  2. 回転角度の正規化
    回転角度を360で割った余りを計算(剰余演算)し、0~359度の範囲に収めます。これにより、負の回転角度や360度以上の値が調整されます。
  3. ページサイズの取得
    ページオブジェクトのmediaboxプロパティから、ページの幅と高さを取得します。このプロパティはPDFページのサイズ情報を含んでいます。
  4. 幅と高さの計算
    mediabox.widthmediabox.heightを浮動小数点数に変換し、ページの幅と高さを計算します。
  5. 結果の返却
    幅、高さ、正規化された回転角度をタプル形式で返します。この情報は、描画位置や座標計算に使用されます。

このメソッドは、PDFのページ構造を正確に把握するための基盤を提供します。特に、異なるページサイズや回転方向を持つPDFを扱う際に役立ちます。

    def add_text_layer_to_page(self, page, content, font_name, font_size,
                               font_color, text_x, text_y, text_padding,
                               text_rotation_angle, transparency,
                               page_width, page_height):
        """
        既存のPDFページにテキストレイヤーを重ねる。

        :param page: PyPDF2のページオブジェクト
        :param content: 描画するテキスト
        :param font_name: フォントの名前
        :param font_size: フォントサイズ
        :param font_color: テキストと枠線の色(RGBタプル)
        :param text_x: 描画位置のX座標
        :param text_y: 描画位置のY座標
        :param text_padding: テキストと枠線間の余白
        :param text_rotation_angle: テキストの回転角度(度単位)
        :param transparency: テキストと枠線の透明度(0.0〜1.0)
        :param page_width: ページの幅
        :param page_height: ページの高さ
        """

        # 新しいテキストレイヤーを作成
        text_layer_pdf = self.create_text_layer_for_page(
            content, font_name, font_size, font_color,
            text_x, text_y, text_padding, page_width, page_height,
            text_rotation_angle, transparency
        )
        text_layer_reader = PyPDF2.PdfReader(text_layer_pdf)    # テキストレイヤーを読み込む
        text_page = text_layer_reader.pages[0]                  # 最初のページを取得
        page.merge_page(text_page)                              # テキストレイヤーを既存のページに重ねる

ここでは、既存のPDFの特定のページにテキストレイヤーを追加するためのメソッド add_text_layer_to_page を定義しています。このメソッドは、新しいPDFレイヤーを生成し、それを指定された既存のページに重ね合わせる処理を行います。

このメソッドは、事前に指定されたフォントや色、座標を基にテキストレイヤーを作成し、それを既存のPDFページに統合することで、動的なPDF編集を可能にします。

引数の詳細は、下表の通りです。

引数 説明
page PyPDF2 のページオブジェクトです。既存のPDFページを指します。
content 描画するテキストです。
font_name 使用するフォントの名前です。
font_size テキストのフォントサイズです。
font_color テキストと枠線の色をRGBタプル(例: (255, 0, 0))で指定します。
text_x テキストを描画するX座標です。
text_y テキストを描画するY座標です。
text_padding テキストと枠線間の余白を指定する値です。
text_rotation_angle テキストの回転角度を指定します。
transparency テキストと枠線の透明度(0.0〜1.0)を指定します。
page_width ページの幅です。
page_height ページの高さです。

戻り値はありませんが、引数として受け取った page オブジェクトにテキストレイヤーが統合されます。

処理の流れは、次の通りです。

  1. 新しいPDFレイヤーの生成
    create_text_layer_for_page メソッドを使用して、新しいPDFレイヤーを生成します。このレイヤーには、指定されたテキストやフォント設定が反映されます。
  2. PDFレイヤーの読み込み
    生成されたPDFレイヤーを PyPDF2.PdfReader を使って読み込みます。このステップでは、PDFレイヤーの内容が操作可能なオブジェクトとして取得されます。
  3. ページの取得
    読み込んだPDFレイヤーの最初のページを取得します。このページが、既存のPDFに重ねるためのレイヤーとして利用されます。
  4. 既存ページへのレイヤー統合
    取得したページオブジェクトを用いて、page.merge_page を呼び出し、既存のPDFページに新しいレイヤーを重ね合わせます。

このメソッドを使うことで、既存のPDFに対して動的にテキストを追加できます。

    def merge_pdfs(self, content, font_name='CustomFonts', font_size=12,
                   font_color=(0, 0, 0), text_x=0, text_y=0, text_padding=10,
                   specific_page=None, apply_to_all_pages=False,
                   text_rotation_angle=0, transparency=0.5):
        """
        既存のPDFにテキストを重ね、新しいPDFを作成する。

        :param content: 追加するテキスト
        :param font_name: フォントの名前
        :param font_size: フォントサイズ
        :param font_color: テキストと枠線の色(RGBタプル)
        :param text_x: 描画位置のX座標(左上原点)
        :param text_y: 描画位置のY座標(左上原点)
        :param text_padding: テキストと枠線間の余白
        :param specific_page: テキストを追加する特定のページ番号(0基準)。
                              apply_to_all_pages が True の場合、この値は無視される。
        :param apply_to_all_pages: 全ページに適用するか(Trueなら全ページ)
        :param text_rotation_angle: テキストの回転角度(度単位)
        :param transparency: テキストと枠線の透明度(0.0〜1.0)
        """

        with open(self.source_pdf_path, "rb") as f_input:
            reader = PyPDF2.PdfReader(f_input)  # 入力PDFを読み込む
            writer = PyPDF2.PdfWriter()         # 出力PDFのライターを作成

            # PDFの各ページを処理
            for i, page in enumerate(reader.pages):
                # ページの幅、高さ、回転角度を取得
                page_width, page_height, rotation = self.get_page_dimensions(page)

                # 対象ページかどうかを判定
                if apply_to_all_pages or (specific_page is not None and i == specific_page):
                    rotation = rotation % 360  # 回転角度を正規化

                    # 回転角度に応じて座標と回転を調整
                    if rotation == 0:
                        adjusted_x = text_x
                        adjusted_y = page_height - text_y - font_size
                        adjusted_rotation_angle = text_rotation_angle
                    elif rotation == 90:
                        adjusted_x = text_y + font_size
                        adjusted_y = text_x
                        adjusted_rotation_angle = text_rotation_angle + 90
                    elif rotation == 180:
                        adjusted_x = page_width - text_x
                        adjusted_y = text_y + font_size
                        adjusted_rotation_angle = text_rotation_angle + 180
                    elif rotation == 270:
                        adjusted_x = page_width - text_y - font_size
                        adjusted_y = page_height - text_x
                        adjusted_rotation_angle = text_rotation_angle + 270
                    else:
                        adjusted_x = text_x
                        adjusted_y = page_height - text_y - font_size
                        adjusted_rotation_angle = text_rotation_angle

                    # テキストレイヤーをページに追加
                    self.add_text_layer_to_page(
                        page, content, font_name, font_size,
                        font_color, adjusted_x, adjusted_y, text_padding,
                        adjusted_rotation_angle, transparency,
                        page_width, page_height
                    )

                # ページを出力PDFに追加
                writer.add_page(page)

            # 出力PDFを保存
            with open(self.destination_pdf_path, "wb") as f_output:
                writer.write(f_output)

        # 処理完了のメッセージを表示
        print("Text added to PDF successfully.")

ここでは、既存のPDFに新しいテキストを重ねたPDFを作成(出力)するためのメソッド merge_pdfs を定義しています。このメソッドは、指定したテキストやフォント設定を基に、新しいPDFを生成し、指定された場所に保存します。これにより、PDF全体や特定のページに対してテキストを追加する編集が可能になります。

引数の詳細は以下の通りです。

引数名 説明
content 追加するテキストです。
font_name 使用するフォントの名前です。
font_size テキストのフォントサイズです。
font_color テキストと枠線の色です。RGB形式のタプル(例:(255, 0, 0))で表されます。
text_x 描画位置のX座標です。座標は左上原点で計算されます。
text_y 描画位置のY座標です。座標は左上原点で計算されます。
text_padding テキストと枠線間の余白です。単位はポイント(pt)です。
specific_page テキストを追加する特定のページ番号です。0基準の整数で表されます。apply_to_all_pagesTrueの場合は無視されます。
apply_to_all_pages 全てのページにテキストを適用する場合はTrue、特定のページにのみ適用する場合はFalseです。
text_rotation_angle テキストの回転角度です。単位は度です。
transparency テキストと枠線の透明度です。0.0(完全透明)から1.0(完全不透明)の範囲で指定します。

処理の流れは、次の通りです。

  1. 入力PDFを読み込む
    self.source_pdf_pathで指定されたPDFファイルをPyPDF2.PdfReaderを使って開き、変数readerに格納します。
  2. 出力PDFライターを作成する
    PyPDF2.PdfWriterをインスタンス化し、変数writerに格納します。このオブジェクトに新しいページを追加していきます。
  3. PDFの各ページを処理する
    reader.pagesをループで回し、変数pageに各ページのデータを取得します。ループのインデックスはiに格納されます。
  4. ページの幅、高さ、回転角度を取得する
    メソッドget_page_dimensionsを呼び出して、現在のページの幅、高さ、および回転角度を取得します。これらはpage_widthpage_heightrotationに格納されます。
  5. 対象ページかどうかを判定する
    apply_to_all_pagesTrueか、またはspecific_pageと現在のページ番号iが一致する場合に処理を続行します。
  6. 回転角度に応じて座標と回転角度を調整する
    ページの回転角度rotationに応じて、テキストの座標を調整します。この結果はadjusted_xadjusted_yadjusted_rotation_angleに格納されます。
  7. テキストレイヤーをページに追加する
    メソッドadd_text_layer_to_pageを呼び出し、調整後の座標と回転角度を用いてテキストレイヤーをpageに重ねます。
  8. 処理したページを出力PDFに追加する
    writer.add_page(page)を呼び出して、処理済みのpageを出力PDFに追加します。
  9. 出力PDFを保存する
    self.destination_pdf_pathで指定されたパスにファイルを書き出します。これにはwriter.write()を使用します。
  10. 処理結果を通知する
    標準出力に「Text added to PDF successfully.」を表示して処理が完了したことを通知します。

このメソッドを使用すると、既存のPDFに動的にテキストを追加し、編集結果を実際のファイルとして保存することができます。この機能により、PDF作成と出力の中核を担う重要な役割を果たしています。

def main():
    """
    既存のPDFにテキストと枠線を重ねる処理を行う。

    この関数では、PDFHandlerクラスを利用して次の処理を実行する:
    - 入力PDFと出力PDFの指定
    - テキストの内容、位置、フォント、サイズ、透明度の設定
    - 指定されたページまたは全ページにテキストを重ねる処理
    """
    # PDF編集に必要な設定を指定
    source_pdf_path = 'input.pdf'                       # 入力元のPDFファイルパス
    destination_pdf_path = 'output.pdf'                 # 出力先のPDFファイルパス
    content = '参考'                                     # PDFに描画するテキスト
    font_size = 22                                      # テキストのフォントサイズ
    font_color = (255, 0, 0)                            # テキストの色(RGB形式)
    font_file_path = 'fonts/YuGothB.ttc'                # 使用するフォントファイルのパス
    specific_page = 0                                   # テキストを追加するページ番号(0基準)
                                                        # apply_to_all_pages が True の場合、この値は無視される
    apply_to_all_pages = True                           # 全ページに適用するか(Trueなら全ページ)
    text_rotation_angle = 5                             # テキストの回転角度(度単位)

    text_x = 50                                         # テキスト描画位置のX座標(左上原点)
    text_y = 50                                         # テキスト描画位置のY座標(左上原点)

    text_padding=10                                     # テキストの余白を指定

    # PDF操作クラスのインスタンスを作成
    pdf_handler = PDFHandler(
        source_pdf_path,
        destination_pdf_path,
        font_file_path
    )

    # PDFにテキストを重ねる処理を実行
    pdf_handler.merge_pdfs(
        content,                                        # 追加するテキスト
        font_name="YuGothB",                            # 使用するフォント名
        font_size=font_size,                            # フォントサイズ
        font_color=font_color,                          # フォントの色
        text_x=text_x,                                  # テキストのX座標
        text_y=text_y,                                  # テキストのY座標
        text_padding=text_padding,                      # テキストの余白を指定
        specific_page=specific_page,                    # 特定のページ番号
        apply_to_all_pages=apply_to_all_pages,          # 全ページに適用するか
        text_rotation_angle=text_rotation_angle,        # テキストの回転角度
        transparency=0.3                                # 透明度
    )

ここでは、PDFHandler クラスを利用して、既存のPDFにテキストと枠線を重ね、新しいPDFファイルとして保存します。編集対象のPDFや追加するテキストに関する各種設定を行い、merge_pdfs メソッドを呼び出すことで処理を実行します。

この関数の役割は次の通りです。

  1. 入力PDFと出力PDFの指定
    編集対象となる入力PDFのパス(source_pdf_path)と、編集結果を保存する出力PDFのパス(destination_pdf_path)を設定します。
  2. テキスト描画のパラメータ指定
    テキストの内容(content)、位置(text_xtext_y)、フォントサイズ(font_size)、色(font_color)、透明度(transparency)など、描画に必要な詳細な設定を行います。
  3. PDFHandlerのインスタンス作成
    指定した入力ファイル、出力ファイル、フォントファイルのパスを基にして、PDFHandler クラスのインスタンスを作成します。このインスタンスは、PDF編集の主要な処理を担当します。
  4. PDF編集処理の実行
    merge_pdfs メソッドを呼び出して、PDF全体または特定のページにテキストを追加し、編集済みのPDFを保存します。

設定項目の詳細は下表の通りです。

設定項目 説明
source_pdf_path 入力元のPDFファイルのパスです。
destination_pdf_path 編集後のPDFを保存する出力ファイルのパスです。
content PDFに描画するテキストの内容です。
font_size 描画するテキストのフォントサイズです。
font_color テキストの色をRGB形式で指定します(例: (255, 0, 0))。
font_file_path 使用するフォントファイルのパスです。
specific_page 編集対象となる特定のページ番号(0基準)を指定します。apply_to_all_pagesTrueの場合は無視されます。
apply_to_all_pages 全てのページにテキストを適用する場合はTrue、特定ページのみ適用する場合はFalseです。
text_rotation_angle テキストの回転角度(度単位)です。
text_x テキストの描画位置を指定するX座標です(左上原点)。
text_y テキストの描画位置を指定するY座標です(左上原点)。
text_padding テキストと枠線間の余白を指定します。
transparency テキストの透明度を0.0(完全透明)から1.0(完全不透明)で指定します。

処理の流れは次の通りです。

  1. 必要なファイルパスとパラメータの指定
    source_pdf_pathdestination_pdf_pathfont_file_path で入力・出力ファイルのパスとフォントファイルを指定します。また、テキスト描画に必要な設定(contentfont_sizefont_color など)を変数に代入します。
  2. PDFHandlerのインスタンス作成
    設定されたパスとパラメータを基にして、PDFHandler クラスのインスタンスを生成します。このインスタンスを通じてPDF編集を行います。
  3. テキストの追加とPDFの保存
    merge_pdfs メソッドを呼び出して、指定されたページまたは全ページにテキストを重ねます。その結果をdestination_pdf_pathで指定したパスに保存します。

この関数を利用すると、既存のPDFに対して動的にテキストを追加し、新しいPDFファイルを簡単に作成できます。設定を変更することで、全ページへの適用やページごとの詳細なカスタマイズも可能です。

if __name__ == "__main__":
    main()

ここでは、スクリプトのエントリーポイントを定義しています。if __name__ == "__main__": という条件式は、Pythonがスクリプトを実行するとき、自動的に設定される特別な変数 __name__ を利用しています。スクリプトが直接実行された場合、この値は "__main__" に設定されます。そのため、この条件が成立すると、main() 関数が呼び出される仕組みになっています。

この構造により、スクリプトが他のモジュールからインポートされた場合に、main() 関数が実行されることを防ぎます。これは、モジュールの再利用性と独立性を高めるためのPythonにおける一般的なプラクティスです。

この構造によって、スクリプトを直接実行したときにはPDFの編集処理が行われ、他のプログラムからインポートされたときには必要なクラスや関数のみを利用できるようになります。

ことばの意味

  • プラクティス
    「慣習」「習慣」「推奨される方法」という意味です。ここでは、Pythonプログラミングにおける一般的な慣習やベストプラクティスを指しています。
運営者・ポテ

以上で解説は終了です。ありがとうございました。


おわりに

運営者・ポテ

ご覧いただきありがとうございました。

本稿では、「PDFに電子スタンプを押す方法」を解説いたしました。

お問い合わせやご要望等ございましたら、「お問い合わせ/ご要望」またはコメントにて、ご連絡いただければ幸いでございます。

皆様の人生がより一層素晴らしいものになるよう、少しでもお役に立てれば幸いでございます。

なお、当サイトでは様々な情報を発信しております。もしよろしければ、トップページもご覧いただけると幸いでございます。


記事関連経験

  • Python 3 エンジニア認定基礎試験
    経済産業省が定めたガイドライン「ITスキル標準(ITSS)」に掲載されている民間資格です。
  • Python 使用経験 約5年
    実務に使用する アプリを多数作成してきました。

Python プログラミングスキルアップのための参考情報

ここでは参考図書を紹介いたしますが、これに限らず自分に合うものを選ぶことが重要だと考えております。皆様の、より一層のご成功を心からお祈りしております。


「独学プログラマー」というPythonを題材にした書籍は大変勉強になりました。Pythonの技術解説だけにとどまらず、プログラミングの魅力や基本的な知識、思考法、仕事の進め方まで幅広く学べます。


こちらの記事でも紹介しております。もしよろしければご覧ください。


また、Pythonに関する書籍は多数出版されています。興味のある方は、チェックしてみてください。

\チェックしてみよう/

\チェックしてみよう/

\チェックしてみよう/

【QRコード】PC<--->スマホの切り替えにご利用ください

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です