105 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from PIL import Image, ImageDraw, ImageFont
 | |
| 
 | |
| 
 | |
| class ImageText(object):
 | |
|     def __init__(self, filename_or_size, mode='RGBA', background=(0, 0, 0, 0),
 | |
|                  encoding='utf8'):
 | |
|         if isinstance(filename_or_size, str):
 | |
|             self.filename = filename_or_size
 | |
|             self.image = Image.open(self.filename)
 | |
|             self.size = self.image.size
 | |
|         elif isinstance(filename_or_size, (list, tuple)):
 | |
|             self.size = filename_or_size
 | |
|             self.image = Image.new(mode, self.size, color=background)
 | |
|             self.filename = None
 | |
|         self.draw = ImageDraw.Draw(self.image)
 | |
|         self.encoding = encoding
 | |
| 
 | |
|     def save(self, filename=None):
 | |
|         self.image.save(filename or self.filename)
 | |
| 
 | |
|     def get_font_size(self, text, font, max_width=None, max_height=None):
 | |
|         if max_width is None and max_height is None:
 | |
|             raise ValueError('You need to pass max_width or max_height')
 | |
|         font_size = 1
 | |
|         text_size = self.get_text_size(font, font_size, text)
 | |
|         if (max_width is not None and text_size[0] > max_width) or \
 | |
|                 (max_height is not None and text_size[1] > max_height):
 | |
|             raise ValueError("Text can't be filled in only (%dpx, %dpx)" % text_size)
 | |
|         while True:
 | |
|             if (max_width is not None and text_size[0] >= max_width) or \
 | |
|                (max_height is not None and text_size[1] >= max_height):
 | |
|                 return font_size - 1
 | |
|             font_size += 1
 | |
|             text_size = self.get_text_size(font, font_size, text)
 | |
| 
 | |
|     def write_text(self, position, text, font_filename, font_size=11, color=(0, 0, 0), max_width=None, max_height=None):
 | |
|         x, y = position
 | |
|         if font_size == 'fill' and \
 | |
|            (max_width is not None or max_height is not None):
 | |
|             font_size = self.get_font_size(text, font_filename, max_width, max_height)
 | |
|         text_size = self.get_text_size(font_filename, font_size, text)
 | |
|         font = ImageFont.truetype(font_filename, font_size)
 | |
|         if x == 'center':
 | |
|             x = (self.size[0] - text_size[0]) / 2
 | |
|         if y == 'center':
 | |
|             y = (self.size[1] - text_size[1]) / 2
 | |
|         self.draw.text((x, y), text, font=font, fill=color)
 | |
|         return text_size
 | |
| 
 | |
|     def get_text_size(self, font_filename, font_size, text):
 | |
|         font = ImageFont.truetype(font_filename, font_size)
 | |
|         return font.getsize(text)
 | |
| 
 | |
|     def write_text_box(self, position, text, box_width, font_filename, font_size=11, color=(0, 0, 0), place='left',
 | |
|                        justify_last_line=False):
 | |
|         x, y = position
 | |
|         lines = []
 | |
|         line = []
 | |
|         text_height = 0
 | |
|         text_lines = text.split('\n')
 | |
|         for text_line in text_lines:
 | |
|             words = text_line.split(' ')
 | |
|             for word in words:
 | |
|                 new_line = ' '.join(line + [word])
 | |
|                 size = self.get_text_size(font_filename, font_size, new_line)
 | |
|                 text_height = size[1]
 | |
|                 if size[0] <= box_width:
 | |
|                     line.append(word)
 | |
|                 else:
 | |
|                     lines.append(line)
 | |
|                     line = [word]
 | |
|             if line:
 | |
|                 lines.append(line)
 | |
|                 line = []
 | |
|         lines = [' '.join(line) for line in lines if line]
 | |
|         height = y
 | |
|         for index, line in enumerate(lines):
 | |
|             height += text_height
 | |
|             if place == 'left':
 | |
|                 self.write_text((x, height), line, font_filename, font_size, color)
 | |
|             elif place == 'right':
 | |
|                 total_size = self.get_text_size(font_filename, font_size, line)
 | |
|                 x_left = x + box_width - total_size[0]
 | |
|                 self.write_text((x_left, height), line, font_filename, font_size, color)
 | |
|             elif place == 'center':
 | |
|                 total_size = self.get_text_size(font_filename, font_size, line)
 | |
|                 x_left = int(x + ((box_width - total_size[0]) / 2))
 | |
|                 self.write_text((x_left, height), line, font_filename, font_size, color)
 | |
|             elif place == 'justify':
 | |
|                 words = line.split()
 | |
|                 if (index == len(lines) - 1 and not justify_last_line) or len(words) == 1:
 | |
|                     self.write_text((x, height), line, font_filename, font_size, color)
 | |
|                     continue
 | |
|                 line_without_spaces = ''.join(words)
 | |
|                 total_size = self.get_text_size(font_filename, font_size, line_without_spaces)
 | |
|                 space_width = (box_width - total_size[0]) / (len(words) - 1.0)
 | |
|                 start_x = x
 | |
|                 for word in words[:-1]:
 | |
|                     self.write_text((start_x, height), word, font_filename, font_size, color)
 | |
|                     word_size = self.get_text_size(font_filename, font_size, word)
 | |
|                     start_x += word_size[0] + space_width
 | |
|                 last_word_size = self.get_text_size(font_filename, font_size, words[-1])
 | |
|                 last_word_x = x + box_width - last_word_size[0]
 | |
|                 self.write_text((last_word_x, height), words[-1], font_filename, font_size, color)
 | |
|         return box_width, height - y |