【Pillow/Python】textメソッドで描画する文字のフォントやサイズを変更する

Pillowのtextメソッドで描画する文字列のフォントやサイズの変更方法の解説ページアイキャッチ

このページにはプロモーションが含まれています

このページでは、Python の画像処理ライブラリの1つである Pillow のフォントについて説明していきます。

Pillow では ImageDraw モジュールの text メソッドを利用することで画像に文字列を描画することが可能です。そして、この text メソッドでは font 引数を指定することで描画する文字列のフォントやサイズを指定することが可能です。

text メソッドに関しては下記ページで詳しく説明していますので、text メソッドの全般的な使い方に関しては下記ページをご参照いただければと思います。このページではフォントに焦点を当てて解説していきます。

PIllowでの画像への文字列の描画の仕方の解説ページアイキャッチ 【Python/Pillow】画像に文字列を描画する(textメソッド)

例えば Mac であれば、下の図のようにフォントを Menlo や Helvetica に変更したり、

textで描画する文字列のフォントを変更する様子1

Windows であれば下の図のようにフォントをメイリオや MS ゴシックに変更したりするようなことができます。

textで描画する文字列のフォントを変更する様子2

また、同じフォントであっても、太字や斜体など細かなフォント指定も可能です。

textで描画する文字列のフォントを変更する様子3

さらに、フォントのサイズ(文字のサイズ)の変更も行うことができます。

textで描画する文字列のフォントを変更する様子4

では、これらのフォントやサイズの変更はどのようにすれば実現できるのでしょうか?

このページでは、上記で説明したようなフォント・サイズの変更方法について詳しく・分かりやすく解説していきます!上記のような Pillow でのフォントの扱い方に関して興味のある方は是非ページを読み進めていっていただければと思います!

