Pythonでブログのサムネイル画像を自動生成する方法

IT・プログラミング

今回は、ブログのサムネイルをPythonを使って自動で作成する方法を紹介したいと思います。
たくさんのブログ記事を書きたい時に、ブログのサムネイルを一つ一つ丁寧に作っていくのはなかなか時間がかかります。
もちろん、一つ一つ丁寧に作った方がクオリティは高くなるのですが、効率的にサイト構築を行っていくためには、ある程度自動化できるところは自動化して効率化を図る必要があります。
そこで今回は、Pythonを使って、タイトルの文字列から一括でサムネイルを生成したいと思います。

ベースとなる画像の作成

まず、初めにベースとなるサムネイルのデザインを作成しておきましょう。
タイトルの文字列を画像の中心付近に入力していきたいので、基本的に中心部分は空白として外側などにデザインをするようにしてください。
そのようにして作成した画像をベースイメージとして保存します。今回はbase_img.pngというファイル名で保存しています。
base image

作成する際には、canvaなどを使うとさまざまなテンプレートからお気に入りのものを選び、編集することができるので、簡単にデザインの整った画像を生成できます。

タイトルの自動挿入

今回はこのベースイメージにタイトル部分の文字列を自動で挿入していきます。
そのために使うライブラリはPillowというライブラリです。
このライブラリは画像の編集や文字の挿入などに特化しているライブラリです。

以下のコードを実行すれば、サムネイルを生成できます。
必要な入力項目は先程作成したベースイメージのファイルパスと新しく生成したいファイルのパス、そしてタイトル部分として追加したい文字列、出力先のパスをそれぞれ入力してください。
また、color_wordsに色を変えたい単語とその色の辞書を渡すことで文字の色を変えることができます。
そのほかデフォルトの文字色と、行間も指定可能です。

def add_text_to_image(base_image_path, text, output_path, color_words={}, default_color="#073678", line_spacing=20):
    base_image = Image.open(base_image_path)
    image_width, image_height = base_image.size
    image_with_text = base_image.copy()
    draw = ImageDraw.Draw(image_with_text)
    font_path = "C:/Windows/Fonts/meiryo.ttc"
    font_size = 65
    font = ImageFont.truetype(font_path, font_size, encoding="unic")


    lines = text.split('\n')
    y = (image_height - font_size*len(lines)) // 2

    for line in lines:
        x = (image_width - font.getbbox(line)[2]) // 2 
        for color_word in color_words.keys():
            if color_word in line:
                words = split_text(line, color_words.keys())
                break
            else:
                words = line
        print(words)    
        for word in words:
            word_width, word_height = get_size(draw,word, font=font)
            if color_words and word in color_words:
                color = color_words[word]
                draw.text((x, y), word, fill=color, font=font)
            else:
                draw.text((x, y), word, fill=default_color, font=font)

            x += word_width + font.getbbox(' ')[0]  # Add word width and space

        y += font.getsize(line)[1] + line_spacing

    image_with_text.save(output_path)
    print(f"Image with text saved as {output_path}")

これを以下のように実行します。

autopost.add_text_to_image(base_image_path, 'Pythonで\nブログのサムネイルを\n自動生成する方法', 'test.png', color_words={'Python':'#E36F24','サムネイル':'#E36F24','自動生成':'#E36F24'})

すると次のような画像が生成できます。

完成画像

かなり簡単に作成できたかと思います。

コードの注意点としては、Pillowはデフォルトのままだと日本語が使えない設定になっているので、日本語を指定する必要があります。
この時、OSに元々入っているフォントを指定して使うので、Windowsの場合は上記のコードで実行できますが、MacやLinuxでは書き方が若干変わってくるので注意してください。
ファイルリソースが読み込めないといったようなエラーが発生した場合は、ファイルのパスが間違っている可能性が高いです。

このコードを使うとかなり簡単にサムネイル画像を作成できるので、時間がない人はぜひ使ってみてください。

コードの解説

最後にコードの中身を解説していきます。

モジュールのインポート

# 必要なモジュールをインポートします
from PIL import Image, ImageDraw, ImageFont

