Exemplo n.º 1
0
    def render_traits(image):
        traits_images_b64 = [
            trait_image_task(
                trait_args["trait_id"],
                trait_args["trait_name"],
                trait_args["trait_count"],
                trait_args["trait_sets"],
            ) for trait_args in traits
        ]

        trait_images_rgba = [
            load_base64_image(trait_image_b64)
            for trait_image_b64 in traits_images_b64 if trait_image_b64
        ]

        if len(trait_images_rgba) == 0:
            # no traits to draw
            return image

        # assume same size -> probably safe
        height_per_trait = trait_images_rgba[0].shape[0]

        for idx, trait_image_rgba in enumerate(trait_images_rgba):
            trait_x = CHAMPION_HEX_X + CHAMPION_HEX_WIDTH + TRAITS_H_GUTTER
            trait_y = idx * (height_per_trait + TRAITS_V_GUTTER)

            overlay_transparent(image, trait_image_rgba, trait_x, trait_y)

        return image
Exemplo n.º 2
0
def og_meta_hexes_image_task(username, twitch_id, youtube_id, traits, hex_status_map):

    template_image = cv2.imread(PATH_TO_TEMPLATE, cv2.IMREAD_UNCHANGED)

    hexes_and_traits_image = load_base64_image(
        hexes_and_traits_task(hex_status_map=hex_status_map, traits=traits)
    )

    overlay_transparent(template_image, hexes_and_traits_image, HEXES_X, HEXES_Y)

    def render_username(template_image):

        with WandImage.from_array(
            cv2.cvtColor(template_image, cv2.COLOR_BGRA2RGBA)
        ) as img:
            with WandDrawing() as context:
                context.font_size = BASE_FONT_SIZE

                if username:
                    context.fill_color = "#f7d676"
                    # Icon height doesnt match measurements exactly... HEIGHT/2 would be best for y
                    context.text(x=LOGO_WIDTH + 2, y=28, body=f"/u/{username}")
                else:
                    context.fill_color = "white"
                    context.fill_opacity = 0.8
                    context.text(x=LOGO_WIDTH + 2, y=28, body="• Temporary build")

                context(img)

            img.format = "png"

            img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8)

            if img_buffer is not None:
                template_image = cv2.imdecode(img_buffer, cv2.IMREAD_UNCHANGED)

        return template_image

    template_image = render_username(template_image)

    if youtube_id or twitch_id:
        social_media_image = load_base64_image(
            make_social_media_image(twitch_id=twitch_id, youtube_id=youtube_id)
        )

        social_media_width = social_media_image.shape[1]

        social_media_x = IMAGE_WIDTH - social_media_width - 5

        template_image = cv2.convertScaleAbs(template_image, alpha=(255.0 / 65535.0))

        overlay_transparent(template_image, social_media_image, social_media_x, 5)

    retval, buffer = cv2.imencode(".png", template_image)

    if output_path:
        cv2.imwrite(output_path, template_image)

    return base64.b64encode(buffer)
Exemplo n.º 3
0
    def render_item_slots(image):
        item_slots_x = 0
        item_slots_y = 0

        for idx, item_id in enumerate(item_ids):
            item_slot_x = item_slots_x
            item_slot_y = item_slots_y + idx * (ITEM_SLOT_HEIGHT +
                                                ITEM_SLOT_V_GUTTER)

            item_picture = get_item_picture(item_id,
                                            ITEM_SLOT_WIDTH,
                                            is_shadow=len(item_id) > 2)

            overlay_transparent(image, item_picture, int(item_slot_x),
                                item_slot_y)

        return image
Exemplo n.º 4
0
    def render_stars(image):
        stars_center_x = CHAMPION_HEX_X + HEX_INRADIUS
        stars_y = CHAMPION_HEX_HEIGHT + STAR_V_GUTTER

        stars_width = star_level * (STAR_WIDTH + STAR_H_GUTTER)

        stars_x = stars_center_x - stars_width / 2
        star_filename = STAR_FILENAMES[str(star_level)]

        star_image = cv2.imread(os.path.join(PATH_TO_STARS, star_filename),
                                cv2.IMREAD_UNCHANGED)

        for idx in range(star_level):
            star_x = stars_x + idx * (STAR_WIDTH + STAR_H_GUTTER)

            overlay_transparent(image, star_image, int(star_x), int(stars_y))

        return image
