サイトロゴ

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

著者画像
Toshihiko Arai

はじめに

ブログや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.

https://pillow.readthedocs.io/en/stable/

Pillowのインストール

$ pip3 install Pillow

画像の上に文字を表示

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

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

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

$ 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
$ ls /Library/Fonts/
Arial Unicode.ttf   BROOKH2.ttf     BauhausBoldItalic.ttf   BauhausRegular.ttf
BAUHHL.ttf      BauhausBold.ttf     BauhausItalic.ttf
$ 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

フォントのタイプ

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

拡張子 意味
.ttf TrueTypeフォント
.otf OpenTypeフォント
.ttc TrueTypeフォントを1つのファイルにまとめたもの
.otc OpenTypeフォントを1つのファイルにまとめたもの

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

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

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

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)

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

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

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

offset_xoffset_y に関しては下記URLで詳しく説明されてますのでご参考に。

https://stackoverflow.com/questions/43060479/how-to-get-the-font-pixel-height-using-pils-imagefont-class

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

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

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

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を使って簡単に画像に文字を重ねることができました。この他にも画像に画像を重ねたり、図形を描画したりもできるはずです。

関連記事