このブロックでは、Pillow(Python Imaging Library)から必要なモジュールをインポートしています。これらのモジュールは画像の操作と描画に使用されます。

関数の定義

# 画像にテキストを追加する関数を定義します
def add_text_to_image(base_image_path, text, output_path, color_words={}, default_color="#073678", line_spacing=20):
    # 関数の本体がここに続きます...

このブロックでは、add_text_to_image という名前の関数を定義しています。この関数は、指定されたパラメータを使用して画像にテキストを追加する役割を果たします。

画像の準備

    # ベースとなる画像を開きます
    base_image = Image.open(base_image_path)
    # 画像の幅と高さを取得します
    image_width, image_height = base_image.size
    # ベース画像のコピーを作成します
    image_with_text = base_image.copy()

このブロックでは、ベース画像を開き、その幅と高さを取得しています。また、ベース画像のコピーを作成し、このコピーに対してテキストを追加します。

フォントとテキストの設定

    # テキストを描画するためのオブジェクトを作成します
    draw = ImageDraw.Draw(image_with_text)
    # 使用するフォントを指定します(Windowsのフォントを使用しています)
    font_path = "C:/Windows/Fonts/meiryo.ttc"
    font_size = 65
    font = ImageFont.truetype(font_path, font_size, encoding="unic")

このブロックでは、テキストを描画するための ImageDraw オブジェクトを作成し、フォントのパスとサイズを指定しています。このフォントはWindowsのメイリオフォントを使用しています。

テキストの分割と配置

    # テキストを改行ごとに分割します
    lines = text.split('\n')
    # テキストを中央に配置するためのy座標を計算します
    y = (image_height - font_size*len(lines)) // 2

このブロックでは、テキストを改行文字 \n で分割し、各行をリスト lines に格納します。また、テキストを中央に配置するための y 座標を計算します。

テキストのループ

    for line in lines:
        # テキストを中央に配置するためのx座標を計算します
        x = (image_width - font.getbbox(line)[2]) // 2 

        # テキスト中の特定の単語にカスタムの色を適用します
        for color_word in color_words.keys():
            if color_word in line:
                words = split_text(line, color_words.keys())
                break
            else:
                words = line

このブロックでは、テキストを行ごとに処理します。各行に対して以下の処理を行います:

  • テキストを中央に配置するための x 座標を計算します。
  • テキスト中にカスタムの色が指定された単語があるかを確認します。カスタムの色がある場合、その単語のみが抽出され、それ以外の場合は行全体が words 変数に格納されます。

単語のループ

        for word in words:
            # 単語の幅と高さを取得します
            word_width, word_height = get_size(draw, word, font=font)
            # カスタムの色が指定されている場合、その色を使用して単語を描画します
            if color_words and word in color_words:
                color = color_words[word]
                draw.text((x, y), word, fill=color, font=font)
            # カスタムの色が指定されていない場合、デフォルトの色を使用して単語を描画します
            else:
                draw.text((x, y), word, fill=default_color, font=font)

            # 次の単語のx座標を設定します
            x += word_width + font.getbbox(' ')[0]  # 単語の幅とスペースを加算

このブロックでは、各行内の単語を処理します。各単語に対して以下の処理を行います:

  • 単語の幅と高さを取得します。これは、テキストを描画する際に単語の配置に使用されます。
  • カスタムの色が指定されている場合、その色を使用して単語を描画します。
  • カスタムの色が指定されていない場合、デフォルトの色を使用して単語を描画します。
  • 次の単語の x 座標を設定します。これにより、次の単語は前の単語の右に配置されます。

行の間隔と次の行のy座標

        # 次の行のy座標を設定します
        y += font.getsize(line)[1] + line_spacing

このブロックでは、次の行の y 座標を設定し、行と行の間隔を調整します。この行が処理されると、次の行が正確にその下に配置されます。

画像の保存

    # 画像を保存します
    image_with_text.save(output_path)
    print(f"Image with text saved as {output_path}")

このブロックでは、テキストを追加した画像を指定された出力パスに保存します。image_with_text はテキストが追加されたベース画像のコピーです。また、保存が完了したことを確認するためにメッセージが表示されます。

タイトルとURLをコピーしました