Exemplo n.º 5
0
def hexes_and_traits_task(hex_status_map, traits):

    image = np.ones((IMAGE_HEIGHT, IMAGE_WIDTH, 4), dtype=np.uint8)

    hexes_img = load_base64_image(
        hexes_image_task(hex_status_map, width=HEXES_WIDTH))

    overlay_transparent(
        image,
        hexes_img,
        HEXES_X,
        HEXES_Y,
    )

    print(f"TRAITS_WIDTH, {TRAITS_WIDTH}, IMAGE_WIDTH, {IMAGE_WIDTH}")

    trait_compact_imgs = [
        load_base64_image(
            make_trait_compact_image(
                trait_id=trait["trait_id"],
                trait_name=trait["trait_name"],
                trait_style=trait["trait_style"],
                desired_width=TRAITS_WIDTH,
            )) for trait in traits
    ]

    # they should all have the same height; used for v-positioning
    (trait_image_height, trait_image_width,
     channels) = trait_compact_imgs[0].shape

    for idx, trait_compact_image in enumerate(trait_compact_imgs):
        trait_x = TRAITS_X
        trait_y = TRAITS_Y + idx * (trait_image_height + TRAITS_V_GUTTER)

        overlay_transparent(image, trait_compact_image, trait_x, trait_y)

    retval, buffer = cv2.imencode(".png", image)

    if output_path:
        cv2.imwrite(output_path, image)

    return base64.b64encode(buffer)
Exemplo n.º 6
0
        def make_untrimmed_social_media_img():
            social_config = [
                {
                    "id": twitch_id,
                    "image_path": os.path.join(
                        PATH_TO_ASSETS, "socials", "twitch-transparent.png"
                    ),
                },
                {
                    "id": youtube_id,
                    "image_path": os.path.join(
                        PATH_TO_ASSETS, "socials", "youtube-22.png"
                    ),
                },
            ]

            # more space than we'll ever need; crop later
            social_base_image = np.zeros(
                (LOGO_HEIGHT, int(CARRY_IMAGE_WIDTH / 2), 4), dtype=np.uint8
            )

            SOCIAL_ROW_HEIGHT = 16
            SOCIAL_ICON_WIDTH = 22

            config_to_apply = [config for config in social_config if config["id"]]

            for idx, config in enumerate(config_to_apply):
                social_id = config["id"]
                image_path = config["image_path"]

                social_icon_image = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)

                social_row_y = (SOCIAL_ROW_HEIGHT + 12) * idx

                overlay_transparent(
                    social_base_image, social_icon_image, 0, social_row_y
                )

                with WandImage.from_array(
                    cv2.cvtColor(social_base_image, cv2.COLOR_BGRA2RGBA)
                ) as img:
                    with WandDrawing() as context:
                        context.font_size = BASE_FONT_SIZE
                        context.fill_color = "white"

                        context.text(
                            x=SOCIAL_ICON_WIDTH + 2,
                            y=social_row_y + BASE_FONT_SIZE,
                            body=f"{social_id}",
                        )

                        context(img)

                    img.format = "png"

                    img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8)

                    if img_buffer is not None:
                        social_base_image = cv2.imdecode(
                            img_buffer, cv2.IMREAD_UNCHANGED
                        )

            return social_base_image
