Python 을 이용 하여 메모지 그림 을 어떻게 만 드 는 지 상세 하 게 설명 합 니 다.

머리말
최근 에 문자 로 그림 을 돌 리 는 수요 가 있 지만 앱 을 다운로드 하고 싶 지 않 아 Python Pillow 를 사용 하여 하 나 를 실 현 했 습 니 다.효 과 는 다음 과 같 습 니 다.

PIL 은PIL.ImageDraw.ImageDraw.text 방법 을 제공 하여 문 자 를 그림 에 편리 하 게 쓸 수 있 습 니 다.간단 한 예 는 다음 과 같 습 니 다.

from PIL import Image, ImageDraw, ImageFont
# get an image
base = Image.open('Pillow/Tests/images/hopper.png').convert('RGBA')

# make a blank image for the text, initialized to transparent text color
txt = Image.new('RGBA', base.size, (255,255,255,0))

# get a font
fnt = ImageFont.truetype('Pillow/Tests/fonts/FreeMono.ttf', 40)
# get a drawing context
d = ImageDraw.Draw(txt)

# draw text, half opacity
d.text((10,10), "Hello", font=fnt, fill=(255,255,255,128))
# draw text, full opacity
d.text((10,60), "World", font=fnt, fill=(255,255,255,255))

out = Image.alpha_composite(base, txt)

