2017-05-07 96 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调用的总和。)