def draw_text( data, text, color = 255, pos = 'lr' ): from PIL.Image import fromarray from PIL.ImageDraw import Draw from PIL import ImageFont from numpy import asarray font = ImageFont.load_default() image = fromarray( data ) draw = Draw( image ) w, h = draw.textsize( text, font = font ) position = { 'ul': lambda iw, ih, tw, th: ( 2, 0 ), 'ur': lambda iw, ih, tw, th: ( iw - tw - 2, 0 ), 'll': lambda iw, ih, tw, th: ( 2, ih - th ), 'lr': lambda iw, ih, tw, th: ( iw - tw - 2, ih - th ), } pos = position[ pos ]( data.shape[ 1 ], data.shape[ 0 ], w, h ) draw.text( pos, text, fill = color, font = font ) del draw return asarray( image )
def text(self, image, fonts, font_sizes=None, drawings=None, squeeze_factor=0.75, color=None): color = color if color else self._color fonts = tuple([truetype(name, size) for name in fonts for size in font_sizes or (65, 70, 75)]) draw = Draw(image) char_images = [] for c in self._text: font = random.choice(fonts) c_width, c_height = draw.textsize(c, font=font) char_image = Image.new('RGB', (c_width, c_height), (0, 0, 0)) char_draw = Draw(char_image) char_draw.text((0, 0), c, font=font, fill=color) char_image = char_image.crop(char_image.getbbox()) for drawing in drawings: d = getattr(self, drawing) char_image = d(char_image) char_images.append(char_image) width, height = image.size offset = int((width - sum(int(i.size[0] * squeeze_factor) for i in char_images[:-1]) - char_images[-1].size[0]) / 2) for char_image in char_images: c_width, c_height = char_image.size mask = char_image.convert('L').point(lambda i: i * 1.97) image.paste(char_image, (offset, int((height - c_height) / 2)), mask) offset += int(c_width * squeeze_factor) return image
def drawer(image, text): draw = Draw(image) char_images = [] for c in text: font = random.choice(fonts) c_width, c_height = draw.textsize(c, font=font) c_height *= 2 char_image = Image.new('RGB', (c_width, c_height), (0, 0, 0)) char_draw = Draw(char_image) char_draw.text((0, 0), c, font=font, fill=color()) char_image = char_image.crop(char_image.getbbox()) for drawing in drawings: char_image = drawing(char_image) char_images.append(char_image) width, height = image.size offset = int((width - sum(int(i.size[0] * squeeze_factor) for i in char_images[:-1]) - char_images[-1].size[0]) / 2) for char_image in char_images: c_width, c_height = char_image.size mask = char_image.convert('L').point(lambda i: i * 1.97) image.paste(char_image, (offset, int((height - c_height) / 2)), mask) offset += int(c_width * squeeze_factor) return image
def decompose_word(img, word, font): x_size = img.size[0] y_size = img.size[1] letters = len(word) array = img_to_array(img) array.shape = (array.shape[1], array.shape[2]) #print word, img.size draw = Draw(Image.new("L",(100,100))) total_font_size = float(draw.textsize(word, font)[0]) data = [] start = 0 for letter in word: # range(0,x_size, x_size / len(word)): #print i*word_size,(i+1)*word_size, array.shape letter_size = draw.textsize(letter, font)[0] size = int(x_size*letter_size/total_font_size) middle = int((start + size) / 2) a = max(0,middle - 64) b = min(x_size, middle + 64) #print acc_size, acc_size+x img = array[:,a:b] if middle - 64 < 0: padding = 255*np.ones((y_size, 64 - middle)) print padding.shape, img.shape img = np.hstack([padding,img]) if middle + 64 > x_size: padding = 255*np.ones((y_size, (middle + 64) - x_size)) print padding.shape, img.shape img = np.hstack([img,padding]) data.append((img,letter)) start = start + size #acc_size = acc_size + x return data
def draw_text(image, text, font_size): font = truetype(join(current_dir, 'static/font.ttf'), font_size) color = '#5C87B2' draw = Draw(image) char_images = [] for ch in text: c_width, c_height = draw.textsize(ch, font=font) char_image = Image.new('RGB', (c_width, c_height), (0, 0, 0)) char_draw = Draw(char_image) char_draw.text((0, 0), ch, font=font, fill=color) char_image = char_image.crop(char_image.getbbox()) char_images.append(char_image) width, height = image.size total = len(char_images) for i, char_image in enumerate(char_images): c_width, c_height = char_image.size mask = char_image.convert('L').point(lambda i: i * 1.97) upper = int((height - c_height) / 2) left = int((width * (i + 1) / (total + 1)) - c_width / 2) image.paste(char_image, (left, upper), mask) return image
def text(self, image, fonts, font_sizes=None, drawings=None, squeeze_factor=0.75, color=None): color = color if color else self._color fonts = tuple([ truetype(name, size) for name in fonts for size in font_sizes or (65, 70, 75) ]) draw = Draw(image) char_images = [] for c in self._text: font = random.choice(fonts) c_width, c_height = draw.textsize(c, font=font) char_image = Image.new('RGB', (c_width, c_height), (0, 0, 0)) char_draw = Draw(char_image) char_draw.text((0, 0), c, font=font, fill=color) char_image = char_image.crop(char_image.getbbox()) for drawing in drawings: d = getattr(self, drawing) char_image = d(char_image) char_images.append(char_image) width, height = image.size offset = int( (width - sum(int(i.size[0] * squeeze_factor) for i in char_images[:-1]) - char_images[-1].size[0]) / 2) for char_image in char_images: c_width, c_height = char_image.size mask = char_image.convert('L').point(lambda i: i * 1.97) image.paste(char_image, (offset, int((height - c_height) / 2)), mask) offset += int(c_width * squeeze_factor) return image
def draw_text(image, text, font_size): font = truetype(join(current_dir, 'static/DroidSansFallback.ttf'), font_size) color = '#5C87B2' draw = Draw(image) char_images = [] for ch in text: c_width, c_height = draw.textsize(ch, font=font) char_image = Image.new('RGB', (c_width, c_height), (0, 0, 0)) char_draw = Draw(char_image) char_draw.text((0, 0), ch, font=font, fill=color) char_image = char_image.crop(char_image.getbbox()) char_images.append(char_image) width, height = image.size total = len(char_images) for i, char_image in enumerate(char_images): c_width, c_height = char_image.size mask = char_image.convert('L').point(lambda i: i * 1.97) upper = int((height - c_height) / 2) left = int((width * (i + 1) / (total + 1)) - c_width / 2) image.paste(char_image, (left, upper), mask) return image
def draw_gameover(self, draw: ImageDraw.Draw): text = 'GAME OVER' text_width, text_height = draw.textsize(text) draw.text((Vector(*canvas_size) - (text_width, text_height)) / 2, text, fill=(255, 255, 255, 255))
def draw_text(text, font_spec, text_color, xy=None, anchor=None, box_color=None, box_padding=0, border_color=None, border_width=0, image=None): """Draws centered text on an image, optionally in a box.""" draw = Draw(image) text_size = font_spec['size'] font = ImageFont.truetype(font_spec['file'], size=text_size) # Measure the width of each character. character_widths = [] for character in text: # Override the measured width, if specified. width_overrides = font_spec['width_overrides'] if character in width_overrides.keys(): character_width = width_overrides[character] else: character_width, _ = draw.textsize(character, font) character_widths.append(character_width) text_width = sum(character_widths) # If any xy is specified, use it. text_height = font_spec['height'] if xy: x = xy[0] - text_width // 2 y = xy[1] - text_height // 2 # If any anchor is specified, adjust the xy. if anchor == 'center': x = image.width // 2 - text_width // 2 y = image.height // 2 - text_height // 2 elif anchor == 'center_x': x = image.width // 2 - text_width // 2 elif anchor == 'center_y': y = image.height // 2 - text_height // 2 elif anchor == 'bottom_right': x = image.width - box_padding - border_width - text_width y = image.height - box_padding - border_width - text_height # Draw the box background and border. box_xy = [ x - box_padding, y - box_padding, x + text_width + box_padding, y + text_height + box_padding ] border_xy = [ box_xy[0] - border_width, box_xy[1] - border_width, box_xy[2] + border_width, box_xy[3] + border_width ] if border_color: draw.rectangle(border_xy, border_color) if box_color: draw.rectangle(box_xy, box_color) # Draw the text character by character. y -= font_spec['y_offset'] for index in range(len(text)): character = text[index] draw.text((x, y), character, text_color, font) x += character_widths[index]
def make_text(text: str, box=(0, 0), init_font_size=76, align='left', font_path='', color=(0, 0, 0, 255), stroke=None): # split text into individual words, then draw them sequentially. # in fact more efficient than previously thought. # NOTE: arg `align` is NYI, probably impossible words = text.split() canvas = Image.new('RGBA', box, color=(255, 255, 255, 0)) # method scope x, y = 0, 0 font_size = init_font_size while True: # (re-)initiate canvas canvas = Image.new('RGBA', box, color=(255, 255, 255, 0)) draw = Draw(canvas) # for each font size, first fill the width. # if the height exceeds the size of the box, reduce font size. # repeat font size reduction until fits. if 0 < font_size <= 16: font_size -= 1 elif 16 < font_size < 32: font_size -= 2 elif font_size >= 32: font_size -= 4 else: break font = truetype(font_path, size=font_size) space_width = draw.textsize(' ', font=font)[0] line_height = int(font_size * 1.2) # start filling words idx = 0 # position in list `words` y = 0 while idx < len(words): # words not depleted # new line x = 0 word = words[idx] word_width = draw.textsize(word, font=font)[0] # skip this size if even a single word won't fit if word_width > box[0]: break # fill line until it would overflow while x + word_width <= box[0]: draw.text( (x, y - font_size // 10), word, fill=color if stroke is None else WHITE, font=font, stroke_fill=stroke, # stroke width: 2 is the bare minimum stroke_width=(max(font_size // 20, 2) if stroke is not None else 0)) x += word_width + space_width idx += 1 if idx >= len(words): break word = words[idx] word_width = draw.textsize(words[idx], font=font)[0] y += line_height if y <= box[1] and idx == len(words): return canvas
color2 = [] for c in range(3): s = 0 s2 = 0 for tone in range(12): s += coefs[c][tone] * cc[tone] s2 += (coefs[c][tone] * cc2[tone] + coefs[c][tone] * cc[tone]) / 2 color.append(int(s)) color2.append(int(s2)) color = tuple(color2) w, h = 426, 240 image = Image.new("RGB", (w, h), (0, 0, 0)) draw = Draw(image) text = name if True else ", ".join([f"{c:.2f}" for c in cc]) ww, hh = draw.textsize(text) draw.text(((w - ww) // 2, (h - hh) // 2), text) line = [0, h] for ii, tone in enumerate(range(12)): line.append(int((ii + 1) * w / 13)) line.append(h - 50 * cc[tone]) line += [w, h] draw.line(line, width=1, fill=color) image.save(f"imgs/img{i:09}.png") for o in range(height): overview.putpixel((i, o), color) plt.figure(figsize=(10, 6)) plt.subplot(2, 1, 1)
def __calculate_single_sticker_location_text_offset( self, text: str, draw_context: ImageDraw.Draw, font=None) -> tuple: text_size = draw_context.textsize(text, font=font) return int((self.single_sticker_dim[0] - text_size[0]) / 2), int( self.single_sticker_dim[1] * 0.29)
def make_emoji_text(text: str, emojis={}, instance='', box=(0, 0), init_font_size=76, align='left', font_path='', color=(0, 0, 0, 255), stroke=None): # different method # used for text with custom emojis # less efficient than without # TODO: flag for no-render-emoji # split text into individual words, then draw them sequentially. # NOTE: arg `align` is NYI, probably impossible words = advanced_split(text) canvas = Image.new('RGBA', box, color=(255, 255, 255, 0)) # method scope x, y = 0, 0 font_size = init_font_size while True: # (re-)initiate canvas canvas = Image.new('RGBA', box, color=(255, 255, 255, 0)) draw = Draw(canvas) # for each font size, first fill the width. # if the height exceeds the size of the box, reduce font size. # repeat font size reduction until fits. if 0 < font_size <= 16: font_size -= 1 elif 16 < font_size < 32: font_size -= 2 elif font_size >= 32: font_size -= 4 else: break font = truetype(font_path, size=font_size) space_width = draw.textsize(' ', font=font)[0] line_height = int(font_size * 1.2) # start filling words idx = 0 # position in list `words` y = 0 while idx < len(words): # words not depleted # new line x = 0 word = words[idx] emoji = get_emoji_if_is(word, size=font_size, instance=instance, emojis=emojis) # emoji: Image of it if is an emoji, else None word_width = (emoji.size[0] if emoji else draw.textsize(word, font=font)[0]) # skip this size if even a single word won't fit if word_width > box[0]: break # fill line until it would overflow while x + word_width <= box[0]: if emoji: if 'A' in emoji.getbands(): # emoji has Alpha channel, aka transparency canvas.paste(emoji, box=(x, y), mask=emoji) else: canvas.paste(emoji, box=(x, y)) else: draw.text( (x, y - font_size // 10), word, fill=color if stroke is None else WHITE, font=font, stroke_fill=stroke, # stroke width: 2 is the bare minimum stroke_width=(max(font_size // 20, 2) if stroke is not None else 0)) x += word_width + (space_width if not is_CJK(word) else 0) idx += 1 if idx >= len(words): break word = words[idx] emoji = get_emoji_if_is(word, size=font_size, instance=instance, emojis=emojis) word_width = (emoji.size[0] if emoji else draw.textsize( words[idx], font=font)[0]) y += line_height if y <= box[1] and idx == len(words): return canvas
def render(self, draw: ImageDraw.Draw): w, h = draw.textsize(self.message) draw.text(((128 - w) / 2, (32 - h) / 2), self.message, font=font, fill=255)