フォントの変更(ImageFont

まずは、Pillow で文字列を描画する text メソッドにおける “フォントを変更する” 方法について説明していきます。

この text メソッドは ImageDraw モジュールで定義される Draw クラスのメソッドになります。text メソッドに関しての詳細については別途下記ページで解説していますので、text メソッド自体について知りたい方は下記ページを参照していただければと思います。

PIllowでの画像への文字列の描画の仕方の解説ページアイキャッチ 【Python/Pillow】画像に文字列を描画する(textメソッド)

例えば下記は、msg 変数の参照する文字列を画像に描画するスクリプトの例となります。

textメソッド
from PIL import Image, ImageDraw

msg = 'Hello!'

# Imageオブジェクトの生成
image = Image.new('RGB', (200, 100), 'lightgray')

# Drawオブジェクトの生成
drawer = ImageDraw.Draw(image)

# 文字列の描画(textメソッドを実行)
drawer.text(xy=(0, 0), text=msg, fill='black')

# 文字列描画後の画像を表示
image.show()

実行すれば、下図のように灰色背景の画像に Hello という文字列が描画されることになります。今回は灰色背景の画像を使ってフォントについて説明していきますが、Image.new ではなく Image.open を利用して Image オブジェクトを生成するようにすれば任意の画像に文字列を描画することも可能となります。

textメソッドによって画像に文字列が描画される様子

文字列の描画は行えましたが、ちょっと文字のサイズが小さいですね…。また、もしかしたらフォントも気に入ってないかもしれません。

こういったフォントや文字のサイズに関しては、text メソッドに font 引数を指定することで変更することが可能です。そして、この font 引数にはフォントオブジェクトを指定します。つまり、text メソッドで描画される文字列のフォントは、この font 引数に指定するフォントオブジェクトによって決まることになります。

したがって、好みのフォントやサイズに応じたフォントオブジェクトを生成し、それを text メソッド実行時に font 引数に指定するようにすることで、自由自在に描画する文字列のフォントやサイズを変更することができるようになります。

font引数に指定するフォントオブジェクトに応じて文字列の描画結果が異なる様子

ということで、Pillow で描画する文字列のフォントを変更するためには、まずはフォントオブジェクトを生成してやる必要があることになります。

MEMO

文字のサイズに関しては font 引数の指定以外の手段で変更することも可能です

これに関しては後述で解説します

フォントオブジェクトの生成

では、フォントオブジェクトはどのようにして生成すれば良いでしょうか?

次は、この点について説明していきます。

ImageFont.truetype 関数で生成

他にもやり方はあると思いますが、おそらく一番一般的なフォントオブジェクトの生成方法は ImageFont モジュールを利用する方法になると思います。ImageFont モジュールには truetype 関数が用意されており、この truetype 関数よりフォントオブジェクトを生成することが可能です。

そして、この truetype 関数では font 引数(第1引数)に利用したいフォントの “ファイルパス” を指定することで、そのフォントに基づいたフォントオブジェクトを生成することができます。

ImageFont.truetype関数がフォントオブジェクトを生成する様子

フォントの実体はファイルであり、その中で文字の形状などが定義されています。font 引数でファイルパスを指定することで、そのファイルに基づいたフォントオブジェクトを生成することが可能となります。このファイルの拡張子は .ttc.ttf の場合がありますが、拡張子は省略して指定しても問題ありません。拡張子を省略した場合は単なるフォント名になる場合が多いです。

例えば MacOSX ではフォントのファイルとして Helvetica.ttc が標準で用意されているはずで、この 'Helvetica.ttc'font 引数に指定してやることでフォントが Helvetica であるフォントオブジェクトを生成することができます。拡張子を省略して 'Helvetica' を指定しても問題ありません。

ImageFont.truetype関数がフォントオブジェクトを生成する様子

そして、このフォントオブジェクトを font 引数に指定して text メソッドを実行すればフォント Helvetica で文字列を描画することができます。

フォントオブジェクトに基づいたフォントで文字列が描画される様子

こんな感じで、フォントのファイルパスを引数に指定して ImageFont.truetype 関数を実行してフォントオブジェクトを生成し、それを font 引数に指定して text メソッドを実行するのがフォントを指定した文字列描画の基本的な流れとなります。

指定可能なフォントのファイルパス

では、具体的に ImageFont.truetype 関数の font 引数に指定可能なパスにはどんなものがあるのでしょうか?

おそらく、Pillow でフォントを扱う上で一番難しいのはココになると思います。なぜ難しいのかというと、それは使用している PC によって指定可能なパスが異なるからになります。要は PC にインストールされているフォントのファイルパスのみを指定することが可能で、それ以外を指定すると例外が発生することになります。

特に OS によってインストールされているファイルが異なるため注意が必要になります。例えば上記の例で示した 'Helvetica.ttc' は Mac をお使いの方であれば問題ありませんが、Windows を利用されている場合は指定すると例外が発生することになると思います。少なくとも私の PC で試したら例外が発生しました…。

  File "C:\Users\daeu\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\PIL\ImageFont.py", line 245, in __init__
    self.font = core.getfont(
                ^^^^^^^^^^^^^
OSError: cannot open resource

では、自身の PC で font 引数に指定可能なパスは具体的に何になるのでしょうか?

これを知る一番確実な方法はフォントのインストール先フォルダを実際に調べてみることになると思います。そのフォルダに存在するファイルのファイル名が、基本的に font 引数に指定可能なパスであると言えます。

そして、このフォントのインストール先フォルダは OS によって異なります。具体的な OS 毎のフォントのインストール先フォルダは下記となります。WINDIR は Windows の環境変数として定義されているパスであり、基本的には C:¥windows¥ と定義されており、この場合の %WINDIR%¥fonts は C:¥Windows¥fonts を指すことになります。

  • WIndows:
    • %WINDIR%¥fonts
  • Mac:
    • /Library/Fonts/
    • /System/Library/Fonts/
    • ~/Library/Fonts/

要は、ImageFont.truetype を実行した際には、font 引数に指定されたパスを上記フォルダからの相対パスとしてファイルの検索が行われ、そのファイルが存在する場合はそのファイルからフォントの定義を読み込み、text メソッド実行時にそのフォントの定義に従って文字列が描画されることになります。

font引数で指定したパスのファイルが読み込まれてフォントオブジェクトが生成される様子

そのため、font 引数に指定されたパス(上記のフォルダから見た相対パス)にファイルが存在しなければ ImageFont.truetype 関数で例外が発生することになります。逆に言えば、上記のフォルダに存在するファイルであれば、そのフォルダからの相対パスを font 引数に指定してやれば基本的に ImageFont.truetype の実行は成功すると考えられます。そのため、font 引数に指定可能なパスを調べたい場合は、まずは上記のフォルダの中に存在するファイルを調べてみると良いでしょう。

MEMO

上記では相対パスに対する説明に限定していますが、実際には直接フォントのファイルのパスを絶対パスで指定することも可能です

この場合、前述で示したフォルダ以外に存在するフォントも利用することが可能です

少し説明が長くなりましたが、Windows の場合、例えば下記を実行すれば MS ゴシックのフォントで文字列が描画されることになります。

MSゴシックでの文字列描画
from PIL import Image, ImageDraw, ImageFont

# 使用するフォント
font_name = 'msgothic.ttc'

# 描画する文字列
msg = 'Hello!'

# Imageオブジェクトの生成
image = Image.new('RGB', (200, 100), 'lightgray')

# Drawオブジェクトの生成
drawer = ImageDraw.Draw(image)

# フォントオブジェクトの生成
font = ImageFont.truetype(font=font_name)

# 文字列の描画(textメソッドを実行)
drawer.text(xy=(0, 0), text=msg, fill='black', font=font)

# 文字列描画後の画像を表示
image.show()

スクリプトを実行して表示される画像は下図のようなものになります。

フォントMSGothicで文字列を描画した結果

また、Mac の場合、上記スクリプトの下記を実行すれば Helvetica のフォントで文字列が描画されることになります。

Helveticaでの文字列描画
from PIL import Image, ImageDraw, ImageFont

# 使用するフォント
font_name = 'Helvetica.ttc'

# 描画する文字列
msg = 'Hello!'

# Imageオブジェクトの生成
image = Image.new('RGB', (200, 100), 'lightgray')

# Drawオブジェクトの生成
drawer = ImageDraw.Draw(image)

# フォントオブジェクトの生成
font = ImageFont.truetype(font=font_name)

# 文字列の描画(textメソッドを実行)
drawer.text(xy=(0, 0), text=msg, fill='black', font=font)

# 文字列描画後の画像を表示
image.show()

こちらのスクリプトを実行して表示される画像は下図のようなものになります。文字が小さいのでフォントの違いが分かりにくいですが、後述で紹介する手順でフォントサイズを大きくしてやればフォントによる違いがより明確になります。

フォントHelveticaで文字列を描画した結果

ここまでの説明の通り、使用する PC、特に OS によって font 引数に指定可能なパスが異なります。ここから紹介するスクリプトでは基本的に font 引数に 'Helvetica.ttc' を指定する例を示していきますので、特に Windows を利用されている場合は font 引数に指定するパスを自身の PC で使用可能なものに置き換えてから実行するようにしてください。

スポンサーリンク

スタイル(太字や斜体)の指定

先ほど説明したように、font 引数(第1引数)に使用したいフォントのファイルのパスを指定して ImageFont.truetype 関数を実行することでフォントオブジェクトを生成することが可能です。

そして、そのフォントオブジェクトを text メソッド実行時に font 引数へ指定してやることで、描画する文字列のフォントを ImageFont.truetype 関数の font 引数に指定したファイルのフォントに変更することが可能となります。

ただ、Word や Power Point 等では文字列のフォントだけでなく、太字や斜体等のスタイルを設定することも可能です。Pillow で文字列を描画する際には、こういったスタイルを設定することはできないのでしょうか?

結論としては「できる」が答えとなります。ここからは、この “フォントのスタイル” の指定方法について説明していきます。

index 引数でフォントのスタイルを指定

前述の通り、ImageFont.truetype 関数でフォントオブジェクトを生成する際にはフォントのファイルのパスを指定して実行する必要があります。そして、このフォントのファイルには、実は複数種のフォントが定義されています。より具体的には、ファイルには太字や斜体・太字かつ斜体等の複数のスタイルのフォントが定義されています。

フォントファイルに複数のスタイルが定義されている様子

ImageFont.truetype 関数の index 引数

ImageFont.truetype 関数でフォントオブジェクトを生成する際に font 引数のみを指定した場合、生成されるフォントオブジェクトは指定したファイルの標準的なスタイルのフォントに基づいたものになります。

ですが、前述の通りファイルには複数のスタイルが定義されており、それらのスタイルの中から好みのものを指定してフォントオブジェクトを生成することも可能です。したがって、そのスタイルさえ指定さえしてやれば太字や斜体のフォントオブジェクトも生成することができます。

index 引数とスタイルの対応の調べ方

で、このスタイルは ImageFont.truetype 関数の index 引数によって指定することが可能です。index 引数には整数を指定します。

スタイルをindex引数で指定する様子

では、具体的に太字にしたい場合や斜体にしたい場合は index 引数に何を指定すれば良いのでしょうか?

これは実は一概には言えなくて、ファイル(フォント種)によって異なります。ですが、index 引数とスタイルとの対応は自力で簡単に調べることができます。

フォントオブジェクトには getname というメソッドが用意されており、このメソッドを実行すればフォントオブジェクトのフォント名だけでなく太字や斜体などのスタイル名を取得することができます。したがって、とりあえず index 引数に整数を指定し、その時に生成されるフォントオブジェクトから getname メソッドを実行させてやれば、その index 引数に対応するスタイルを確認することができます。ちょっと面倒ですが、スクリプトを用意しておけば調べるのも楽になると思います。

具体的には下記のようなスクリプトを用意してやれば、font_path に指定したファイルにどんなフォントが定義されているかを確認することが可能となります。

定義されているスタイルの確認
from PIL import ImageFont

# フォントのパス
font_path = 'Helvetica.ttc'

for i in range(100):

    try:
        # index=iでフォントオブジェクトを生成してみる
        font = ImageFont.truetype(font=font_path, index=i)
    except OSError:
        # 例外が発生したらindex=iのフォントは存在しないのでループ終了
        break

    # フォントファミリーとフォントスタイルを出力
    print(font.getname())

例えば上記のように font_path'Helvetica.ttc' を指定した場合、スクリプトを実行して出力される結果は下記のようになります。

('Helvetica', 'Regular')
('Helvetica', 'Bold')
('Helvetica', 'Oblique')
('Helvetica', 'Bold Oblique')
('Helvetica', 'Light')
('Helvetica', 'Light Oblique')

この結果より、Helvetica.ttc には6種類のスタイルが定義されていることが確認できます。Regular が標準、Bold が太字、Oblique が斜体、Light が細字を意味しますので、例えば太字のスタイルで描画したいのであれば index=1 を、細字&斜体のスタイルで描画したいのであれば index=5 を指定して ImageFont.truetype 関数を実行してやれば良いことになります。

実際に、Helvetica の太字と細字&斜体のスタイルで描画を行うスクリプトの例が下記となります。

スタイルの指定
from PIL import Image, ImageDraw, ImageFont

# 使用するフォント
font_name = 'Helvetica.ttc'

# 描画する文字列
msg = 'Hello!'

# Imageオブジェクトの生成
image = Image.new('RGB', (200, 100), 'lightgray')

# Drawオブジェクトの生成
drawer = ImageDraw.Draw(image)

# 太字で描画
font = ImageFont.truetype(font=font_name, index=1)
drawer.text(xy=(20, 20), text=msg, fill='black', font=font)

# 細字&斜体で描画
font = ImageFont.truetype(font=font_name, index=5)
drawer.text(xy=(20, 60), text=msg, fill='black', font=font)

# 文字列描画後の画像を表示
image.show()

実行すれば Hello! という文字列が2つ描画されている画像が表示されるはずです。そして、それぞれの文字列が太字・細字&斜体のスタイルで描画されていることが確認できると思います。ちょっとサイズが小さくて分かりにくいかも…。

太字・細字&斜体で文字列を描画した結果

前述でも説明しましたが、定義されているスタイルの種類はフォント(のファイル)によって異なるので注意してください。例えば Menlo の場合は、下記の4つしかスタイルが定義されていません(さらに斜体が Italic で表現されています)。

('Menlo', 'Regular')
('Menlo', 'Bold')
('Menlo', 'Italic')
('Menlo', 'Bold Italic')

また、フォント(のファイル)によってはスタイル毎にファイルが別れている場合があります。例えば Mac には Times New Roman のフォントのファイルが下記のように複数用意されており、スタイル毎にファイルが別れていることが確認できます。

Times New Roman Bold Italic.ttf
Times New Roman Bold.ttf
Times New Roman Italic.ttf
Times New Roman.ttf

こういった背景より、スタイルを適切に使い分けるようにするためには、事前に前述で示したようなスクリプトでフォントのファイルで定義されているスタイルを調べておいた方が良いと思います。

フォントのサイズの変更

続いてフォントのサイズの変更方法について説明してきます。

ちょっとここまでの話は複雑だったかもしれませんが、フォントのサイズの変更に関しては単純明快です。

スポンサーリンク

ImageFont.truetype 関数の size 引数で指定

フォントのサイズの変更に関しては2つの方法を紹介していきます。1つ目が、ImageFont.truetype を実行する際に size 引数を指定する方法になります。要は、フォントオブジェクトを生成する際にフォントのサイズを指定します。size 引数にはピクセル数を整数で指定します。

サイズをsize引数で指定する様子

これにより、そのフォントオブジェクトを font 引数に指定して text メソッドを実行してやれば、size 引数で指定したサイズの文字が描画されることになります。size 引数のデフォルト値は 10 になりますので、より大きな文字を描画したいのであれば 10 よりも大きい整数を指定してやれば良いことになります。

例えば下記を実行すればフォントサイズ 20 とフォントサイズ 40 とで文字列を描画した結果が表示されることになります(前者は太字、後者は細字&斜体のスタイルを適用しています)。

フォントサイズの指定
from PIL import Image, ImageDraw, ImageFont

# 使用するフォント
font_name = 'Helvetica.ttc'

# 描画する文字列
msg = 'Hello!'

# Imageオブジェクトの生成
image = Image.new('RGB', (200, 100), 'lightgray')

# Drawオブジェクトの生成
drawer = ImageDraw.Draw(image)

# サイズ20・太字で描画
font = ImageFont.truetype(font=font_name, size=20, index=1)
drawer.text(xy=(20, 20), text=msg, fill='black', font=font)

# サイズ40・細字&斜体で描画
font = ImageFont.truetype(font=font_name, size=40, index=5)
drawer.text(xy=(20, 60), text=msg, fill='black', font=font)

# 文字列描画後の画像を表示
image.show()

このスクリプトを実行して表示される画像は下の図のようなものになります。上側の文字列はフォントサイズ 20 で、下側の文字列のフォントサイズ 40 で描画しており、文字の大きさが異なることが確認できると思います。

サイズ20&サイズ40で文字列を描画した結果

text メソッドの font_size 引数で指定

ここまで説明してきたように、ImageFont.truetype 関数でフォントオブジェクトを生成することによって描画する文字列のフォントやスタイル、さらにはサイズ等を指定することが可能となります。

まぁでも、フォントオブジェクトを生成するのは面倒ですし、何より font 引数に指定可能なパスを自分で調べる必要があって手順が複雑です。

そんな方に朗報です。最新の Pillow (バージョン 10.1.0 以降) であれば、フォントのサイズの変更はフォントオブジェクトの生成なしに実現可能です。続いては、フォントオブジェクトの生成を行わずにフォントのサイズを変更する方法について説明します。

手順は簡単で、text メソッド実行時に font_size 引数を指定してやれば良いだけになります。font_size 引数には整数を指定します。この際には、フォントとしてはデフォルト設定のものが使用されることになります。

サイズをtextメソッドのfont_size引数で指定する様子

例えば下記を実行すればフォントサイズ 20 とフォントサイズ 40 とで文字列を描画した結果が表示されることになります。

textメソッドでのフォントサイズの指定
from PIL import Image, ImageDraw

# 描画する文字列
msg = 'Hello!'

# Imageオブジェクトの生成
image = Image.new('RGB', (200, 100), 'lightgray')

# Drawオブジェクトの生成
drawer = ImageDraw.Draw(image)

# サイズ20で描画
drawer.text(xy=(20, 20), text=msg, fill='black', font_size=20)

# サイズ40・細字&斜体で描画
drawer.text(xy=(20, 50), text=msg, fill='black', font_size=40)

# 文字列描画後の画像を表示
image.show()

このスクリプトを実行して表示される画像は下の図のようなものになります。上側の文字列はフォントサイズ 20 で、下側の文字列のフォントサイズ 40 で描画しており、text メソッドの引数でも文字の大きさを変更できることが確認できると思います。

font_size引数の指定によってサイズ20&サイズ40で文字列を描画した結果

こんな感じで、フォントのサイズを変更したいだけであれば text メソッドの引数指定のみで実現することが可能です。この方法は、フォントオブジェクトを生成しなくて良いので、とにかく文字を大きくしたい場合などに活躍すると思います。それに対し、フォントやスタイルも指定したい場合はフォントオブジェクトを生成する方法を採用する必要があります。

また、text メソッドに font 引数を指定した場合、font_size 引数の指定は無視されるようになるので注意してください。font 引数を指定した場合は、font 引数に指定したフォントオブジェクトに設定されたフォントのサイズが優先されることになります。フォントオブジェクト生成時に size 引数を指定しなかったのであれば、デフォルト値の 10 のサイズが優先されることになります。

この辺りを頭に入れて、文字のサイズ変更の2つの方法を適切に使い分けていただければと思います!

まとめ

このページでは、Python の画像処理ライブラリの1つである Pillow のフォントについて説明しました!

Pillow では ImageDraw モジュールにおける Draw クラスの text メソッドにより画像に文字列を描画することが可能です。そして、その文字列のフォントやスタイル、さらにはサイズは text メソッドの font 引数の指定により変更することができます。

この font 引数にはフォントオブジェクトを指定する必要があり、このフォントオブジェクトは Pillow の ImageFont モジュールにおける truetype 関数から生成することができます。このフォントオブジェクト生成時にフォントやスタイル、さらにサイズを指定することで自由自在に描画する文字列のフォントを変更することができます。が、特に truetype 関数の font 引数(第1引数)に指定可能なパスが OS によって異なる点に注意してください。

また、サイズのみを変更するのであれば、フォントオブジェクトを用意する必要もなく、text メソッドの font_size 引数の指定で変更することが可能です。デフォルトのフォントのサイズが小さいので、とにかく大きい文字を描画したいのであれば text メソッドの font_size の指定のみで十分だと思います。最新の Pillow であれば、この方法でのフォントサイズの変更が可能ですので、是非このサイズ変更についても覚えておいてください!

同じカテゴリのページ一覧を表示