Exemplo n.º 7
0
def og_meta_carry_image_task(
    champion_id, star_level, item_ids, traits, username, twitch_id, youtube_id
):
    template_image = cv2.imread(PATH_TO_TEMPLATE, cv2.IMREAD_UNCHANGED)

    template_height, template_width, template_channels = template_image.shape

    carry_image = load_base64_image(
        carry_champion_image_task(champion_id, star_level, item_ids, traits)
    )

    overlay_transparent(template_image, carry_image, 5, LOGO_HEIGHT)

    def render_username(template_image):

        with WandImage.from_array(
            cv2.cvtColor(template_image, cv2.COLOR_BGRA2RGBA)
        ) as img:
            with WandDrawing() as context:
                context.font_size = BASE_FONT_SIZE

                if username:
                    context.fill_color = "#f7d676"
                    # Icon height doesnt match measurements exactly... HEIGHT/2 would be best for y
                    context.text(x=LOGO_WIDTH + 2, y=28, body=f"/u/{username}")
                else:
                    context.fill_color = "white"
                    context.fill_opacity = 0.8
                    context.text(x=LOGO_WIDTH + 2, y=28, body="• Temporary build")

                context(img)

            img.format = "png"

            img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8)

            if img_buffer is not None:
                template_image = cv2.imdecode(img_buffer, cv2.IMREAD_UNCHANGED)

        return template_image

    template_image = render_username(template_image)

    def render_social_media(template_image):
        if not (username and (twitch_id or youtube_id)):
            # nothing to do
            return template_image

        def make_untrimmed_social_media_img():
            social_config = [
                {
                    "id": twitch_id,
                    "image_path": os.path.join(
                        PATH_TO_ASSETS, "socials", "twitch-transparent.png"
                    ),
                },
                {
                    "id": youtube_id,
                    "image_path": os.path.join(
                        PATH_TO_ASSETS, "socials", "youtube-22.png"
                    ),
                },
            ]

            # more space than we'll ever need; crop later
            social_base_image = np.zeros(
                (LOGO_HEIGHT, int(CARRY_IMAGE_WIDTH / 2), 4), dtype=np.uint8
            )

            SOCIAL_ROW_HEIGHT = 16
            SOCIAL_ICON_WIDTH = 22

            config_to_apply = [config for config in social_config if config["id"]]

            for idx, config in enumerate(config_to_apply):
                social_id = config["id"]
                image_path = config["image_path"]

                social_icon_image = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)

                social_row_y = (SOCIAL_ROW_HEIGHT + 12) * idx

                overlay_transparent(
                    social_base_image, social_icon_image, 0, social_row_y
                )

                with WandImage.from_array(
                    cv2.cvtColor(social_base_image, cv2.COLOR_BGRA2RGBA)
                ) as img:
                    with WandDrawing() as context:
                        context.font_size = BASE_FONT_SIZE
                        context.fill_color = "white"

                        context.text(
                            x=SOCIAL_ICON_WIDTH + 2,
                            y=social_row_y + BASE_FONT_SIZE,
                            body=f"{social_id}",
                        )

                        context(img)

                    img.format = "png"

                    img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8)

                    if img_buffer is not None:
                        social_base_image = cv2.imdecode(
                            img_buffer, cv2.IMREAD_UNCHANGED
                        )

            return social_base_image

        social_base_image = make_untrimmed_social_media_img()

        social_base_image = crop_to_contents(social_base_image)

        social_image_width = social_base_image.shape[1]

        social_image_x = template_width - social_image_width - 5

        # convert back to uint8 (wand turns things into uint16)
        template_image = cv2.convertScaleAbs(template_image, alpha=(255.0 / 65535.0))

        overlay_transparent(
            template_image,
            social_base_image,
            social_image_x,
            5,
        )

        return template_image

    template_image = render_social_media(template_image)

    retval, buffer = cv2.imencode(".png", template_image)

    if output_path:
        cv2.imwrite(output_path, template_image)

    return base64.b64encode(buffer)
