Example #1
0
    def inject_symbol(self, symbol: GenericSymbol, original_image: Image):
        # Fetch the image in appropriate format
        text_box_config = self.ctbm.get_config(symbol)
        resolution = text_box_config.resol if text_box_config else 1
        image_quality_prefix = SYMBOL_SOURCE_RESOLUTIONS[resolution]
        symbol_image = Image.open(
            os.path.join(PNG_SYMBOL_PATH, f"{image_quality_prefix}",
                         f"{symbol.name}.png"),
            "r",
        )
        symbol.resolution = resolution

        # Put symbol and text boxes
        offset = self.ASSEMBLY_IMAGE_OFFSET
        assemble_image = Image.new("L", self.ASSEMBLY_IMAGE_SIZE, 255)
        assemble_image.paste(symbol_image, offset)
        symbol.size_w, symbol.size_h = symbol_image.size

        # Move symbol if it is going to be plotted outside the visible region
        symbol = self.reposition_inside_visible(symbol)

        self.inject_text(symbol, assemble_image, offset)
        if symbol.orientation > 0:
            assemble_image = assemble_image.rotate(symbol.orientation,
                                                   expand=True)

        # Paste the generated symbol in the diagram
        inverted_image = ImageOps.invert(assemble_image)
        assemble_image.putalpha(inverted_image)

        original_image.paste(assemble_image, (symbol.x, symbol.y),
                             mask=inverted_image)
        # Recalculate positioning after the paste [and rotation]
        self.recalculate_positions(symbol, offset)
Example #2
0
 def make_beautiful_gif(self, template: Image, avatar: Image) -> BytesIO:
     gif_list = [frame.copy() for frame in ImageSequence.Iterator(avatar)]
     img_list = []
     num = 0
     temp = None
     for frame in gif_list:
         template = template.convert("RGBA")
         frame = frame.convert("RGBA")
         # frame = frame.rotate(-30, expand=True)
         # frame = frame.resize((60, 60), Image.ANTIALIAS)
         template.paste(frame, (370, 45), frame)
         template.paste(frame, (370, 330), frame)
         # temp2.thumbnail((320, 320), Image.ANTIALIAS)
         img_list.append(template)
         num += 1
         temp = BytesIO()
         template.save(temp,
                       format="GIF",
                       save_all=True,
                       append_images=img_list,
                       duration=0,
                       loop=0)
         temp.name = "beautiful.gif"
         if sys.getsizeof(temp) < 8000000 and sys.getsizeof(temp) > 7000000:
             break
     return temp
Example #3
0
def display_char(img: Image, font: Font, location: Tuple[int, int],
                 character: str) -> None:
    """Paste a single character from a fontsheet to the display image.

    Args:
        img:         The display image to be pasted into
        font:        The font class in use
        location:    (x, y) location tuple to paste character
        character:   Character to be pasted

    Notes:
        X and Y coordinates are anchored to the top left pixel of the character,
        and 0,0 is the top left of the display

    """
    # sheet = font.sheetstring
    # (
    #     "ABCDEFGHIJKLMNOPQRSTUVWXYZ():;[]abcdefghijklmnopqrstuvwxyz      "
    #     "ÄÖÜäöü          ⓓⓛⓜⓡⓢⓣⓥ       ⓃⓄ'①②-  ?!.&é ▷▶▼♂$×./,♀0123456789"
    # )
    # sheet_x = (sheet.index(character) % font.sheetwidth) * font.charwidth
    # sheet_y = (int(sheet.index(character) / font.sheetwidth)) * font.charheight

    # char_sprite = font.crop((sheet_x, sheet_y, sheet_x + char_width, sheet_y + char_height))
    char_sprite = font.get_character(character)
    img.paste(char_sprite, location, create_mask(char_sprite))
