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?

jpgからパワポスライド作成ツール

Posted at

SS 192.png 画像の束からプレゼン用スライド

やること

jpgやpngの入ったフォルダを指定すると、そこから1ページに1枚写真が入ったパワポスライドを作成してくれるツールです。
旅行の土産話はもちろん、トレードショーや学会などに視察を行った時の報告書づくりに使えます。
またpdfをjpg化した際にもまとめてパワポに貼り直せます。

コード

ひょっとするとパワポ本来の機能でもできそうな気がしますが、pythonのコードにしました。
(制作はChatGPTに手伝ってもらってます。)

jpg2pptx.py

import os
import tkinter as tk
from tkinter import filedialog
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from PIL import Image, ExifTags
import pyheif

# フォルダ選択のためのダイアログを表示する関数


def select_folder():
    root = tk.Tk()
    root.withdraw()
    folder_selected = filedialog.askdirectory()
    return folder_selected

# フォルダ内の対応する画像ファイルを取得し、番号順にソートする関数


def get_sorted_image_files(folder_path):
    supported_formats = ('.png', '.jpg', '.jpeg', '.gif', '.heic')
    files = [f for f in os.listdir(folder_path) if os.path.splitext(f)[
        1].lower() in supported_formats]
    files.sort(key=lambda f: int(''.join(filter(str.isdigit, f)))
               if ''.join(filter(str.isdigit, f)) else float('inf'))
    return files

# HEICファイルをPILイメージに変換する関数


def load_heic_image(heic_path):
    heif_file = pyheif.read(heic_path)
    image = Image.frombytes(
        heif_file.mode,
        heif_file.size,
        heif_file.data,
        "raw",
        heif_file.mode,
        heif_file.stride,
    )
    return image

# 画像の向きをExifデータに基づいて修正する関数


def correct_image_orientation(image):
    try:
        for orientation in ExifTags.TAGS.keys():
            if ExifTags.TAGS[orientation] == 'Orientation':
                break
        exif = image._getexif()
        if exif is not None:
            orientation = exif.get(orientation)
            if orientation == 3:
                image = image.transpose(Image.ROTATE_180)
            elif orientation == 6:
                image = image.transpose(Image.ROTATE_270)
            elif orientation == 8:
                image = image.transpose(Image.ROTATE_90)
    except (AttributeError, KeyError, IndexError):
        pass
    return image

# 重複しないファイル名を生成する関数


def generate_unique_filename(directory, filename):
    base, ext = os.path.splitext(filename)
    counter = 1
    unique_filename = filename
    while os.path.exists(os.path.join(directory, unique_filename)):
        unique_filename = f"{base}_{counter}{ext}"
        counter += 1
    return unique_filename

# PowerPointファイルを作成する関数


def create_ppt_from_images(image_folder):
    ppt = Presentation()

    # スライドサイズを1920x1080ピクセルに設定
    ppt.slide_width = Inches(1920 / 96)  # 96 DPI
    ppt.slide_height = Inches(1080 / 96)  # 96 DPI

    # スライドマスターのクリアと背景設定
    slide_master = ppt.slide_master
    for layout in slide_master.slide_layouts:
        for shape in layout.shapes:
            if shape.has_text_frame:
                sp = shape
                sp.text = ""
            sp = layout.shapes._spTree.remove(sp._element)
        layout.background.fill.solid()
        layout.background.fill.fore_color.rgb = RGBColor(0, 0, 0)

    image_files = get_sorted_image_files(image_folder)

    for image_file in image_files:
        img_path = os.path.join(image_folder, image_file)
        slide = ppt.slides.add_slide(ppt.slide_layouts[5])  # 白紙スライドを追加

        # スライドの背景色を黒に設定
        slide.background.fill.solid()
        slide.background.fill.fore_color.rgb = RGBColor(0, 0, 0)

        if os.path.splitext(img_path)[1].lower() == '.heic':
            img = load_heic_image(img_path)
        else:
            img = Image.open(img_path)

        img = correct_image_orientation(img)
        img_width, img_height = img.size

        # スライドサイズ (1920x1080ピクセル)
        slide_width = ppt.slide_width.inches * 96  # ピクセル単位
        slide_height = ppt.slide_height.inches * 96  # ピクセル単位

        # 画像の縦横比を維持して、スライドの高さに収まるように縮小拡大
        scale_ratio = slide_height / img_height

        width = img_width * scale_ratio
        height = img_height * scale_ratio

        left = (slide_width - width) / 2  # 横方向の余白はスライドの中央に配置
        top = 0  # 縦方向は上下にぴったり合わせる

        # 回転後の画像を保存してから貼り付ける
        temp_img_path = os.path.join(image_folder, f"temp_{image_file}")
        img.save(temp_img_path)

        slide.shapes.add_picture(temp_img_path, Inches(
            left / 96), Inches(top / 96), Inches(width / 96), Inches(height / 96))

        # 一時ファイルを削除
        os.remove(temp_img_path)

    # 出力ファイルを選択したディレクトリと同じ階層に保存
    parent_folder = os.path.dirname(image_folder)
    output_filename = generate_unique_filename(
        parent_folder, "ReportSlider.pptx")
    output_path = os.path.join(parent_folder, output_filename)
    ppt.save(output_path)
    print(f"PowerPointファイルが作成されました: {output_path}")


# メイン処理
if __name__ == "__main__":
    image_folder = select_folder()
    if image_folder:
        create_ppt_from_images(image_folder)
    else:
        print("フォルダが選択されませんでした。")

使い方

ターミナルで

python jpg2pptx.py 

を実行し、ダイアログボックスでjpgやpngが入ったフォルダを選択します。
そのフォルダと同じ階層に、"ReportSlider.pptx"というファイルが生成されます。
パワポでファイルを開くと、写真が1ページに1枚ずつ、上下もしくは左右にフィットする形で中央配置されています。デフォルトは黒背景です。

最後に

もし動かなかったらすみません。
必要なライブラリなどちょっとまとめます。
(HEIC対応しようとしてちょっと不具合出てます。)

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?