>

현재 텍스트가 포함 된 이미지를 출력하는 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

예상 결과 : 텍스트가 다음 줄로 줄 바꿈되어야합니다.

  • 답변 # 1

    각 줄을 따로 그려야하므로 텍스트 래퍼가 도움이 될지 확실하지 않습니다.

    한 줄에 최대 문자 길이를 계산 한 다음 다음과 같이하십시오 :

    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.
    
    

  • 답변 # 2

    글꼴을 다루기 때문에 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
    
    

    이것은 단어 기반이 아니라 문자 기반이기 때문에 일종의 짜증입니다. 그리고 대부분의 글꼴은 비례하기 때문에 비율이 잘못되었을 수 있습니다. 내장 너비 가정 세트를 포함하여 일부 휴리스틱을 사용하여 조정할 수 있습니다. (모든 문자의 너비를 한 번 계산하고 테이블에 저장하고 모든 글꼴이 해당 너비를 사용한다고 가정합니다. 여전히 잘못되었지만 비율 방법보다 근사치가 더 빠르며 빠릅니다!)

  • 이전 Java의 '고유 한'객체 목록
  • 다음 reactjs - componentWillReceiveProps는 페이지를 새로 고치는 경우에만 상태를 업데이트합니다