Pythonで画像をPDFに変換する
Pythonを使用して画像をPDFファイルに変換する方法は、いくつかのライブラリを利用することで実現できます。ここでは、代表的なライブラリであるPillowとreportlabを使った方法を中心に、その手順、応用、注意点などを解説します。
Pillowを用いた基本的な変換
Pillowは、Pythonで画像を扱うための強力なライブラリであり、画像ファイルの読み込み、加工、保存など、幅広い機能を提供します。Pillow単体で直接PDFに保存する機能は持っていませんが、画像を一度PillowのImageオブジェクトとして読み込み、その画像をreportlabなどのPDF生成ライブラリに渡すことで、PDFに埋め込むことができます。
Pillowのインストール
まず、Pillowをインストールします。コマンドプロンプトまたはターミナルで以下のコマンドを実行してください。
pip install Pillow
reportlabのインストール
次に、PDFを生成するためのライブラリであるreportlabをインストールします。
pip install reportlab
Pillowとreportlabを組み合わせた変換
以下は、Pillowで画像を読み込み、reportlabを使ってPDFに保存する基本的なコード例です。
from PIL import Image
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
def image_to_pdf(image_path, output_pdf_path):
try:
# 画像をPillowで開く
img = Image.open(image_path)
img_width, img_height = img.size
# PDFキャンバスを作成
c = canvas.Canvas(output_pdf_path)
# 画像のアスペクト比を維持したまま、PDFページに収まるようにサイズを調整
# PDFのページサイズ(デフォルトはA4)に対して画像のサイズを計算
page_width, page_height = c._pagesize
aspect_ratio = img_height / img_width
if img_width > page_width or img_height > page_height:
if img_width / page_width > img_height / page_height:
# 横幅を基準に縮小
new_width = page_width
new_height = page_width * aspect_ratio
else:
# 高さを基準に縮小
new_height = page_height
new_width = page_height / aspect_ratio
else:
# 画像がページサイズより小さい場合はそのまま
new_width = img_width
new_height = img_height
# 画像をPDFに描画
# 座標 (0, 0) は左下隅
# 画像を中央に配置する場合の計算例
x_offset = (page_width - new_width) / 2
y_offset = (page_height - new_height) / 2
c.drawInlineImage(img, x_offset, y_offset, width=new_width, height=new_height)
# PDFを保存
c.save()
print(f"Successfully converted {image_path} to {output_pdf_path}")
except FileNotFoundError:
print(f"Error: Image file not found at {image_path}")
except Exception as e:
print(f"An error occurred: {e}")
# 使用例
# image_file = "your_image.jpg" # 変換したい画像ファイルのパスを指定
# output_pdf = "output.pdf" # 出力するPDFファイルのパスを指定
# image_to_pdf(image_file, output_pdf)
このコードでは、Image.open()で画像を読み込み、そのサイズを取得します。canvas.Canvas()でPDFドキュメントを作成し、drawInlineImage()メソッドを使って画像をPDFに描画します。画像のサイズ調整は、PDFのページサイズに合わせてアスペクト比を維持しながら行われます。
複数の画像を一つのPDFに変換する
複数の画像を順番に一つのPDFファイルにまとめることも一般的です。この場合、各画像に対してdrawInlineImage()を呼び出すことになります。
複数画像変換のコード例
from PIL import Image
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
from reportlab.lib.pagesizes import letter # ページサイズとしてletterを選択
def images_to_pdf(image_paths, output_pdf_path):
try:
c = canvas.Canvas(output_pdf_path, pagesize=letter) # ページサイズを指定
page_width, page_height = letter # 選択したページサイズを取得
for image_path in image_paths:
try:
img = Image.open(image_path)
img_width, img_height = img.size
# 画像のアスペクト比を維持したまま、PDFページに収まるようにサイズを調整
aspect_ratio = img_height / img_width
if img_width > page_width or img_height > page_height:
if img_width / page_width > img_height / page_height:
new_width = page_width * 0.9 # 余白を考慮
new_height = page_width * aspect_ratio * 0.9
else:
new_height = page_height * 0.9 # 余白を考慮
new_width = page_height / aspect_ratio * 0.9
else:
new_width = img_width
new_height = img_height
# 画像をPDFに描画(中央配置)
x_offset = (page_width - new_width) / 2
y_offset = (page_height - new_height) / 2
c.drawInlineImage(img, x_offset, y_offset, width=new_width, height=new_height)
# 次の画像のために新しいページを追加(最初の画像以外)
c.showPage()
except FileNotFoundError:
print(f"Warning: Image file not found at {image_path}. Skipping.")
except Exception as e:
print(f"An error occurred while processing {image_path}: {e}. Skipping.")
# 最後のページを保存
c.save()
print(f"Successfully converted multiple images to {output_pdf_path}")
except Exception as e:
print(f"An error occurred during PDF creation: {e}")
# 使用例
# image_files = ["image1.jpg", "image2.png", "image3.jpeg"] # 変換したい画像ファイルのパスのリスト
# output_pdf_multiple = "output_multiple.pdf"
# images_to_pdf(image_files, output_pdf_multiple)
この例では、image_pathsというリストに画像ファイルのパスを格納し、ループ処理で各画像をPDFに描画しています。c.showPage()メソッドは、現在のページを終了し、次のページを開始するために使用されます。これにより、各画像が別々のページに配置されます。
ページサイズと余白の調整
reportlabでは、pagesizesモジュールからさまざまな標準ページサイズ(letter, A4, legalなど)を選択できます。また、画像を描画する際にx_offsetやy_offsetを調整することで、ページ内での配置を制御したり、余白を設けることができます。上記のコード例でも、画像サイズをページサイズの90%に収めるように調整することで、ある程度の余白を確保しています。
より高度なPDF生成:reportlabの活用
reportlabは単に画像を配置するだけでなく、テキスト、図形、表などを組み合わせて、より複雑なレイアウトのPDFを生成するための豊富な機能を提供します。
テキストの追加
画像の上にキャプションなどを追加したい場合、canvas.drawString()やcanvas.drawText()メソッドを使用します。
図形の描画
線(canvas.line())や矩形(canvas.rect())、円(canvas.circle())なども描画可能です。
フォントとスタイルの設定
reportlab.lib.fontsモジュールやcanvas.setFont()メソッドを使って、フォントの種類、サイズ、色などを設定できます。
その他のライブラリの利用
reportlab以外にも、PythonでPDFを生成するためのライブラリは存在します。
wkhtmltopdf と pdfkit
wkhtmltopdfは、HTML/CSSをPDFに変換するツールであり、Pythonからはpdfkitライブラリを経由して利用できます。WebページをPDF化するのに適していますが、画像のみを変換する場合は、一度HTMLを作成してからPDF化する手間がかかります。
fpdf2
fpdf2は、FPDFライブラリのフォークであり、比較的シンプルで使いやすいPDF生成ライブラリです。画像挿入機能も備わっています。
注意点と考慮事項
* **画像フォーマットの対応:** Pillowは多くの画像フォーマット(JPEG, PNG, GIF, BMP, TIFFなど)に対応していますが、使用するライブラリによっては特定のフォーマットしかサポートしていない場合があります。
* **画質とファイルサイズ:** 画像の解像度や圧縮率によっては、生成されるPDFのファイルサイズが大きくなることがあります。必要に応じて、画像をPDFに埋め込む前にリサイズしたり、圧縮したりすることを検討してください。
* **パフォーマンス:** 大量の画像を変換する場合や、高解像度の画像を扱う場合は、処理に時間がかかることがあります。
* **エラーハンドリング:** ファイルが見つからない、画像ファイルが破損しているなどのエラーが発生する可能性があるため、適切なエラーハンドリング(try-exceptブロックの使用)を行うことが重要です。
* **アスペクト比の維持:** 画像をPDFに配置する際に、アスペクト比を維持しないと画像が歪んで表示されます。適切なサイズ調整ロジックを実装することが不可欠です。
まとめ
Pythonで画像をPDFに変換する方法は、主にPillowとreportlabを組み合わせるのが一般的です。Pillowで画像を読み込み、reportlabでPDFドキュメントを作成して画像を埋め込むという流れになります。単一の画像から複数の画像まで、目的に応じて柔軟に処理を記述できます。PDFにテキストや図形を追加するなどの高度な機能もreportlabで実現可能です。変換にあたっては、対応フォーマット、画質、パフォーマンス、エラーハンドリングなどに注意を払うことで、より高品質なPDF生成が可能となります。
