3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Python】PIL(Pillow)で画像に文字を描く

Posted at

はじめに

pythonのPILで画像に文字を入れたかったときに調べたことのメモです。

結論から

200×100の透明の画像に枠を描き中央に"Hello.World!"と描きます。
img.png

draw text
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

text = "Hello,World!"
fontFile = "Menlo-Regular.ttf"
fontSize = 24
mode = "RGBA"
whidth, hight = (200, 100)
baseColor = (0, 0, 0, 0)
lineColor = (0, 0, 255, 255)
textColor = (255, 0, 0, 255)

im = Image.new(mode, (whidth, hight), baseColor)
dr = ImageDraw.Draw(im)
dr.rectangle((0,0,whidth - 1, hight - 1), baseColor, lineColor)
dr.line((0, hight//2, whidth, hight//2), lineColor)
dr.line((whidth//2, 0, whidth//2, hight), lineColor)

font = ImageFont.truetype(fontFile, fontSize)
textWidth,textHight = dr.textsize(text, font)
text_x = (whidth - textWidth) // 2
text_y = (hight - textHight) // 2
dr.text((text_x, text_y), text, textColor, font=font)

説明

記事を書いてるときは覚えているのですが、すぐに忘れてしまうので細かく分解して説明しておきます。

透明の画像をつくる

新しく画像をつくるには、Image.new(mode, size, color)を使います。

mode 一覧
mode 説明
1 1 ビット ピクセル、白黒、1 バイトあたり 1 ピクセルで格納
L 8 ビット ピクセル、白黒
P  8 ビット ピクセル、カラー パレットを使用して他のモードにマッピング
RGB 3x8 ビット ピクセル、トゥルーカラー
RGBA 4x8 ビット ピクセル、透過マスク付きトゥルーカラー
CMYK 4x8 ビット ピクセル、4色分解
YCbCr 3x8 ビット ピクセル、カラー ビデオ形式
Note これは、ITU-R BT.2020 標準ではなく、JPEG を参照していること
LAB 3x8 ビット ピクセル、Lab 色空間
HSV 3x8 ビット ピクセル、色相、彩度、値の色空間
I 32 ビットの符号付き整数ピクセル
F 32 ビット浮動小数点ピクセル
追加モード 次のようないくつかの追加モードを限定的にサポートします。
LA アルファ付きの L
PA アルファ付きの P
RGBX パディング付きのトゥルーカラー
RGBa プレマルチプライド アルファを使用したトゥルーカラー
La 事前に乗算されたアルファを持つ L
I;16 16 ビット符号なし整数ピクセル
I;16L 16 ビットのリトルエンディアン符号なし整数ピクセル
I;16B 16 ビット ビッグ エンディアンの符号なし整数ピクセル
I;16N 16 ビット ネイティブ エンディアン符号なし整数ピクセル
BGR;15 15 ビット反転 True Color
BGR;16 16 ビット反転 True Color
BGR;24 24 ビット反転 True Color
BGR;32 32 ビット反転 True Color
make image
from PIL import Image

mode = "RGBA"                           # モード
whidth, hight = (200, 100)              # 幅、高さ
size = (whidth, hight)                  # サイズ
baseColor = (0, 0, 0, 0)                # 色
im = Image.new(mode, size, baseColor)   # 画像を生成
im.save("img_0.png")                    # 画像を保存

よく使うmode"RGBA""L"くらいです。

長方形を描く

長方形を描くには次のメソッドを使います。
ImageDraw.rectangle(xy, fill=None, outline=None, width=1)

パラメータ
パラメータ 意味
xy 境界ボックスを定義する 2 つのポイント。 [(x0, y0), (x1, y1)] または [x0, y0, x1, y1] のシーケンス。境界ボックスには両方の端点が含まれます。
outline アウトラインに使用する色。
fill 塗りつぶしに使用する色
width ライン幅 (ピクセル単位)
draw rectangle
from PIL import Image
from PIL import ImageDraw

im = Image.open("img_0.png")            # 画像を開く
dr = ImageDraw.Draw(im)                 # 描画オブジェクトを生成
whidth, hight = im.size                 # 画像の幅と高さ
box = (0, 0, whidth - 1, hight - 1)     # 境界ボックス
fillColor = (0, 0, 0, 0)                # 塗りつぶしの色
lineColor = (0, 0, 255, 255)            # 線の色
dr.rectangle(box, fillColor, lineColor) # 長方形を描画
im.save("img_1.png")                    # 画像を保存

左上の座標がが(0,0)で、境界ボックスには両方の端点が含まれるので、画像サイズが256 × 256の場合の最大の長方形なら、(0, 0 ,255, 255)と指定します。
なので、box = (0, 0, width - 1, hight - 1)になります。

線を描く

線を描くには次のメソッドを使います。
ImageDraw.line(xy, fill=None, width=0, joint=None)

パラメータ
パラメータ 意味
xy [(x, y), (x, y), ...] のような 2 タプルまたは [x, y, x, y, ...] のような数値のシーケンス。
fill 線に使用する色。
width ライン幅 (ピクセル単位)
joint 一連のライン間のジョイント タイプ。丸みを帯びたエッジの場合は「curve」にするか、None にすることができます。
draw line
from PIL import Image
from PIL import ImageDraw

im = Image.open("img_1.png")            # 画像を開く
dr = ImageDraw.Draw(im)                 # 描画オブジェクトを生成
whidth, hight = im.size                 # 画像の幅と高さ
lineColor = (0, 0, 255, 255)            # 線の色
centerX = whidth // 2                   # 左右の中央
centerY = hight // 2                    # 上下の中央
xy = ((centerX, 0), (centerX, hight))   # 縦線の始点と終点
dr.line(xy, lineColor)                  # 縦線を描画
xy = ((0,centerY), (whidth, centerY))   # 横線の始点と終点
dr.line(xy, lineColor)                  # 横線を描画
im.save("img_2.png")                    # 画像を保存

画面中央に文字を描く

文字を描画するだけならImageDrawモジュールだけでもできるのですが、文字のフォントを指定する場合はImageFontを使います。
ImageFont.truetype(font=None, size=10, index=0, encoding='', layout_engine=None)

パラメータ
パラメータ 意味
font TrueType フォントを含むファイル名またはファイルのようなオブジェクト。ファイルがこのファイル名で見つからない場合、ローダーは、Windows の fonts/ ディレクトリや、macOS の /Library/Fonts/、/System/Library/Fonts/、および ~/Library/Fonts/ などの他のディレクトリも検索する場合があります。
size 要求されたサイズ (ピクセル単位)。
index ロードするフォント フェース (デフォルトは最初に利用可能なフェース)。
encoding 使用するフォント エンコーディング (デフォルトは Unicode)。可能なエンコーディングには次のものがあります (詳細については、FreeType のドキュメントを参照してください)。[”unic” (Unicode),”symb” (Microsoft Symbol),”ADOB” (Adobe Standard),”ADBE” (Adobe Expert),”ADBC” (Adobe Custom),”armn” (Apple Roman),”sjis” (Shift JIS),”gb “ (PRC),”big5”,”wans” (Extended Wansung),”joha” (Johab),”lat1” (Latin-1)]
使用する文字セットを指定します。後続の操作で提供されるテキストのエンコーディングは変更されません。
layout_engine] 利用可能な場合、使用するレイアウト エンジン: ImageFont.Layout.BASIC または ImageFont.Layout.RAQM。利用可能な場合、Raqm レイアウトがデフォルトで使用されます。それ以外の場合は、基本レイアウトが使用されます。
英語以外のすべてのテキストには、Raqm レイアウトをお勧めします。 Raqm レイアウトが不要な場合は、基本レイアウトの方がパフォーマンスが高くなります。
feature="raqm"と共にPIL.features.check_feature()を使用して、Raqm レイアウトのサポートを確認できます。
draw text
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

text = "Hello,World!"                   # 描画したい文字
fontFile = "Menlo-Regular.ttf"          # フォントファイル
fontSize = 24                           # フォントサイズ
im = Image.open("img_2.png")            # 画像を開く
dr = ImageDraw.Draw(im)                 # 描画オブジェクトを生成

# フォント オブジェクトを作成します。
fnt = ImageFont.truetype(fontFile, fontSize)

# 文字の幅と高さを取り出します。
textWidth, textHight = dr.textsize(text, font=fnt)
whidth, hight = im.size                 # 画像の幅と高さ
textColor = (255, 0, 0, 255)            # 文字の色
text_X = (whidth - textWidth) // 2      # 文字の左端座標
text_Y = (hight - textHight) // 2       # 文字の上端座標

# 画像の中央に文字を描画します。
dr.text((text_X, text_Y), text, textColor, font=fnt)

im.save("img_3.png")                    # 画像を保存

フォントを指定しないとデフォルトのビットマップフォントが使われます。
dr.text((text_X, text_Y), text, textColor)
その場合、文字のサイズを知ることができないので、文字の位置指定が雑になります。

参考にさせていいただきました。

Pillow (PIL Fork) 9.3.0 documentation

Python, Pillowで文字(テキスト)を描画、フォント設定 | note.nkmk.me

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?