Exemplo n.º 8
0
def carry_champion_image_task(champion_id, star_level, item_ids, traits):

    image = np.zeros((IMG_HEIGHT, IMG_WIDTH, 4), dtype=np.uint8)

    champion_hex_picture = get_champion_hex_picture(
        champion_id, desired_width=CHAMPION_HEX_WIDTH)

    overlay_transparent(
        image,
        champion_hex_picture,
        CHAMPION_HEX_X,
        0,
    )

    def render_hex_border(image):
        center_x = CHAMPION_HEX_X + HEX_INRADIUS
        center_y = HEX_CIRCUMRADIUS

        circumradius_no_stroke = HEX_CIRCUMRADIUS - CHAMPION_HEX_STROKE / 2

        def map_vertex_to_position(vertex: int):
            x = center_x + math.sin(
                INTERIOR_ANGLE * vertex) * circumradius_no_stroke
            y = center_y - math.cos(
                INTERIOR_ANGLE * vertex) * circumradius_no_stroke

            return (x, y)

        hex_vertices = np.array(
            [map_vertex_to_position(vertex) for vertex in range(6)],
            dtype=np.int32)

        hex_stroke = STAR_COLORS[str(star_level)]

        cv2.polylines(
            image,
            [hex_vertices],
            True,
            hex_stroke,
            thickness=int(CHAMPION_HEX_STROKE),
        )

        return image

    image = render_hex_border(image)

    # attach traits
    def render_traits(image):
        traits_images_b64 = [
            trait_image_task(
                trait_args["trait_id"],
                trait_args["trait_name"],
                trait_args["trait_count"],
                trait_args["trait_sets"],
            ) for trait_args in traits
        ]

        trait_images_rgba = [
            load_base64_image(trait_image_b64)
            for trait_image_b64 in traits_images_b64 if trait_image_b64
        ]

        if len(trait_images_rgba) == 0:
            # no traits to draw
            return image

        # assume same size -> probably safe
        height_per_trait = trait_images_rgba[0].shape[0]

        for idx, trait_image_rgba in enumerate(trait_images_rgba):
            trait_x = CHAMPION_HEX_X + CHAMPION_HEX_WIDTH + TRAITS_H_GUTTER
            trait_y = idx * (height_per_trait + TRAITS_V_GUTTER)

            overlay_transparent(image, trait_image_rgba, trait_x, trait_y)

        return image

    image = render_traits(image)

    # attach stars
    def render_stars(image):
        stars_center_x = CHAMPION_HEX_X + HEX_INRADIUS
        stars_y = CHAMPION_HEX_HEIGHT + STAR_V_GUTTER

        stars_width = star_level * (STAR_WIDTH + STAR_H_GUTTER)

        stars_x = stars_center_x - stars_width / 2
        star_filename = STAR_FILENAMES[str(star_level)]

        star_image = cv2.imread(os.path.join(PATH_TO_STARS, star_filename),
                                cv2.IMREAD_UNCHANGED)

        for idx in range(star_level):
            star_x = stars_x + idx * (STAR_WIDTH + STAR_H_GUTTER)

            overlay_transparent(image, star_image, int(star_x), int(stars_y))

        return image

    image = render_stars(image)

    def render_item_slots(image):
        item_slots_x = 0
        item_slots_y = 0

        for idx, item_id in enumerate(item_ids):
            item_slot_x = item_slots_x
            item_slot_y = item_slots_y + idx * (ITEM_SLOT_HEIGHT +
                                                ITEM_SLOT_V_GUTTER)

            item_picture = get_item_picture(item_id,
                                            ITEM_SLOT_WIDTH,
                                            is_shadow=len(item_id) > 2)

            overlay_transparent(image, item_picture, int(item_slot_x),
                                item_slot_y)

        return image

    image = render_item_slots(image)

    retval, buffer = cv2.imencode(".png", image)

    if output_path:
        cv2.imwrite(output_path, image)

    return base64.b64encode(buffer)
Exemplo n.º 9
0
    def render_trait_name(image):

        trait_name_img = np.zeros(image.shape, dtype=np.uint8)

        icon_background_width = trait_style_background_img.shape[1]
        icon_background_height = trait_style_background_img.shape[0]

        trait_hex_inradius = icon_background_width / 2
        trait_hex_circumradius = icon_background_height / 2

        text_x = int(icon_background_width + TEXT_MARGIN_LEFT)
        text_centre_y = int(trait_hex_circumradius)

        (text_width, text_height) = get_text_dimensions(
            text=trait_name,
            font_size=BASE_FONT_SIZE,
        )

        pil_img = Image.fromarray(np.uint8(trait_name_img))

        # wanted to get text drawn with pillow; could not get working. Resorting to wand
        d = ImageDraw.Draw(pil_img)

        rect_x1 = int(trait_hex_inradius - TRAIT_BG_PADDING / 2)
        rect_y1 = int(text_centre_y - text_height / 2 - TRAIT_BG_PADDING / 2)
        rect_x2 = int(
            trait_hex_inradius
            + TEXT_MARGIN_LEFT
            + rect_x1
            + text_width
            + TRAIT_BG_PADDING
        )
        rect_y2 = int(rect_y1 + text_height + TRAIT_BG_PADDING)

        d.rectangle(
            [(rect_x1, rect_y1), (rect_x2, rect_y2)],
            fill=TRAIT_BG,
        )
        trait_name_img = np.asarray(pil_img)

        with WandImage.from_array(
            cv2.cvtColor(trait_name_img, cv2.COLOR_BGRA2RGBA)
        ) as img:
            with WandDrawing() as context:
                context.fill_color = "white"

                path_to_font = os.path.join(
                    PATH_TO_ASSETS,
                    "fonts",
                    "Heebo-Bold.ttf",
                )


                context.font = path_to_font

                context.font_size = BASE_FONT_SIZE

                text_y = int(text_centre_y + BASE_FONT_SIZE / 3)  # idk why 3

                context.text(text_x, text_y, trait_name)

                context(img)

            img.format = "png"

            img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8)

        if img_buffer is not None:
            # # uint16 -> uint8 conversion (needed coming from wand)
            trait_name_img = cv2.imdecode(img_buffer, cv2.IMREAD_UNCHANGED)
            trait_name_img = cv2.convertScaleAbs(
                trait_name_img, alpha=(255.0 / 65535.0)
            )

            overlay_transparent(trait_name_img, image, 0, 0)

        return trait_name_img