Example #4
0
def printBlog(xy, img: Image, today: datetime, blog, idx = 0):
    if not blog.get('data'):
        return
    
    x = xy[0]
    y = xy[1]
    
    draw = ImageDraw.Draw(img)

    date = utils.parseTime(blog['data'][idx]['publishDate'])
    title = str(blog['data'][idx]['title'])
    subtitle = str(blog['data'][idx]['subtitle'])

    twoline, title = linebreakString(draw, title)
    title = truncateString(draw, title, 370)

    _, subtitle = linebreakString(draw, subtitle, (3 if twoline else 4), font = rbtv_config.fontTiny)
    subtitle = truncateString(draw, subtitle, 370, font = rbtv_config.fontTiny)

    
    draw.rectangle((0, y, 600, y + 137), fill = 0)

    draw.text((x + 210, y + 5), title, font = rbtv_config.fontSmall, fill = 255)
    draw.text((x + 210, y + 5 + (60 if twoline else 30)), subtitle, font = rbtv_config.fontTiny, fill = 255)
    
    r = requests.get('https:' + str(blog['data'][idx]['thumbImage'][0]['url']))
    preview = Image.open(BytesIO(r.content))
    maxsize = (200, 140)
    tn_image = preview.thumbnail(maxsize)
    img.paste(preview, (x, y))

    delta = getTimeDelta(int((today - date).total_seconds()))
    draw.text((x, y - 25), delta, font = rbtv_config.fontTiny, fill = 0)
Example #5
0
def mark_dig(cell_image: Image, table_index: int, cell_index: int,
             row_index: int):
    dir_path = os.path.dirname(os.path.realpath(__file__))
    cell_icon = Image.open(os.path.join(dir_path, 'dig.png')).resize((35, 35))
    cell_image.paste(cell_icon, (7, 7), cell_icon)
    write_table_index(cell_icon, table_index)
    known_digs.append(UnitIconPosition(cell_icon, XY(cell_index, row_index)))
Example #6
0
def paste_switch(switch: bool, back: Image, image_on: Image, image_off: Image,
                 left: int, top: int) -> Image:
    if switch:
        back.paste(image_on, (left, top))
    else:
        back.paste(image_off, (left, top))
    return back
Example #7
0
def mark_unit(mark_filename: str, cell_image: Image, table_index: int, cell_index: int, row_index: int):
    dir_path = os.path.dirname(os.path.realpath(__file__))
    cell_icon = Image.open(os.path.join(dir_path, mark_filename)).resize((35, 35))
    cell_image.paste(cell_icon, (7, 7), cell_icon)
    write_table_index(cell_icon, table_index)
    if do_recon:
        known_units.append(UnitIconPosition(cell_icon, XY(cell_index, row_index)))
Example #8
0
    def draw(self, image: Image):
        mask = None
        if self.item_type in [self.LABEL, self.TIMESTAMP, self.LEGEND]:
            en = ImageEnhance.Brightness(self.cache)
            mask = en.enhance(0)

        image.paste(self.cache, self.position, mask)
