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 )
Beispiel #2
0
 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
Beispiel #3
0
 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
Beispiel #5
0
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
Beispiel #6
0
 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
Beispiel #7
0
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
Beispiel #8
0
 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))
Beispiel #9
0
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]
Beispiel #10
0
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
Beispiel #11
0
    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)
Beispiel #13
0
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
Beispiel #14
0
 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)