[Python] OGPっぽい画像を作る

に公開

はじめに

% cogp OGPっぽい画像を作りたい ogp

とすると、下のような画像がzennのimages配下にogp.pngとして保存するコマンドを作成する
alt
こういうやつを作りたい

動作環境

バージョン
macOS macOS14.4 (23E214)
Python 3.12.3

概要

引数

引数 概要
第1引数 画像内の文字
第2引数 出力画像ファイル名

特徴

% cogp test1\\ntest2 test

  • 入力文字列内に\\nを含めると、そこで改行される
  • 右下に作成日を付ける

手順

  1. figmaで背景の土台を作る
  2. Pythonでコードを書く
  3. 実行権限を付与し、パスを通す

figmaで土台を作る

地味に頑張る
alt text
OGP_foundation.png

ディレクトリ構成

% tree -L 2

.
├── OGP_foundation.png
├── README
├── cogp
├── cogp_venv
│   ├── bin
│   ├── include
│   ├── lib
│   └── pyvenv.cfg
└── irohakakuC-Medium.ttf

Pythonでコードを書く

全体コード

https://gist.github.com/nematatu/b7ab0a3844558827f6075002ad7abfbf

使用ライブラリ

  • PIL: 画像生成
  • datetime: 日時を取得
  • sys: コマンドで引数を取得
  • os: パスを作成

コード概要

大雑把に説明しています。
gist↑を参照しながら見たほうがいいです。

  • シバン(shibang)

スクリプトファイルの先頭に書く行で、スクリプトを実行する処理系(インタプリタ)を指定する仕組み

マシンに、「Pythonのコードですよ〜」っていうのを明示的に示している

#! /usr/bin/env python3
  • ファイルが保存されている絶対パスを取得する
    土台画像のOGP.pngと、フォントのパスを取得するために必要
    (相対パスではなく、絶対パスで欲しいため)
parent_dir=os.path.dirname(os.path.abspath(__file__))
  • wrap_text関数で改行処理を行う

引数

  • text: 入力文字
  • max_width: 1行の文字の長さの上限
  • font: 使用フォントを指定
  1. 入力文字を\nで分割する
test_line = f"{current_line}{char}"
  1. 分割された文字列に対して以下の処理を行う
処理
  1. 仮にcurrent_lineに次の一文字を追加してみて、テキストの長さを取得する
test_line = f"{current_line}{char}"
width, height = draw.textbbox(
    (0, 0, image_width, image_height), test_line, font=font
)[2:]
  1. テキストの長さがmax_widthを超えなければそれを新たにcurrent_lineとする
if width <= max_width:
    current_line = test_line
  1. 超えてしまった場合、1文字追加前のテキストをlines配列に格納
if current_line:
    lines.append(current_line)
  1. current_lineを、追加する1文字で初期化する(改行)
current_line=char
  1. forを抜けた後に、current_linelines配列に格納する

  2. 入力文字の高さを調べ、全体の高さを調べる

    if lines:
        line_bbox = draw.textbbox(
            (0, 0, image_width, image_height), lines[0], font=font
        )
        line_height = line_bbox[3] - line_bbox[1]
    else:
        line_height = 0
    # 全部の行の高さ
    total_text_height = line_height * len(lines)

    start_y = (image_height - total_text_height) // 2
  1. 画像の中心に文字を描画
  2. 名前と日付を描画する

シェルではバックスラッシュがエスケープされてしまうので、\\nと入力する
コード内で\\n\nと置換する

title = sys.argv[1].replace("\\n", "\n")
  1. コマンドとして実装
    https://zenn.dev/kotopasi/articles/33f648f3e99482

おわりに

これから使っていこ〜

GitHubで編集を提案

Discussion