Example #9
0
    def draw(self, im: Image, im_ry: Image = None):

        x, y = (0, 0)
        w, h = im.size
        for i in range(len(self.children)):
            c = self.children[i]
            percent = self.weights[i] / self.weights_total

            new_w = 0
            new_h = 0
            if self.is_vertical:
                new_h = int(percent * h)
                new_size = (w, new_h)
            else:
                new_w = int(percent * w)
                new_size = (new_w, h)

            new_image = View.create_image(new_size)
            new_image_ry = View.create_image(new_size)
            c.draw(new_image, new_image_ry)
            im.paste(new_image, (x, y))
            if im_ry is not None:
                im_ry.paste(new_image_ry, (x, y))
            x += new_w
            y += new_h
            del c, percent, new_w, new_h, new_size, new_image, new_image_ry
    def render(self, im: Image) -> None:
        # Lid image
        lid = Image.new("1", (WIDTH * 2, HEIGHT * 2), color=0)

        draw = ImageDraw.Draw(lid)

        # Draw lid
        lid_height = int(EYE_HEIGHT * self.y)
        x1 = WIDTH - EYE_WIDTH
        y1 = HEIGHT - 1 - HALF_EYE_HEIGHT
        x2 = WIDTH + EYE_WIDTH
        y2 = HEIGHT - 1 + lid_height
        draw.rectangle(((x1, y1), (x2, y2)), fill=1)

        bend_height = int(EYE_HEIGHT * (1.0 - self.y) * self.bend)
        x3 = WIDTH - HALF_EYE_WIDTH
        y3 = HEIGHT - 1 + lid_height - bend_height
        x4 = WIDTH + HALF_EYE_WIDTH
        y4 = HEIGHT - 1 + lid_height + bend_height
        draw.chord(((x3, y3), (x4, y4)), 0, 180, fill=1)

        # Rotate
        lid = lid.rotate(self.angle + self.angle_offset,
                         resample=RESAMPLE,
                         expand=0)

        # Translate and compose
        location = ((im.size[0] - lid.size[0]) // 2,
                    (im.size[1] - lid.size[1]) // 2 + self.offset)
        im.paste(self.BLACK, location, lid)
def _paste(bg: Image, p_conf: PasteConf) -> None:
    """
    according to paste configuration paste image over another
    :param bg: background image
    :param p_conf: paste configuration
    :return: None
    """
    with Image.open(p_conf.im_path) as im:
        im = im.convert('RGBA')
        im_w, im_h = im.size
        if p_conf.target_w <= 0 or p_conf.target_h <= 0:
            print('Target size(w, h) must > 0!')
            exit()
        if p_conf.resize_mode == 'scale':
            # 缩放贴图,以宽 target_w 为准,等比计算高度,可放大缩小
            p_conf.target_h = int(p_conf.target_w / im_w * im_h)
            im = im.resize((p_conf.target_w, p_conf.target_h), Image.ANTIALIAS)
        elif p_conf.resize_mode == 'trim':
            # 裁剪贴图,默认中心裁剪,只能缩小
            if p_conf.target_w > im_w:
                p_conf.target_w = im_w
            if p_conf.target_h > im_h:
                p_conf.target_h = im_h
            crop1_x = int((im_w - p_conf.target_w) // 2)
            crop1_y = int((im_h - p_conf.target_h) // 2)
            crop2_x = int((im_w + p_conf.target_w) // 2)
            crop2_y = int((im_h + p_conf.target_h) // 2)
            crop_box = (crop1_x, crop1_y, crop2_x, crop2_y)
            im = im.crop(crop_box)

        bg.paste(im, (p_conf.c_pos_x - p_conf.target_w // 2,
                      p_conf.c_pos_y - p_conf.target_h // 2), im)
Example #12
0
    def make_wheeze_img(self, template: Image, avatar: Image):
        # print(template.info)
        template = template.convert("RGBA")

        if type(avatar) != str:
            avatar = avatar.convert("RGBA")
            template.paste(avatar, (60, 470), avatar)
        else:
            font_loc = str(bundled_data_path(self) / "impact.ttf")
            font1 = ImageFont.truetype(font_loc, 40)
            draw = ImageDraw.Draw(template)
            margin = 40
            offset = 470
            count = 0
            for line in textwrap.wrap(avatar, width=10):
                count += 1
                if count == 6:
                    draw.text((margin, offset),
                              f"{line}...",
                              fill=(0, 0, 0),
                              font=font1)
                    break
                draw.text((margin, offset),
                          f"{line}",
                          fill=(0, 0, 0),
                          font=font1)
                offset += font1.getsize(line)[1]
        temp = BytesIO()
        template.save(temp, format="PNG")
        temp.name = "wheeze.png"
        return temp
Example #13
0
    def draw(self, image: Image, width: int, height: int, draw_x: int, draw_y: int, text: str):
        slice_path = os.path.join(self.art_repo.art_cache,
                                  "{0}_slice{1}x{2}.png".format(self.scryfall_id, width, height))
        if os.path.exists(slice_path):
            log.debug("[%s] Using cache", slice_path)
            slice_im = Image.open(slice_path)
        else:
            log.debug("[%s] Generating slice", slice_path)
            slice_im = self.generate_slice(width, height)
            slice_im.save(slice_path)

        # Now make some text
        x = 3
        y = 3
        shadowcolor = (0, 0, 0, 255)
        fillcolor = (255, 255, 255, 255)

        log.debug("Drawing text %s", text)

        draw = ImageDraw.Draw(slice_im)
        font = self.art_repo.get_small_text_font(height-(y * 2)-2)

        for i in range(-1, 2):
            for j in range(-1, 2):
                draw.text((x + i, y + j), text, font=font, fill=shadowcolor)

        # now draw the text over it
        draw.text((x, y), text, font=font, fill=fillcolor)

        log.debug("Drawing slice at %s x %s", draw_x, draw_y)
        image.paste(slice_im, (draw_x, draw_y))
Example #14
0
    def render(self, im: Image) -> None:
        # Lid image
        lid = Image.new("1", (self.width * 2, self.height * 2), color=0)

        draw = ImageDraw.Draw(lid)

        # Draw lid
        lid_height = int(self.eye_height * self.y)
        x1 = self.width - self.scale_factor_lid_height
        y1 = self.height - 1 - self.half_eye_height
        x2 = self.width + self.scale_factor_lid_height
        y2 = self.height - 1 + lid_height
        draw.rectangle(((x1, y1), (x2, y2)), fill=1)

        bend_height = int(self.eye_height * (1.0 - self.y) * self.bend)
        x3 = self.width - self.scale_factor_lid_bend
        y3 = self.height - 1 + lid_height - bend_height
        x4 = self.width + self.scale_factor_lid_bend
        y4 = self.height - 1 + lid_height + bend_height
        draw.chord(((x3, y3), (x4, y4)), 0, 180, fill=1)

        # Rotate
        lid = lid.rotate(self.angle + self.angle_offset,
                         resample=RESAMPLE,
                         expand=0)

        # Translate and compose
        location = ((im.size[0] - lid.size[0]) // 2,
                    (im.size[1] - lid.size[1]) // 2 + self.offset)
        im.paste(self.black, location, lid)
Example #15
0
async def draw_player(
    draw: ImageDraw.Draw,
    composite: Image,
    player: Player,
    character: Image,
    rank: Image,
    y_offset: int,
) -> None:

    ready = is_ready if player.is_ready() else not_ready
    voice = voice_on if player.is_in_voice() else voice_off

    y_offset += PLAYER_ONE_START
    composite.paste(rank, (88, y_offset), rank)
    composite.paste(ready, (132, y_offset + 11), ready)
    composite.paste(voice, (155, y_offset + 5), voice)
    composite.paste(character, (183, y_offset))

    try:
        profile = await player.get_avatar()
        composite.paste(profile.resize((19, 19)), (226, y_offset + 8))
    except Exception:
        pass

    draw.text(
        (255, y_offset + 11),
        player.get_name(),
        font=name_font,
        fill=(81, 81, 81, 255),
    )
Example #16
0
    def _draw_outlined_text(self,
                            image: Image,
                            position: Tuple[int, int],
                            content: str,
                            font: ImageFont.ImageFont,
                            background_color: Optional[Union[Tuple,
                                                             str]] = None,
                            stroke_width: int = 0,
                            stroke_color: Union[Tuple, str] = "#000"):

        overlay = Image.new('RGBA', image.size)
        x, y, text_width, text_height = self.get_text_bounding_box(
            center_position=position, font_size=font.size, text=content)

        draw = ImageDraw.ImageDraw(overlay, 'RGBA')
        if background_color is not None:
            margin = 10
            draw.rectangle(
                [(x - margin, y - margin),
                 (x + text_width + 2 * margin, y + text_height + 2 * margin)],
                fill=background_color)

        # Draw inner white text
        draw.multiline_text((x, y),
                            content,
                            self.text_color,
                            font=font,
                            align='center',
                            stroke_width=stroke_width,
                            stroke_fill=stroke_color)

        image.paste(overlay, None, overlay)
Example #17
0
def display_sprite(img: Image, location: Tuple[int, int],
                   mon: Pokemon) -> None:
    """Paste sprite and bounding box into display image.

    Args:
        img:      The display image to be pasted into
        location: (x, y) location tuple to paste character
        id:       Id of the pokemon sprite to paste
        gen:      Generation to pull sprite from
        ver:      Version within generation to pull sprite from
        form:     Choose form if pokemon has more than one

    Notes:
        X and Y coordinates are anchored to the top left of the bounding box
        for the sprite, 0,0 is the top left of the display.

    Todo:
        Sprites are currently stored using sprites from gen 2, but without
        an indicator by filename to indicate generation. I think the best
        solution may be to make each sprite file a full sheet, with gen 1 left
        aligned. This will require shifting all of the sprites over 56 pixels
        as they are gen 2, but it would help expansion in the future if done now.

    """
    box = Image.open("assets/ui/spritebox.png")
    sprite_sheet = Image.open("assets/sprites/{:03d}.png".format(id))

    # TODO: Put this next line in a try/except or get index errors for high gens
    # sprite = sprite_sheet.crop((0, 56 * ver, 56, 56 + 56 * ver))
    sprite = random.choice(mon.sprites)

    img.paste(box, location, create_mask(box))
    img.paste(sprite, tuple(n + 6 for n in location), create_mask(sprite))
def pentagram(im: Image) -> Image:
    """Adds pentagram to the image."""
    im = im.convert("RGB")
    wt, ht = im.size
    penta = Image.open("bot/resources/halloween/bloody-pentagram.png")
    penta = penta.resize((wt, ht))
    im.paste(penta, (0, 0), penta)
    return im
Example #19
0
def get_superimposed_icons(bg: Image,
                           fg: list,
                           size: int = _TILESIZE_WILD,
                           **kwargs) -> Image:
    """
    Returns a PIL image which is the superimposition of
    a background icon and a foreground icon (or more).

    """

    save = kwargs.get("save")
    caller = kwargs.get("caller")
    bg = bg.convert("RGBA")

    if len(fg) > 1:
        fg = sort_by_visibility(fg)

        if caller and caller in fg:
            fg = [x for x in fg if x != caller]
            fg = fg[:3] + [caller]
        else:
            fg = fg[:4]

        rsize = int(size * 0.60)
        offset_x = int(size * (0.45 if save else 0))
        offset_y = int(size * (0.50 if save else 0))
        c = 0
        for obj in fg:
            c += 1
            obj = get_icon_from_name(obj.db.icon).convert("RGBA")
            obj = obj.resize((rsize, rsize), resample=Image.LANCZOS)
            bg.paste(obj, (offset_x, offset_y), obj)

            offset_x += int(size * (0.50 if save else 0.40))
            offset_y += int(size *
                            (0.50 if save else 0.35)) if len(fg) == 2 else 0
            if c % 2 == 0:
                offset_x = int(size * (0.45 if save else 0))
                offset_y += int(size * (0.50 if save else 0.35))

        return bg
    elif len(fg) == 1:
        fg = get_icon_from_name(fg[0].db.icon).convert("RGBA")
    elif len(fg) == 0:
        fg = get_icon_from_name().convert("RGBA")

    rsize = int(size * 0.80)
    fg = fg.resize((rsize, rsize), resample=Image.LANCZOS)

    width_fg, height_fg = fg.size
    width_bg, height_bg = bg.size

    offset_y = (width_bg - width_fg) // 2
    offset_x = (height_bg - height_fg) // 2

    bg.paste(fg, (offset_x, offset_y), fg)
    return bg
Example #20
0
def deepfry(img: Image,
            *,
            colours: ColourTuple = DefaultColours.red,
            flares: bool = True) -> Image:
    """
    Deepfry a given image.

    Parameters
    ----------
    img : `Image`
        Image to manipulate.
    colours : `ColourTuple`, optional
        A tuple of the colours to apply on the image.
    flares : `bool`, optional
        Whether or not to try and detect faces for applying lens flares.

    Returns
    -------
    `Image`
        Deepfried image.
    """
    img = img.copy().convert('RGB')
    flare_positions = []

    if flares:
        opencv_img = cv2.cvtColor(numpy.array(img), cv2.COLOR_RGB2GRAY)

    # Crush image to hell and back
    img = img.convert('RGB')
    width, height = img.width, img.height
    img = img.resize((int(width**.75), int(height**.75)),
                     resample=Image.LANCZOS)
    img = img.resize((int(width**.88), int(height**.88)),
                     resample=Image.BILINEAR)
    img = img.resize((int(width**.9), int(height**.9)), resample=Image.BICUBIC)
    img = img.resize((width, height), resample=Image.BICUBIC)
    img = ImageOps.posterize(img, 4)

    # Generate colour overlay
    r = img.split()[0]
    r = ImageEnhance.Contrast(r).enhance(2.0)
    r = ImageEnhance.Brightness(r).enhance(1.5)

    r = ImageOps.colorize(r, colours[0], colours[1])

    # Overlay red and yellow onto main image and sharpen the hell out of it
    img = Image.blend(img, r, 0.75)
    img = ImageEnhance.Sharpness(img).enhance(100.0)

    # Apply flares on any detected eyes
    for flare in flare_positions:
        flare_transformed = flare_img.copy().resize((flare.size, ) * 2,
                                                    resample=Image.BILINEAR)
        img.paste(flare_transformed, (flare.x, flare.y), flare_transformed)

    return img
Example #21
0
def get_layered_icon(base: Image, layers: list) -> Image:
    """
    Add layer on top of base tile. Called by add_rivers() and such.

    """
    base = base.convert("RGB")
    for layer in layers:
        layer = get_wild_tile_from_name(layer).convert("RGBA")
        base.paste(layer, (0, 0), layer)
    return base
Example #22
0
 def make_beautiful_img(self, template: Image, avatar: Image) -> BytesIO:
     # print(template.info)
     template = template.convert("RGBA")
     avatar = avatar.convert("RGBA")
     template.paste(avatar, (370, 45), avatar)
     template.paste(avatar, (370, 330), avatar)
     temp = BytesIO()
     template.save(temp, format="PNG")
     temp.name = "beautiful.png"
     return temp
Example #23
0
 def draw_on(self, image: Image, box: BoxT, debug=False):
     x1, y1, x2, y2 = box
     w, h = x2 - x1, y2 - y1
     img = Image.new('L', (w, h), 'white')
     self.node.draw_on(img, (0,0,w,h), debug=debug)
     if debug:
         draw = ImageDraw.Draw(img)
         draw.rectangle((1,1,w-1,h-1))
     rotated = img.rotate(self.angle_deg, fillcolor='white')
     image.paste(rotated, box=box)
Example #24
0
def add_darkness(minimap: Image, br: int) -> Image:
    """
    Superimpose darkness levels to the already composed minimap.

    """
    if br < 4:
        dark_level = "dark" + str(br)
        fg = os.path.join(_ASSETS_LOCATION, dark_level) + ".png"
        fg = Image.open(fg).convert("RGBA")
        minimap.paste(fg, (0, 0), fg)
    return minimap
Example #25
0
def paste(im:Image,b:bytes,screensize,index):
    w,h = screensize
    row,col = index
    x = col*(w-20)
    y = row*(h-20)
    box = (x,y)
    bio = BytesIO()
    bio.write(b)
    bio.seek(0)
    tmp = Image.open(bio)
    im.paste(tmp,box)
Example #26
0
def _render_rotated(img: Image, font: ImageFont, color: Color, x, y, angle,
                    string: str):
    """render text rotated by an angle by creating a seperate image with the 
    text, rotating it, and pasting it onto the target image"""

    # create a new image with a transparent alpha channel
    txt = Image.new("RGBA", (800, 400), (255, 255, 255, 0))
    d = ImageDraw.Draw(txt)
    d.text((0, 0), string, (*color.value, 255), font)
    w = txt.rotate(angle, resample=Image.BICUBIC, expand=True)
    img.paste(w, (x, y), w)
Example #27
0
 def _draw_header(self, img: Image, today: datetime):
     draw = ImageDraw.Draw(img)
     #clock
     rbtv_printer.printClock((0,0), img, today)
     #views
     rbtv_printer.printViews((345, 70), img, self.api.getStreamCount())
     #views
     rbtv_printer.printSelf((5, 75), img, self.api.getSelf(), self.api.getNotifications())
     #placeholder for preview image
     img.paste(rbtv_config.preview_placeholder, (600-250, 0))
     return img
Example #28
0
def paste_single_map(template: Image, map_: Image) -> Image:
    """
    Overlays a single map image on to the template image
    Args:
        template (Image): The base template image
        map_ (Image): The single image to paste on the template
    Returns:
        Image: The template image with the map image pasted on
    """
    paste_coords = (148, 652)
    template.paste(map_, paste_coords)
    return template
Example #29
0
 def make_badge(template: Image, avatar: Image):
     """Create basic badge from regular avatar"""
     watermark = avatar.convert("RGBA")
     watermark.putalpha(128)
     watermark = watermark.resize((100, 100))
     id_image = avatar.resize((165, 165))
     template.paste(watermark, (845, 45, 945, 145), watermark)
     template.paste(id_image, (60, 95, 225, 260))
     temp = BytesIO()
     template.save(temp, format="PNG")
     temp.name = "temp.gif"
     return temp
Example #30
0
 def draw(self, im: Image, im_ry: Image = None):
     x_space = int(im.size[0] * self.s)
     y_space = int(im.size[1] * self.s)
     xy = (x_space, y_space)
     new_size = (int(im.size[0] - (x_space * 2)),
                 int(im.size[1] - (y_space * 2)))
     new_image = View.create_image(new_size)
     new_image_ry = View.create_image(new_size)
     self.c.draw(new_image, new_image_ry)
     im.paste(new_image, xy)
     if im_ry is not None:
         im_ry.paste(new_image_ry, xy)
def spotlight(img: Image, center: (int, int), radius: int) -> Image:
    width, height = img.size
    overlay_color = (0, 0, 0, 128)
    img_overlay = Image.new(size=img.size, color=overlay_color, mode='RGBA')
    for x in range(width):
        for y in range(height):
            dx = x - center[0]
            dy = y - center[1]
            distance = math.sqrt(dx * dx + dy * dy)
            if distance < radius:
                img_overlay.putpixel((x, y), (0, 0, 0, 0))
    img.paste(img_overlay, None, mask=img_overlay)
    return img
def overlay(img: Image, overlay_color: tuple, orig_file_name:str):
    """
    Place an overlay over an existing image

    :param img: Image opened with PIL.Image
    :param overlay_color: four-tuple with color to add to your image
    :param orig_file_name: name of the original file
    """

    assert len(overlay_color) == 4, 'Overlay color shall be a 4-tuple'

    img_overlay = Image.new(size=img.size, color=overlay_color, mode='RGBA')
    img.paste(img_overlay, None, mask=img_overlay)

    color_string = '_'.join([str(c) for c in overlay_color])
    filename = '{orig}_overlay_{color}.jpg'.format(orig=orig_file_name, color=color_string)
    save_img(img, filename)