<p>因为您要处理字体,所以您需要了解<a href="https://pillow.readthedocs.io/en/stable/reference/ImageFont.html#PIL.ImageFont.PIL.ImageFont.ImageFont.getsize" rel="nofollow noreferrer">^{<cd1>}</a>方法。这将帮助您了解如何拆分文本。你知道吗</p>
<p>假设您有一个字符串:</p>
<pre><code>def get_a_string():
return "here is some string"
text = get_a_string()
</code></pre>
<p>现在,您还有一个图像,其宽度和高度为:</p>
<pre><code>bgcolor = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
img = Image.new('RGB', (300, 200), color=bgcolor)
# Read the size tuple, unpack into height, width
img_height, img_width = img.size
</code></pre>
<p>如果文本太长,应缩短:</p>
<pre><code>font = ImageFont.truetype("Arial.ttf", 14)
text_height, text_width = font.getsize(text)
if text_width > (0.95 * img_width):
# Not enough room. Break the text
lines = split_by_words()
</code></pre>
<p>你怎么能缩短它?首先,尝试使用单词边界:</p>
<pre><code>def split_by_words(text):
text = text.rstrip() # Strip trailing whitespace
words = text.split()
lines = []
while words:
# I use None instead of '' to allow for leading spaces
line = None
for i, word in enumerate(words):
new_line = word if line is None else line + ' ' + word
(h, w) = font.getsize(new_line)
if w > img_width:
# New line won't fit? Break, keeping old line value.
break
else:
# Still fits? Save it!
line = new_line
if i == 0:
# First word was too long. Try character-by-character
lines.extend(split_by_character(words[0]))
# TODO: You might want to put lines[-1] into words[0] to join long first word
# remainder with short second word.
words = words[1:]
else:
lines.append(line)
words = words[i:]
return lines
</code></pre>
<p>这会调用<code>getsize</code>很多次,这可能会很昂贵。(或不是:如果你是从猫图片中产生模因,可能不会花很多钱,因为文字很短。如果你在写文字处理器,当心!)你知道吗</p>
<p>另一种方法是计算原始文本的大小,然后假设所有字符的宽度相同,并根据图像大小与文本大小的比率猜测拆分的位置:</p>
<pre><code>th, tw = font.getsize(text)
ih, iw = img.size
ratio = iw / tw # 300 / 622, say
split_pos = int(len(text) * ratio) # 0.51 * text len, about halfway along
line1 = text[:split_pos]
if font.getsize(line1) > iw:
while True:
split_pos -= 1
line1 = line1[:-1]
if font.getsize(line1) <= iw:
break
else: # too short
while True:
line1 += text[split_pos]
if font.getsize(line1) > iw:
line1 = line1[:-1]
break
split_pos += 1
</code></pre>
<p>注意,这是基于字符的,而不是基于单词的,所以有点糟糕。由于大多数字体是成比例的,这个比例可能是错误的。您可以使用一些启发式方法来调整它,包括一组内置的宽度假设。(只需计算一次所有字母的宽度,将它们存储在一个表中,并假设所有字体都使用该宽度-仍然是错误的,但通常比比率法更接近,而且更快!)你知道吗</p>