【Pythonでサムネ制作①】PILで画像の上に文字を重ねて中央表示

【Pythonでサムネ制作①】PILで画像の上に文字を重ねて中央表示
【Pythonでサムネ制作①】PILで画像の上に文字を重ねて中央表示

ブログやYouTubeで使うサムネを、画像編集ソフトを使わずにプログラミングでサクッと制作できたらいいですよね! とくに私なんかは、このブログサイトのアイキャッチ画像をPythonで制作できたら最高と思うのです。

さて、続編があるかどうかわかりませんが、Pythonでサムネ制作の第一弾としまして「画像の上に文字を重ねて中央表示する」をやってみました。

普段の作業が大幅に短縮できそうです。クリエイター&プログラマーの方必見の内容です!

ゴール

こんな感じのベースとなる画像を用意しまして、、、

元となる画像
元となる画像

それがこうなることを目指して進めていきます!

テキストを中央に表示
テキストを中央に表示

ちなみにCSSでテキストを重ねるやり方もあります。詳しくはこちらをご覧ください。

つかうもの

Python3をご用意ください。

Pillow

また、Pillow(PIL)という画像処理によく使われるモジュールが必要です。pipなどでインストールしておきましょう。

Pillow is the friendly PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lundh and Contributors.

Pillow (PIL Fork) 9.2.0 documentation

Pillowのインストール

shell
$ pip3 install Pillow

画像の上に文字を表示

それではさっそく、画像の上に文字を表示してみます。 次のようなプログラムを作成し実行してみてください。

test_overlay_a.py
from PIL import Image,ImageFont,ImageDraw
 
image_path = 'fuji.jpg' # 文字を重ねる画像
out_path = 'a.jpg' # 出力先

font_path = '/System/Library/Fonts/ヒラギノ角ゴシック W5.ttc'
font_size = 100
font_color = (255,255,255) #文字の色
text = '新倉山浅間公園'
pos = (200,100)

font = ImageFont.truetype(font_path, font_size)

image = Image.open(image_path)
draw = ImageDraw.Draw(image)

draw.text(pos, text, font=font, fill=font_color)
image.save(out_path)

するとこうなります。画像の上にテキストが表示できましたね!

画像の上に文字を表示
画像の上に文字を表示

お使いのOSによってフォントの種類や場所は違います。私はmacOSですので、フォントの場所は次のようになってます。

macOSのフォントの保存場所

macOSのフォントの保存場所は主に次の3つです。

  • /System/Library/Fonts
  • /Library/Fonts
  • /Users/ユーザ名/Library/Fonts

フォントが多すぎると画像編集ソフトでいちいち迷うので、使わないフォントは削除するようにしてますが、それでもこれだけたくさんの種類がインストールされてます。

shell
$ ls /System/Library/Fonts/
Apple Braille Outline 6 Dot.ttf			NotoSansKannada.ttc
Apple Braille Outline 8 Dot.ttf			NotoSansMyanmar.ttc
Apple Braille Pinpoint 6 Dot.ttf		NotoSansOriya.ttc
Apple Braille Pinpoint 8 Dot.ttf		NotoSerifMyanmar.ttc
Apple Braille.ttf				Optima.ttc
Apple Color Emoji.ttc				Palatino.ttc
Apple Symbols.ttf				PingFang.ttc
AppleSDGothicNeo.ttc				SFArabic.ttf
AquaKana.ttc					SFCompact.ttf
ArialHB.ttc					SFCompactItalic.ttf
Avenir Next Condensed.ttc			SFCompactRounded.ttf
Avenir Next.ttc					SFNS.ttf
Avenir.ttc					SFNSItalic.ttf
Courier.ttc					SFNSMono.ttf
GeezaPro.ttc					SFNSMonoItalic.ttf
Geneva.ttf					SFNSRounded.ttf
HelveLTMM					STHeiti Light.ttc
Helvetica.ttc					STHeiti Medium.ttc
HelveticaNeue.ttc				Supplemental
Hiragino Sans GB.ttc				Symbol.ttf
Keyboard.ttf					Thonburi.ttc
Kohinoor.ttc					Times.ttc
KohinoorBangla.ttc				TimesLTMM
KohinoorGujarati.ttc				ZapfDingbats.ttf
KohinoorTelugu.ttc				ヒラギノ丸ゴ ProN W4.ttc
LastResort.otf					ヒラギノ明朝 ProN.ttc
LucidaGrande.ttc				ヒラギノ角ゴシック W0.ttc
MarkerFelt.ttc					ヒラギノ角ゴシック W1.ttc
Menlo.ttc					ヒラギノ角ゴシック W2.ttc
Monaco.ttf					ヒラギノ角ゴシック W3.ttc
MuktaMahee.ttc					ヒラギノ角ゴシック W4.ttc
NewYork.ttf					ヒラギノ角ゴシック W5.ttc
NewYorkItalic.ttf				ヒラギノ角ゴシック W6.ttc
Noteworthy.ttc					ヒラギノ角ゴシック W7.ttc
NotoNastaliq.ttc				ヒラギノ角ゴシック W8.ttc
NotoSansArmenian.ttc				ヒラギノ角ゴシック W9.ttc
shell
$ ls /Library/Fonts/
Arial Unicode.ttf	BROOKH2.ttf		BauhausBoldItalic.ttf	BauhausRegular.ttf
BAUHHL.ttf		BauhausBold.ttf		BauhausItalic.ttf
shell
$ ls /Users/mopipico/Library/Fonts/
07にくまるフォント.otf			YAKITORI.TTF
AoyagiKouzanTOTF.otf			aoyagireisyosimo_otf_2_01.otf
HalfFont-Regular.ttf			gomarice_mukasi_mukasi.ttf
KsoKagerou.otf				mokkumokumo.ttf
KsoKagerouN.otf				pupupu-free.otf
KsoTouryu.otf				瀞ノグリッチ黒体H1.otf
KsoTouryuN.otf				瀞ノグリッチ黒体H2.otf
NikkyouSans-mLKax.ttf			瀞ノグリッチ黒体H3.otf
SeimeiKana-Free.otf			瀞ノグリッチ黒体H4.otf

