次の2つの方法を使用して、設定されたフォントタイプとサイズのサンプル文字列のレンダリングwidthを計算します。
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 14)
sample = "Lorem ipsum dolor sit amet, partem periculis an duo, eum lorem paulo an, mazim feugiat lobortis sea ut. In est error eirmod vituperata, prima iudicabit rationibus mel et. Paulo accumsan ad sit, et modus assueverit eum. Quod homero adversarium vel ne, mel noster dolorum te, qui ea senserit argumentum complectitur. Duo at laudem explicari deterruisset, eu quo hinc mnesarchum. Vel autem insolens atomorum at, dolorum suavitate voluptatum duo ex."
#METHOD 1
draw_txt = ImageDraw.Draw(img)
width, height = draw_txt.textsize(sample, font=font)
print width
#METHOD 2
width = 0
for c in sample:
width += font.getsize(c)[0]
print width
METHOD 1
は3236
の幅を生成しますが、METHOD 2
は3270
を生成します。なぜ矛盾があるのですか?さらに、サンプルテキストが短いほど、これら2つの方法の不一致が小さくなることにも気付きました。
フードの下で何が起こっているのですか?そして、どの幅は、レンダリングされた文のtrue幅と考えることができますか?最後に、両方のメソッドがほぼ同じ幅をレポートするようにするためのTweakはありますか?
注:サンプルテキストは445文字です
ここでは2つの異なることを行っています。
モノスペースフォントを使用している場合、状況は異なる可能性がありますが、フォントは一般にkerningと呼ばれるものを使用して、テキストを滑らかにし、少しきつめにします。
Wikipedia さんのコメント:
タイポグラフィでは、kerningはプロポーショナルフォントの文字間の間隔を調整するプロセスであり、通常は視覚的に満足のいく結果が得られます。カーニングは個々の文字フォーム間のスペースを調整し、トラッキング(文字間隔)は文字の範囲にわたって間隔を均一に調整します。適切にカーニングされたフォントでは、文字の各ペア間の2次元の空白スペースはすべて、視覚的に類似した領域を持っています。
これが DejaVuSansフォントのカーニング です。
内部的には、Pillowは2つの方法で大きな違いはありません。それはあなたが彼らを異なる方法で呼んでいるだけです。
3番目のメソッドを追加して、メソッド2と同じ関数を使用して文全体の幅を取得すると、メソッド1と同じように文全体を取得する場合と同じ幅が得られます。
# METHOD 3
width = font.getsize(sample)[0]
print width
これが枕の ImageDraw.textsize
(メソッド1と3から)です。
def textsize(self, text, font=None, *args, **kwargs):
"""Get the size of a given string, in pixels."""
if self._multiline_check(text):
return self.multiline_textsize(text, font, *args, **kwargs)
if font is None:
font = self.getfont()
return font.getsize(text)
1行のテキストの場合、これはfont.getsize
を返すだけであり、メソッド2と同じです。 (また、複数行のテキストの場合、テキストを行に分割し、いくつかのfont.getsize
呼び出しの合計を返します。)