Exemplo n.º 10
0
def make_trait_compact_image(trait_id, trait_name, trait_style, desired_width):

    image = np.zeros((BASE_HEIGHT, BASE_WIDTH, 4), dtype=np.uint8)

    trait_style_background_img = cv2.imread(
        os.path.join(PATH_TO_TRAITS_BG, f"{trait_style}.png"),
        cv2.IMREAD_UNCHANGED,
    )

    overlay_transparent(
        image,
        trait_style_background_img,
        0,
        0,
    )

    trait_hex_height = trait_style_background_img.shape[0]

    trait_icon_path = os.path.join(PATH_TO_TRAITS, f"{trait_name.lower()}.png")

    trait_icon_img = cv2.imread(
        trait_icon_path,
        cv2.IMREAD_UNCHANGED,
    )

    trait_icon_img = extract_icon_from_trait(trait_icon_img)

    trait_icon_width = trait_icon_img.shape[1]
    trait_icon_height = trait_icon_img.shape[0]

    trait_icon_scale_ratio = trait_hex_height / trait_icon_height

    trait_icon_desired_width = int(trait_icon_scale_ratio * trait_icon_width)

    trait_icon_img = cv2.resize(
        trait_icon_img,
        (trait_icon_desired_width, trait_hex_height),
        interpolation=cv2.INTER_AREA,
    )

    overlay_transparent(
        image,
        trait_icon_img,
        2,
        0,
    )

    def render_trait_name(image):

        trait_name_img = np.zeros(image.shape, dtype=np.uint8)

        icon_background_width = trait_style_background_img.shape[1]
        icon_background_height = trait_style_background_img.shape[0]

        trait_hex_inradius = icon_background_width / 2
        trait_hex_circumradius = icon_background_height / 2

        text_x = int(icon_background_width + TEXT_MARGIN_LEFT)
        text_centre_y = int(trait_hex_circumradius)

        (text_width, text_height) = get_text_dimensions(
            text=trait_name,
            font_size=BASE_FONT_SIZE,
        )

        pil_img = Image.fromarray(np.uint8(trait_name_img))

        # wanted to get text drawn with pillow; could not get working. Resorting to wand
        d = ImageDraw.Draw(pil_img)

        rect_x1 = int(trait_hex_inradius - TRAIT_BG_PADDING / 2)
        rect_y1 = int(text_centre_y - text_height / 2 - TRAIT_BG_PADDING / 2)
        rect_x2 = int(
            trait_hex_inradius
            + TEXT_MARGIN_LEFT
            + rect_x1
            + text_width
            + TRAIT_BG_PADDING
        )
        rect_y2 = int(rect_y1 + text_height + TRAIT_BG_PADDING)

        d.rectangle(
            [(rect_x1, rect_y1), (rect_x2, rect_y2)],
            fill=TRAIT_BG,
        )
        trait_name_img = np.asarray(pil_img)

        with WandImage.from_array(
            cv2.cvtColor(trait_name_img, cv2.COLOR_BGRA2RGBA)
        ) as img:
            with WandDrawing() as context:
                context.fill_color = "white"

                path_to_font = os.path.join(
                    PATH_TO_ASSETS,
                    "fonts",
                    "Heebo-Bold.ttf",
                )


                context.font = path_to_font

                context.font_size = BASE_FONT_SIZE

                text_y = int(text_centre_y + BASE_FONT_SIZE / 3)  # idk why 3

                context.text(text_x, text_y, trait_name)

                context(img)

            img.format = "png"

            img_buffer = np.asarray(bytearray(img.make_blob()), dtype=np.uint8)

        if img_buffer is not None:
            # # uint16 -> uint8 conversion (needed coming from wand)
            trait_name_img = cv2.imdecode(img_buffer, cv2.IMREAD_UNCHANGED)
            trait_name_img = cv2.convertScaleAbs(
                trait_name_img, alpha=(255.0 / 65535.0)
            )

            overlay_transparent(trait_name_img, image, 0, 0)

        return trait_name_img

    image = render_trait_name(image)

    resize_factor = desired_width / BASE_WIDTH

    desired_height = int(resize_factor * BASE_HEIGHT)

    image = cv2.resize(
        image,
        (desired_width, desired_height),
        interpolation=cv2.INTER_AREA,
    )

    if output_path:
        cv2.imwrite(output_path, image)

    retval, buffer = cv2.imencode(".png", image)

    return base64.b64encode(buffer)