2017-05-07 122 views
4

我使用以下兩種方法來計算一個樣本串的渲染寬度用於一組字體類型和大小:測量文本的寬度(Python的/ PIL)

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。爲何差異?此外,我還注意到樣本文本越短,這兩種方法之間的差異越小。

這是怎麼回事?而且哪個寬度可以認爲是true渲染句子的寬度?最後,我可以做兩種方法報告大致相同的寬度嗎?

注:示範文本是長

回答

5

字距

你在這裏做什麼兩回事445個字符:

  • 查找長文本的寬度。
  • 找到所有字符的寬度,而盲目地加入他們一起

如果你使用的是等寬字體,事情可能會有所不同,但字體一般使用一種叫做字距使文字更順暢,有點緊。

Wikipedia說:

在排版,字距是調整字符之間的間隔成比例的字體,通常以實現視覺上令人愉悅的結果的過程。克寧調整單個字母表單之間的空間,而跟蹤(字母間距)則統一調整字符範圍內的間距。在一個字體良好的字體中,每對字符之間的二維空白區域都具有視覺上相似的區域。

Kerning brings A and V closer with their serifs over each other

下面是一些kerning of the DejaVuSans font

font kerning showing different char widths

引擎蓋下

引擎蓋下,枕頭是不是做了你的兩個方法非常不同。只是你用不同的方式給他們打電話。

如果增加第三個方法來獲得使用相同的功能,在方法二中全句的寬度,你也將得到同樣的寬度,讓整個句子在方法一:

# METHOD 3 
width = font.getsize(sample)[0] 
print width 

這裏的枕頭的ImageDraw.textsize(從方法一和三):

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) 

對於單行文本,這只是返回font.getsize,同爲法兩種。 (對於多行文本,它只是將它拆分成多行,並返回幾個font.getsize調用的總和。)