def draw_text(image, text, horizontal_offset, vertical_offset, horizontal_justification, vertical_justification, size, color='#FFFFFF', orientation=None, font=None): """Draws text on an image.""" image = convert_safe_mode(image) if orientation: orientation = getattr(Image, orientation) draw = ImageDraw.Draw(image) if font.strip(): font = ImageFont.truetype(font, size) else: font = ImageFont.load_default() text = text.encode('ascii', 'replace') if orientation: font = ImageFont.TransposedFont(font, orientation) location = calculate_location( horizontal_offset, vertical_offset, horizontal_justification, vertical_justification, image.size, draw.textsize(text, font=font)) # draw draw.text(location, text, font=font, fill=color) # composite the watermark with the layer return image
def make_wordcloud(words, counts, width=400, height=200): # sort words by counts inds = np.argsort(counts)[::-1] counts = counts[inds] words = words[inds] # create image img = Image.new("L", (width, height)) draw = ImageDraw.Draw(img) #i = 0 integral = np.zeros((height, width), dtype=np.uint) img_array = np.asarray(img) for word, count in zip(words, counts): font_path = "/usr/share/fonts/truetype/droid/DroidSansMono.ttf" #img_array = img_array.sum(axis=2) # set font size font_size = int(np.log(count)) * 20 runs = 0 while True: font = ImageFont.truetype(font_path, font_size) # transpose font optionally orientation = random.choice([None, Image.ROTATE_90]) transposed_font = ImageFont.TransposedFont(font, orientation=orientation) draw.setfont(transposed_font) # get size of resulting text size = draw.textsize(word) # find possible places using integral image: result = query_integral_image(integral, size[1], size[0]) if result is not None: break # if we didn't find a place, make font smaller font_size -= 1 runs += 1 x, y = result draw.text((result[1], result[0]), word, fill="white") # recompute integral image img_array = np.asarray(img) # recompute bottom right partial_integral = np.cumsum(np.cumsum(img_array[x:, y:], axis=1), axis=0) # paste into old image # if x or y is zero it is a bit annoying if x > 0: if y > 0: partial_integral += (integral[x - 1, y:] - integral[x - 1, y - 1]) else: partial_integral += integral[x - 1, y:] if y > 0: partial_integral += integral[x:, y - 1][:, np.newaxis] integral[x:, y:] = partial_integral img.show()
def make_wordcloud(words, counts, font_path, imagineName, width=800, height=600, margin=5): # sort words by counts inds = np.argsort(counts)[::-1] counts = counts[inds] words = words[inds] # create image img_grey = Image.new("L", (width, height)) draw = ImageDraw.Draw(img_grey) integral = np.zeros((height, width), dtype=np.uint32) img_array = np.asarray(img_grey) font_sizes, positions, orientations = [], [], [] # intitiallize fontsize "large enough" font_size = 1000 # start drawing grey image for word, count in zip(words, counts): # set font size #font_size = min(font_size, int(100 * np.log(count + 100))) while True: # try to find a position font = ImageFont.truetype(font_path, font_size) # transpose font optionally orientation = random.choice([None, Image.ROTATE_90]) transposed_font = ImageFont.TransposedFont(font, orientation=orientation) draw.setfont(transposed_font) # get size of resulting text box_size = draw.textsize(word) # find possible places using integral image: result = query_integral_image(integral, box_size[1] + margin, box_size[0] + margin) if result is not None or font_size == 0: break # if we didn't find a place, make font smaller font_size -= 1 if font_size == 0: # we were unable to draw any more break x, y = np.array(result) + margin // 2 # actually draw the text draw.text((y, x), word, fill="white") positions.append((x, y)) orientations.append(orientation) font_sizes.append(font_size) # recompute integral image img_array = np.asarray(img_grey) # recompute bottom right # the order of the cumsum's is important for speed ?! partial_integral = np.cumsum(np.cumsum(img_array[x:, y:], axis=1), axis=0) # paste recomputed part into old image # if x or y is zero it is a bit annoying if x > 0: if y > 0: partial_integral += (integral[x - 1, y:] - integral[x - 1, y - 1]) else: partial_integral += integral[x - 1, y:] if y > 0: partial_integral += integral[x:, y - 1][:, np.newaxis] integral[x:, y:] = partial_integral # redraw in color img = Image.new("RGB", (width, height)) draw = ImageDraw.Draw(img) everything = zip(words, font_sizes, positions, orientations) for word, font_size, position, orientation in everything: font = ImageFont.truetype(font_path, font_size) # transpose font optionally transposed_font = ImageFont.TransposedFont(font, orientation=orientation) draw.setfont(transposed_font) draw.text((position[1], position[0]), word, fill="hsl(%d" % random.randint(0, 255) + ", 80%, 50%)") name = imagineName + '.png' # img.show() img.save(name) img.show()