フォントのタイプ

フォントのタイプは大雑把に次のとおりです。

拡張子意味
.ttfTrueTypeフォント
.otfOpenTypeフォント
.ttcTrueTypeフォントを1つのファイルにまとめたもの
.otcOpenTypeフォントを1つのファイルにまとめたもの

他にもフォントタイプには、ウェブブラウザでよく使われるeot, woff, woff2などがあります。

画像の「中央」にテキストを表示したい

先ほどのプログラムでは位置を自分で指定しなければなりませんでした。これだと画像の「中央」にテキストを表示したい場合に具合が悪いです。 そこで画像サイズとテキストの縦横幅を取得して、計算して「中央」にテキストを表示できるようにしてみました。

test_overlay_b.py
from PIL import Image,ImageFont,ImageDraw
 
image_path = 'fuji.jpg' # 文字を重ねる画像
out_path = 'b.jpg' # 出力先

font_path = '/System/Library/Fonts/ヒラギノ角ゴシック W5.ttc'
font_size = 100
font_color = (255,255,255) #文字の色
text = '新倉山浅間公園'

font = ImageFont.truetype(font_path, font_size)

image = Image.open(image_path)
draw = ImageDraw.Draw(image)

(font_w, font_h), (offset_x, offset_y) = font.font.getsize(text)
img_w, img_h  = image.size

print("{},{},{},{}".format(font_w, font_h, img_w, img_h))

pos = ((img_w - font_w) / 2, (img_h - font_h) / 2)

draw.text(pos, text, font=font, fill=font_color)
image.save(out_path)

テキストを中央に表示
テキストを中央に表示

はい。いいかんじでキレイに画像の中央にテキストを表示できましたね。

この部分でフォントの縦横幅を取得しているのがポイントです。

py
(font_w, font_h), (offset_x, offset_y) = font.font.getsize(text)
img_w, img_h  = image.size
offset_xoffset_y に関しては下記URLで詳しく説明されてますのでご参考に。

python - How to get the font pixel height using PIL's ImageFont class? - Stack Overflow

【おまけ】テキストに枠線をつけたい

さいごに、テキストの枠線を表現できたら良いですよね?borderとかstroke、outlineとか呼び方はさまざまありますが、よく使われるアレです。

枠線を処理するにはこんな感じのプログラムでいけちゃいます。

test_overlay_c.py
from PIL import Image,ImageFont,ImageDraw
 
image_path = 'fuji.jpg' # 文字を重ねる画像
out_path = 'c.jpg' # 出力先

font_path = '/System/Library/Fonts/ヒラギノ角ゴシック W7.ttc'
font_size = 100
font_color = (255,255,255) # 文字の色
stroke_color = (33, 33, 33) # 枠線の色
text = '新倉山浅間公園'

stroke_width = 10

font = ImageFont.truetype(font_path, font_size)

image = Image.open(image_path)
draw = ImageDraw.Draw(image)

font_w, font_h = font.getsize(text, stroke_width=stroke_width)
img_w, img_h  = image.size

print("{},{},{},{}".format(font_w, font_h, img_w, img_h))

pos = ((img_w - font_w) / 2, (img_h - font_h) / 2)

draw.text(
    pos, text,
    font=font, 
    fill=font_color,
    stroke_width=stroke_width,
    stroke_fill=stroke_color)
image.save(out_path)

デザイン性はともあれ、なんとか枠線がつきました!

テキストに枠線を追加
テキストに枠線を追加

いかがだったでしょうか? Pillowを使って簡単に画像に文字を重ねることができました。この他にも画像に画像を重ねたり、図形を描画したりもできるはずです。 ▼ 続きの「Pythonでサムネ制作 第二弾」を追記しました!

関連記事

最後までご覧いただきありがとうございます!

▼ 記事に関するご質問やお仕事のご相談は以下よりお願いいたします。
お問い合わせフォーム

Pandasで画像・動画処理をはじめよう!
Python学習にオススメの本をご紹介!
関連記事