Pythonで文字を入れてサムネ画像(アイキャッチ)を生成する。

以下は、マークダウン形式に変換した記事です。


Pythonで画像に文字を入れる方法を前回紹介しました。 https://www.tech-tech.xyz/archives/drawtext.html 今回は、文字の大きさを自動調節し、文字入れするスクリプトを書いたので紹介します。つぎのような画像が生成されます。

生成画像

サンプルコード

#./icatch.py
#coding:utf-8
import math
import sys
from PIL import Image, ImageDraw, ImageFont

args = sys.argv
img_path, raw_message = args[1:3]
#環境によって設定を変える
message = raw_message.decode("shift_jis")#Windowsの場合
#message = raw_message.decode("utf-8")#Linux,Macの場合

#画像の読み込み
img = Image.open(img_path)
#drawインスタンスを生成
draw = ImageDraw.Draw(img)
img_width, img_height = img.size

#中央揃え(水平、垂直)
center_align = True
vertical_align = True
#画像幅に対する文字幅の割合
ratio = 0.8
#文字列のフォントファイルを指定
fontpath = "C:\\Windows\\Fonts\\meiryob.ttc"
#文字の色をRGBで設定
msg_color = (255, 255, 255)

#フォントサイズを1ptにしたときのメッセージの幅を求める
font1pt = ImageFont.truetype(fontpath, 1)
msg1pt_width, msg1pt_height = font1pt.getsize(message)
#フォントのサイズ(pt)を求める
font_pt = int(math.floor(ratio * img_width/float(msg1pt_width)))
font = ImageFont.truetype(fontpath, font_pt)
#中央揃えの処理
msg_width, msg_height = font.getsize(message)
if center_align:
    msg_x = int(0.5 * (img_width - msg_width))
else:
    msg_x = 0
if vertical_align:
    msg_y = int(0.5 * (img_height - msg_height))
else:
    msg_y = 0
#文字を書く
draw.text((msg_x, msg_y), message, fill=msg_color, font=font)
#画像を保存
new_path = img_path[:img_path.rfind(".")] + "_text" + img_path[img_path.rfind("."):]
img.save(new_path)

実行方法

第1引数はファイル名で第2引数は表示するメッセージです。 たとえば、下記の画像(cat.jpg)を保存して、次のようにコマンドライン上でスクリプト(icatch.py)を実行すると冒頭で紹介した画像が生成されます。

$icatch.py cat.jpg 我輩は猫である。

生成画像

サンプルコードの解説

文字のフォントサイズの調整

#フォントサイズを1ptにしたときのメッセージの幅を求める
font1pt = ImageFont.truetype(fontpath, 1)
msg1pt_width, msg1pt_height = font1pt.getsize(message)
#フォントのサイズ(pt)を求める
font_pt = int(math.floor(ratio * img_width/float(msg1pt_width)))

ここでフォントサイズの調整を行っています。1ptでの文字列の文字幅を求めます。 文字幅はフォントサイズ(pt)に比例して大きくなります。 したがって、画像の幅を1ptでの文字幅で割ると最適なフォントサイズが求まります。 ここで、ImageFont.truetypeの引数fontpathは環境によって異なりますので、適切なフォントファイルのパスを指定してください。

中央揃えの処理

#中央揃えの処理
msg_width, msg_height = font.getsize(message)
if center_align:
    msg_x = int(0.5 * (img_width - msg_width))
else:
    msg_x = 0
if vertical_align:
    msg_y = int(0.5 * (img_height - msg_height))
else:
    msg_y = 0

ここでメッセージを表示するときのx,y座標を求めています。center_align, vertical_alignで中央揃え(水平、垂直)するかどうかを設定します。

コメント

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