如何将一个非明确给定的字符串分成两行或更多行?
How does one split up a non-explicitly given string into two or more lines?
我目前正在使用 Python 机器人输出带有文本的图像,但我发现文本通常太长而无法显示。因此,我决定将字符串分成两行,以便它适合我的图像。我正在使用 Pillow 5.1 进行图像处理。
我是 Python 编程的新手,我试图搜索如何将 Python 字符串分成两行或更多行。不幸的是,所有结果似乎只处理明确给出的字符串(即 'string')。
print("Ababoubian wisdom!")
ababou2 = ababou() #returns a string, how to split into two lines?
if("Ababou" in ababou2):
ababou2 = ababou()
font = ImageFont.truetype("Arial.ttf", 14)
img = Image.new('RGB', (300, 200), color = (random.randint(0, 255),random.randint(0, 255), random.randint(0, 255)))
d = ImageDraw.Draw(img)
d.text((0, 0), ababou2, font=font) #draws text
预期结果:文本应该换行到下一行。
我不确定文本包装器对您的情况是否有帮助,因为您需要分别绘制每一行。
看来你应该计算单行字符的最大长度,然后做:
ababou2 = ababou() # Whats the point of assigning the same value twice?
# does ababou() returns a different value each time?
if "Ababou" in ababou2:
ababou2 = ababou()
res_text = list()
ababou2 = ababou2.split(' ') # Splits the string by space\ ' ', to a list of strings
curr_txt = ''
for word in ababou2:
if len(curr_txt) < MAX_CHARS_PER_LINE: # This you need to figure out
curr_txt += ' ' + word
else:
res_text.append(curr_txt)
curr_txt = word
font = ImageFont.truetype("Arial.ttf", 14)
img = Image.new('RGB', (300, 200), color = (random.randint(0, 255),random.randint(0, 255), random.randint(0, 255)))
d = ImageDraw.Draw(img)
y = 0
for line in res_text:
d.text((0, y), line, font=font) #draws text
y += SINGLE_ROW_SPACE # Figure out what is the distance between two rows.
因为您正在处理字体,所以您需要了解 getsize
方法。这将帮助您了解如何拆分文本。
假设你有一个字符串:
def get_a_string():
return "here is some string"
text = get_a_string()
现在,您还有一张图片,其宽度和高度为:
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
如果文字太长,您应该缩短它:
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()
如何缩短它?首先,尝试使用单词边界:
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
这将多次调用 getsize
,这可能会很昂贵。 (或者不是:如果你从猫的照片中生成模因,它可能不会花费太多,因为文本很短。如果你正在编写文字处理器,请注意!)
另一种方法是计算原始文本的大小,然后假设所有字符的宽度相同,并根据图像大小与文本大小的比率猜测应该在哪里拆分:
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
请注意,这是基于字符的,而不是基于单词的,所以有点糟糕。而且由于大多数字体都是成比例的,所以比例可能是错误的。您可以使用一些启发式方法来调整它,包括一组内置的宽度假设。 (只计算一次所有字母的宽度,将它们存储在 table 中,并假设所有字体都使用该宽度 - 仍然错误,但通常比比率方法更好,更快!)
我目前正在使用 Python 机器人输出带有文本的图像,但我发现文本通常太长而无法显示。因此,我决定将字符串分成两行,以便它适合我的图像。我正在使用 Pillow 5.1 进行图像处理。
我是 Python 编程的新手,我试图搜索如何将 Python 字符串分成两行或更多行。不幸的是,所有结果似乎只处理明确给出的字符串(即 'string')。
print("Ababoubian wisdom!")
ababou2 = ababou() #returns a string, how to split into two lines?
if("Ababou" in ababou2):
ababou2 = ababou()
font = ImageFont.truetype("Arial.ttf", 14)
img = Image.new('RGB', (300, 200), color = (random.randint(0, 255),random.randint(0, 255), random.randint(0, 255)))
d = ImageDraw.Draw(img)
d.text((0, 0), ababou2, font=font) #draws text
预期结果:文本应该换行到下一行。
我不确定文本包装器对您的情况是否有帮助,因为您需要分别绘制每一行。
看来你应该计算单行字符的最大长度,然后做:
ababou2 = ababou() # Whats the point of assigning the same value twice?
# does ababou() returns a different value each time?
if "Ababou" in ababou2:
ababou2 = ababou()
res_text = list()
ababou2 = ababou2.split(' ') # Splits the string by space\ ' ', to a list of strings
curr_txt = ''
for word in ababou2:
if len(curr_txt) < MAX_CHARS_PER_LINE: # This you need to figure out
curr_txt += ' ' + word
else:
res_text.append(curr_txt)
curr_txt = word
font = ImageFont.truetype("Arial.ttf", 14)
img = Image.new('RGB', (300, 200), color = (random.randint(0, 255),random.randint(0, 255), random.randint(0, 255)))
d = ImageDraw.Draw(img)
y = 0
for line in res_text:
d.text((0, y), line, font=font) #draws text
y += SINGLE_ROW_SPACE # Figure out what is the distance between two rows.
因为您正在处理字体,所以您需要了解 getsize
方法。这将帮助您了解如何拆分文本。
假设你有一个字符串:
def get_a_string():
return "here is some string"
text = get_a_string()
现在,您还有一张图片,其宽度和高度为:
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
如果文字太长,您应该缩短它:
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()
如何缩短它?首先,尝试使用单词边界:
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
这将多次调用 getsize
,这可能会很昂贵。 (或者不是:如果你从猫的照片中生成模因,它可能不会花费太多,因为文本很短。如果你正在编写文字处理器,请注意!)
另一种方法是计算原始文本的大小,然后假设所有字符的宽度相同,并根据图像大小与文本大小的比率猜测应该在哪里拆分:
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
请注意,这是基于字符的,而不是基于单词的,所以有点糟糕。而且由于大多数字体都是成比例的,所以比例可能是错误的。您可以使用一些启发式方法来调整它,包括一组内置的宽度假设。 (只计算一次所有字母的宽度,将它们存储在 table 中,并假设所有字体都使用该宽度 - 仍然错误,但通常比比率方法更好,更快!)