out.show()
왜 문자 의 너 비 를 계산 해 야 합 니까?텍스트 를 배경 그림 에 직접 쓰 면 안 됩 니까?Pillow PIL.ImageDraw.ImageDraw.text문 자 를 쓰 는 것 은 줄 바 꿈 문자 에 따라 줄 을 바 꾸 는 것 입 니 다.문자열 이 너무 길 면 텍스트 부분 이 배경 그림 의 너 비 를 초과 하기 때문에 첫 번 째 단 계 는 텍스트 를 고정된 너비 에 따라 높이 를 계산 해 야 합 니 다.
그림 에 적 힌 것 처럼 문자 회전 그림 은 세 단계 로 나 뉜 다.
  • 계산 문자 의 너비
  • 응답 사이즈 배경 그림 생 성
  • 그림 에 글 을 쓴다
  • 계산 문자 너비
    이 배경 그림 의 너 비 는 고정 되 어 있 기 때문에 문자 의 너 비 는 계산 하지 않 아 도 됩 니 다.PIL.ImageDraw.ImageDraw.text 줄 을 바 꾸 는 것 을 통 해 우 리 는 문자 의 적당 한 위치 에 덧 붙 이면 된다.
    첫 번 째 로 생각 나 는 것 은 textwrap 방법 입 니 다.textwrap 은 줄 바 꿈 문자 의 위 치 를 조정 하여 텍스트 를 포맷 할 수 있 습 니 다.그러나 textwrap 의 또 다른 문 제 는 문자 길이 에 따라 구분 되 는 것 입 니 다.그러나 텍스트 의 문 자 는 똑 같은 너비 가 아 닙 니 다.textwrap 을 통 해 포맷 된 문 자 를 그림 에 쓰 면 효과 가 이 럴 수 있 습 니 다.

    이 방식 을 사용 하면 글꼴 크기 를 조정 하려 면 줄 마다 길 이 를 다시 조정 해 야 합 니 다.
    각 줄 의 너비 가 가능 한 한 일치 하도록 하기 위해 서 는PIL.ImageDraw.ImageDraw.textsize문자 의 너비 와 높이 를 가 져 온 다음 에 약 정 된 너비 에 따라 긴 텍스트 를 텍스트 목록 으로 나 눈 다음 에 목록 의 각 줄 의 문 자 를 그림 에 씁 니 다.
    
    def get_paragraph(text, note_width):
     #                
     txt = Image.new('RGBA', (100, 100), (255, 255, 255, 0))
     # get a drawing context
     draw = ImageDraw.Draw(txt)
     paragraph, sum_width = '', 0
     line_numbers, line_height = 1, 0
     for char in text:
     w, h = draw.textsize(char, font)
     sum_width += w
     if sum_width > note_width:
      line_numbers += 1
      sum_width = 0
      paragraph += '
    ' paragraph += char line_height = max(h, line_height) if not paragraph.endswith('
    '): paragraph += '
    ' return paragraph, line_height, line_numbers def split_text(text): # max_line_height, total_lines = 0, 0 paragraphs = [] for t in text.split('
    '): #
    paragraph, line_height, line_numbers = get_paragraph(t) max_line_height = max(line_height, max_line_height) total_lines += line_numbers paragraphs.append((paragraph, line_numbers)) line_height = max_line_height total_height = total_lines * line_height # , return paragraphs, total_height, line_height
    그림 에 쓸 텍스트 를 문자 너비 로 구분 하 는 효과 입 니 다.

    텍스트 길이 가 고정 되 지 않 기 때문에 생 성 된 텍스트 높이 도 고정 되 지 않 습 니 다.배경 그림 도 동적 으로 생 성 되 어야 합 니 다.
    텍스트 높이 에 따라 배경 그림 생 성

    그림 을 통 해 우 리 는 머리 와 꼬리 부분 이 고정 되 어 있 고 문자 부분 이 변화 하 는 것 을 볼 수 있다.그러면 배경 그림 의 높이 계산 공식 은?
    배경 그림 높이=머리 높이+꼬리 높이+텍스트 높이
    구현 코드 는 다음 과 같 습 니 다:
    
    NOTE_HEADER_IMG = path.normpath(path.join(
     path.dirname(__file__), 'note_header_660.png'))
    NOTE_BODY_IMG = path.normpath(path.join(
     path.dirname(__file__), 'note_body_660.png'))
    NOTE_FOOTER_IMG = path.normpath(path.join(
     path.dirname(__file__), 'note_footer_660.png'))
    NOTE_WIDTH = 660
    NOTE_TEXT_WIDTH = 460
    body_height = NOTE_BODY_HEIGHT = 206
    header_height = NOTE_HEADER_HEIGHT = 89
    footer_height = NOTE_FOOTER_HEIGHT = 145
    font = ImageFont.truetype(NOTE_OTF, 24)
    
    
    def get_images(note_height):
     numbers = note_height // body_height + 1
     images = [(NOTE_HEADER_IMG, header_height)]
     images.extend([(NOTE_BODY_IMG, body_height)] * numbers)
     images.append((NOTE_FOOTER_IMG, footer_height))
     return images
    
    
    def make_backgroud():
     #         
     images = get_images()
     total_height = sum([height for _, height in images])
     #           
     backgroud = Image.new('RGB', (body_width, total_height))
     left, right = 0, 0
     background_img = '/tmp/%s_backgroud.png' % total_height
     #          
     if path.exists(background_img):
     return background_img
     for image_file, height in images:
     image = Image.open(image_file)
     # (0, left, self.body_width, right+height)
     #           0, left
     #       self.body_width, right+height
     backgroud.paste(image, (0, left, body_width, right+height))
     left += height #       ,         
     right += height #           
     backgroud.save(background_img, quality=85)
     return background_img
    그림 에 텍스트 쓰기
    현재 우 리 는 배경 그림 과 분 리 된 텍스트 를 얻 으 면 바로 텍스트 를 그림 에 쓸 수 있다.
    
    def draw_text(paragraphs, height):
     background_img = make_backgroud()
     note_img = Image.open(background_img).convert("RGBA")
     draw = ImageDraw.Draw(note_img)
     #         ,             
     x, y = 80, 100
     for paragraph, line_numbers in paragraphs:
     for line in paragraph.split('
    ')[:-1]: draw.text((x, y), line, fill=(110, 99, 87), font=font) y += line_height # draw.text((x, y), paragraph, fill=(110, 99, 87), font=font) # y += self.line_height * line_numbers note_img.save(filename, "png", quality=1, optimize=True) return filename
    전체 코드 보기[https://github.com/gusibi/momo/blob/master/momo/note.py]
    실행 후 효 과 는 그림:

    닥 친 문제
    편리 하 게 사용 할 수 있 도록 나 는 이것 을 공공 번호 의 기능 으로 만 들 었 다.그리고 심각 한 문제 에 부 딪 혔 다.너무 느리다!
    line 사용proffler 분석 을 통 해 대부분의 시간 이 그림 저장 에 소모 되 었 음 을 알 수 있 습 니 다.
    
    note_img.save(filename, "png", quality=1, optimize=True)
    성능 분석 도구 도 시간 을 차지 합 니 다.테스트 가 완료 되면 분석 을 닫 아야 합 니 다.
    이 문 제 를 해결 하 는 가능 한 방법:
  • 배경 그림 크기 줄 이기
  • 글꼴 크기 줄 이기
  • 테스트 를 통 해 배경 그림 의 너 비 를 990 에서 660 으로 줄 이 고 글씨체 의 크기 를 40px 에서 24px 로 조정 하여 생 성 된 그림 의 크기 와 부 피 를 1 배 가까이 줄 이 고 생 성 속도 도 원래 보다 2/5 빠 른 것 으로 나 타 났 다.
    같은 코드,같은 텍스트,python 3 을 사용 하 는 데 2.3s 만 사 용 했 고 Python 2 를 사용 할 때 5.3 s 로 다른 기능 에서 Python 2 와 Python 3 의 차이 가 이렇게 큰 것 을 본 적 이 없다.
    구체 적 인 차 이 는 소스 코드 로 테스트 할 수 있다.
    그래도 문제 가 있어 요.
    그림 생 성 속 도 를 최적화 한 후에 긴 텍스트 상태 에서 공 호 는 타 임 스 를 초과 할 수 있다 는 것 을 발견 했다.검 사 를 통 해 사진 이 공공 플랫폼 에 올 라 가 는 것 이 너무 느 린 것 으로 밝 혀 졌 다.(서버 는 1M 대역 폭 밖 에 없어 어 쩔 수 없다.)
    해결 방법 은 텐 센트 클 라 우 드 에 사진 을 올 리 고(파일 업 로드 는 내부 네트워크 대역 폭 을 사용 하여 제한 을 받 지 않 음)그림 url 로 돌아 갑 니 다.

    총결산
    이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기