如何将一个非明确给定的字符串拆分为两行或多行?

2024-09-30 16:28:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在使用一个Python机器人来输出带有文本的图像,但是我发现文本常常太长而无法显示。因此,我决定把字符串分成两行,这样它就可以适合我的图像。我利用枕头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

Actual results

预期结果:文本应环绕到下一行。你知道吗


Tags: 字符串text图像文本利用imgstring机器人
2条回答

我不确定一个文本包装器是否能帮助你,因为你需要分别画每一行。你知道吗

似乎应该计算单行中字符的最大长度,然后执行以下操作:

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.

因为您要处理字体,所以您需要了解^{}方法。这将帮助您了解如何拆分文本。你知道吗

假设您有一个字符串:

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

注意,这是基于字符的,而不是基于单词的,所以有点糟糕。由于大多数字体是成比例的,这个比例可能是错误的。您可以使用一些启发式方法来调整它,包括一组内置的宽度假设。(只需计算一次所有字母的宽度,将它们存储在一个表中,并假设所有字体都使用该宽度-仍然是错误的,但通常比比率法更接近,而且更快!)你知道吗

相关问题 更多 >