本記事では、Pythonにて複数の画像ファイルをMicrosoft OfficeのPowerPointに貼り付ける雛形コードを載せました。1スライドあたりに貼り付ける列数を指定することで、画像サイズを自動で調整します。そして、貼り付ける行方向の枚数を自動で算出して、1スライドで収まらない場合は次のスライドへ順次貼り付けてゆく仕様です。使用するライブラリは「python-pptx」と「Pillow」です。
下図4つは、本コードの実行例です。貼り付ける画像の列方向の数を本コード内にある変数「num_cols」の数値で指定できます。
▼画像配置が1スライド4列の場合
各ページの上部には、タイトルとサブタイトルを入力できるレイアウトです。
▼画像配置が1スライド3列の場合
▼画像配置が1スライド2列の場合
▼画像配置が1スライド1枚の場合
■ライブラリのインストール
pip install python-pptx
pip install Pillow
■本プログラム
import glob from pptx import Presentation from pptx.util import Inches, Emu, Pt from pptx.enum.text import PP_ALIGN from pptx.dml.color import RGBColor from pptx.enum.shapes import MSO_SHAPE from PIL import Image # 複数の画像ファイルパスのリスト image_paths = glob.glob("./dir_img/*.jpg") num_figs = len(image_paths) print(num_figs, image_paths) # スライド1枚に画像を貼り付ける列数 num_cols = 2 # 保存するファイル名 save_file_name = f"{num_cols}_cols.pptx" # 画像サイズを取得する関数 def get_image_size(image_path): # 画像サイズを取得 with Image.open(image_path) as img: width, height = img.size return width, height # 画像サイズを取得 image_width, image_height = get_image_size(image_paths[0]) # オリジナル画像のアスペクト比(縦横比)を取得 original_aspect_ratio = image_height / image_width # 新規プレゼンテーションを作成 presentation = Presentation() # スライドの幅と高さを取得 slide_width = presentation.slide_width - (2 * Inches(0.5)) # 左右の余白を引く slide_height = presentation.slide_height - (2 * Inches(0.5)) # 上下の余白を引く # 行列の間隔と行の上部のスペース、左右のスペースを設定 row_spacing = Inches(0.3) # 行間 col_spacing = Inches(0.3) # 列間 top_space_first_row = Inches(1.5) # 上部スペースを持たせる side_space = Inches(1) # 左スペースを持たせる # 行数の計算 if (len(image_paths) % num_cols) == 0: num_rows = len(image_paths) // num_cols else: num_rows = (len(image_paths) // num_cols) + 1 # 画像を横に並べるための計算 total_side_space = 2 * side_space # 左右のスペースの和 #image_and_spacing_width = num_cols * (slide_width - total_side_space) + (num_cols - 1) * col_spacing image_and_spacing_width = num_cols * (slide_width - total_side_space) \ + (num_cols - 1) * col_spacing # 画像のサイズを調整 if image_and_spacing_width > slide_width: # スライドの幅に収まらない場合、画像サイズを調整 total_col_spacing = (num_cols - 1) * col_spacing adjusted_image_width = (slide_width - total_side_space - total_col_spacing) / num_cols adjusted_image_height = adjusted_image_width * original_aspect_ratio # 縦方向にはみ出さないための行数を算出 for i in range(1, num_rows+1, 1): image_and_spacing_height = adjusted_image_height * i + top_space_first_row + row_spacing*(i-1) height_delta = slide_height - image_and_spacing_height if height_delta < 0: num_rows = i break elif num_cols == 1: # 1ページに1枚の場合 total_col_spacing = (num_cols - 1) * col_spacing adjusted_image_width = (slide_width - total_side_space - total_col_spacing) / num_cols adjusted_image_height = adjusted_image_width * original_aspect_ratio num_rows = 1 print('num_cols, num_rows', num_cols, num_rows) # 必要なスライドページ数を計算 if (num_figs % (num_rows * num_cols)) == 0: pages = num_figs // (num_rows * num_cols) else: pages = num_figs // (num_rows * num_cols) + 1 # スライドを必要な分だけ作成する slide_count = 0 fig_count = 0 while slide_count < pages: # スライドを追加 slide = presentation.slides.add_slide(presentation.slide_layouts[5]) title_shape = slide.shapes.title title_shape.text = "タイトル" # 左詰め title_shape.text_frame.paragraphs[0].alignment = PP_ALIGN.LEFT # タイトルのフォントサイズを設定 title_shape.text_frame.paragraphs[0].font.size = Pt(32) # タイトルをスライドの上端に配置 title_shape.top = Inches(0.1) # タイトルの幅をスライドの幅に合わせる title_shape.width = presentation.slide_width # タイトルの高さをフォントサイズと同じに設定 title_shape.height = title_shape.text_frame.paragraphs[0].font.size # サブタイトルを設定 left = title_shape.left top = title_shape.top + title_shape.height width = title_shape.width height = Inches(0.5) textbox = slide.shapes.add_textbox(left, top, width, height) frame = textbox.text_frame frame.text = "サブタイトル" frame.paragraphs[0].alignment = PP_ALIGN.CENTER # 中央配置 frame.paragraphs[0].runs[0].font.size = Pt(28) # フォントサイズを設定 # タイトルの下に棒線を描く left = title_shape.left top = title_shape.top + title_shape.height width = title_shape.width height = Pt(1) # 線の太さを設定 line = slide.shapes.add_shape( MSO_SHAPE.RECTANGLE, left, top, width, height ) fill = line.fill fill.solid() fill.fore_color.rgb = RGBColor(0x00, 0x00, 0x00) # 黒 line.shadow.inherit = True # 影 # 画像ファイルを貼り付けてゆく if num_rows != 1: # スライド1枚に複数の画像を貼り付ける場合 for row in range(num_rows): for col in range(num_cols): #print('row, col', row, col) idx = row * num_cols + col #print(idx) left_inch = col * (adjusted_image_width + col_spacing) + side_space top_inch = top_space_first_row \ + row * (adjusted_image_width * original_aspect_ratio + row_spacing) # 画像を追加 fig_count = idx + slide_count*(num_rows*num_cols) picture = slide.shapes.add_picture(image_paths[fig_count], left_inch, top_inch, width=adjusted_image_width) # 画像の縦横比を保つ picture.lock_aspect_ratio = True # 1ページあたりの必要枚数を貼り付けたらループを抜ける if (idx == (num_rows*num_cols)-1) or (fig_count == num_figs-1): break # 2重ループを抜ける場合は次の3行で出来る else: continue break # ひとつ目のループをbreakで抜けた場合にここにきて、breakにより2つ目のループを抜ける else: # スライド1枚に1枚の画像を貼り付ける場合 left_inch = side_space top_inch = top_space_first_row # 画像を追加 picture = slide.shapes.add_picture(image_paths[slide_count], left_inch, top_inch, width=adjusted_image_width) # 画像の縦横比を保つ picture.lock_aspect_ratio = True slide_count += 1 #print('finished slide',slide_count) # プレゼンテーションを保存 presentation.save(save_file_name) print(f"save {save_file_name}")
以上
<広告>
リンク
リンク
リンク