示例#1
0
文件: util.py 项目: MinshuG/Athena
    def Font(
        self,
        size: int,
        font: str = "BurbankBigCondensed-Black.otf",
        directory: str = "assets/fonts/",
    ):
        """Return a font object with the specified font file and size."""

        try:
            return ImageFont.truetype(f"{directory}{font}", size)
        except OSError:
            Log.Warn(
                self,
                "BurbankBigCondensed-Black.otf not found, defaulted font to LuckiestGuy-Regular.ttf",
            )

            return ImageFont.truetype(f"{directory}LuckiestGuy-Regular.ttf",
                                      size)
        except Exception as e:
            Log.Error(self, f"Failed to load font, {e}")
示例#2
0
    def GenerateImage(self, date: str, itemShop: dict):
        """
        Generate the Item Shop image using the provided Item Shop.

        Return True if image sucessfully saved.
        """

        try:
            featured = itemShop["featured"]
            daily = itemShop["daily"]

            # Ensure both Featured and Daily have at least 1 item
            if (len(featured) <= 0) or (len(daily) <= 0):
                raise Exception(
                    f"Featured: {len(featured)}, Daily: {len(daily)}")
        except Exception as e:
            Log.Error(
                self,
                f"Failed to parse Item Shop Featured and Daily items, {e}")

            return False

        # Determine the max amount of rows required for the current
        # Item Shop when there are 3 columns for both Featured and Daily.
        # This allows us to determine the image height.
        rows = max(ceil(len(featured) / 3), ceil(len(daily) / 3))
        shopImage = Image.new("RGB", (1920, ((545 * rows) + 340)))

        try:
            background = ImageUtil.Open(self, "background.png")
            background = ImageUtil.RatioResize(self, background,
                                               shopImage.width,
                                               shopImage.height)
            shopImage.paste(
                background,
                ImageUtil.CenterX(self, background.width, shopImage.width))
        except FileNotFoundError:
            Log.Warn(self,
                     "Failed to open background.png, defaulting to dark gray")
            shopImage.paste((18, 18, 18),
                            [0, 0, shopImage.size[0], shopImage.size[1]])

        logo = ImageUtil.Open(self, "logo.png")
        logo = ImageUtil.RatioResize(self, logo, 0, 210)
        shopImage.paste(
            logo, ImageUtil.CenterX(self, logo.width, shopImage.width, 20),
            logo)

        canvas = ImageDraw.Draw(shopImage)
        font = ImageUtil.Font(self, 48)
        textWidth, _ = font.getsize(date)
        canvas.text(
            ImageUtil.CenterX(self, textWidth, shopImage.width, 255),
            date,
            (255, 255, 255),
            font=font,
        )
        canvas.text((20, 255), "Featured", (255, 255, 255), font=font)
        textWidth, _ = font.getsize("Daily")
        canvas.text(
            (shopImage.width - (textWidth + 20), 255),
            "Daily",
            (255, 255, 255),
            font=font,
        )

        # Track grid position
        i = 0

        for item in featured:
            card = Athena.GenerateCard(self, item)

            if card is not None:
                shopImage.paste(
                    card,
                    (
                        (20 + ((i % 3) * (card.width + 5))),
                        (315 + ((i // 3) * (card.height + 5))),
                    ),
                    card,
                )

                i += 1

        # Reset grid position
        i = 0

        for item in daily:
            card = Athena.GenerateCard(self, item)

            if card is not None:
                shopImage.paste(
                    card,
                    (
                        (990 + ((i % 3) * (card.width + 5))),
                        (315 + ((i // 3) * (card.height + 5))),
                    ),
                    card,
                )

                i += 1

        try:
            shopImage.save("itemshop.png")
            Log.Success(self, "Generated Item Shop image")

            return True
        except Exception as e:
            Log.Error(self, f"Failed to save Item Shop image, {e}")
示例#3
0
    def GenerateCard(self, item: dict):
        """Return the card image for the provided Fortnite Item Shop item."""

        try:
            name = item["items"][0]["name"]
            rarity = item["items"][0]["rarity"]
            displayrarity = item["items"][0]["displayRarity"]
            category = item["items"][0]["type"]
            price = str(item["finalPrice"])
            if (category == "outfit") or (category == "wrap"):
                if item["items"][0]["images"]["featured"] is not None:
                    icon = item["items"][0]["images"]["featured"]["url"]
                else:
                    icon = item["items"][0]["images"]["icon"]["url"]
            else:
                icon = item["items"][0]["images"]["icon"]["url"]
        except Exception as e:
            Log.Error(self, f"Failed to parse item {name}, {e}")

            return

        if rarity == "common":
            blendColor = (190, 190, 190)
        elif rarity == "uncommon":
            blendColor = (96, 170, 58)
        elif rarity == "rare":
            blendColor = (73, 172, 242)
        elif rarity == "epic":
            blendColor = (177, 91, 226)
        elif rarity == "legendary":
            blendColor = (211, 120, 65)
        elif rarity == "marvel":
            blendColor = (197, 51, 52)
        elif rarity == "dark":
            blendColor = (251, 34, 223)
        elif rarity == "dc":
            blendColor = (84, 117, 199)
        else:
            blendColor = (255, 255, 255)

        card = Image.new("RGBA", (300, 545))

        try:
            layer = ImageUtil.Open(self, f"card_top_{rarity.lower()}.png")
        except FileNotFoundError:
            Log.Warn(
                self,
                f"Failed to open card_top_{rarity.lower()}.png, defaulted to Common",
            )
            layer = ImageUtil.Open(self, "card_top_common.png")

        card.paste(layer)

        if category == 'glider':
            x = 285 / 1.1
            y = 365 / 1.8
            distanceTop = 60
        elif category == 'music':
            x = 285 / 1.1
            y = 365 / 1.6
            distanceTop = 55
        elif category == 'pickaxe':
            x = 285 / 1.1
            y = 365 / 1.3
            distanceTop = 40
        elif category == 'wrap':
            x = 285 / 1.1
            y = 365 / 1.3
            distanceTop = 40
        else:
            x = 285
            y = 365
            distanceTop = 10

        icon = ImageUtil.Download(self, icon)
        icon = ImageUtil.RatioResize(self, icon, x, y)
        card.paste(
            icon,
            ImageUtil.CenterX(self,
                              icon.width,
                              card.width,
                              distanceTop=distanceTop), icon)

        if len(item["items"]) > 1:
            # Track grid position
            i = 0

            # Start at position 1 in items array
            for extra in item["items"][1:]:
                try:
                    extraRarity = extra["rarity"]
                    extraIcon = extra["images"]["smallIcon"]["url"]
                except Exception as e:
                    Log.Error(self, f"Failed to parse item {name}, {e}")

                    return

                try:
                    layer = ImageUtil.Open(
                        self, f"box_bottom_{extraRarity.lower()}.png")
                except FileNotFoundError:
                    Log.Warn(
                        self,
                        f"Failed to open box_bottom_{extraRarity.lower()}.png, defaulted to Common",
                    )
                    layer = ImageUtil.Open(self, "box_bottom_common.png")

                card.paste(layer, (17, (17 + ((i // 1) * (layer.height)))))

                extraIcon = ImageUtil.Download(self, extraIcon)
                extraIcon = ImageUtil.RatioResize(self, extraIcon, 75, 75)

                card.paste(extraIcon,
                           (17, (17 + ((i // 1) * (extraIcon.height)))),
                           extraIcon)

                try:
                    layer = ImageUtil.Open(
                        self, f"box_faceplate_{extraRarity.lower()}.png")
                except FileNotFoundError:
                    Log.Warn(
                        self,
                        f"Failed to open box_faceplate_{extraRarity.lower()}.png, defaulted to Common",
                    )
                    layer = ImageUtil.Open(self, "box_faceplate_common.png")

                card.paste(layer, (17, (17 + ((i // 1) * (layer.height)))),
                           layer)

                i += 1

        try:
            layer = ImageUtil.Open(self,
                                   f"card_faceplate_{rarity.lower()}.png")
        except FileNotFoundError:
            Log.Warn(
                self,
                f"Failed to open card_faceplate_{rarity.lower()}.png, defaulted to Common",
            )
            layer = ImageUtil.Open(self, "card_faceplate_common.png")

        card.paste(layer, layer)

        try:
            layer = ImageUtil.Open(self, f"card_bottom_{rarity.lower()}.png")
        except FileNotFoundError:
            Log.Warn(
                self,
                f"Failed to open card_bottom_{rarity.lower()}.png, defaulted to Common",
            )
            layer = ImageUtil.Open(self, "card_bottom_common.png")

        card.paste(layer, layer)

        canvas = ImageDraw.Draw(card)

        font = ImageUtil.Font(self, 30)
        textWidth, _ = font.getsize(f"{displayrarity} {category.title()}")
        canvas.text(
            ImageUtil.CenterX(self, textWidth, card.width, 385),
            f"{displayrarity} {category.title()}",
            blendColor,
            font=font,
        )

        vbucks = ImageUtil.Open(self, "vbucks.png")
        vbucks = ImageUtil.RatioResize(self, vbucks, 25, 25)

        textWidth, _ = font.getsize(price)
        canvas.text(
            ImageUtil.CenterX(self, ((textWidth - 5) - vbucks.width),
                              card.width, 495),
            price,
            (255, 255, 255),
            font=font,
        )

        card.paste(
            vbucks,
            ImageUtil.CenterX(self, (vbucks.width + (textWidth + 5)),
                              card.width, 495),
            vbucks,
        )

        font = ImageUtil.Font(self, 56)
        textWidth, _ = font.getsize(name)
        if textWidth >= 270:
            # Ensure that the item name does not overflow
            font, textWidth = ImageUtil.FitTextX(self, name, 56, 265)
        canvas.text(
            ImageUtil.CenterX(self, textWidth, card.width, 425),
            name,
            (255, 255, 255),
            font=font,
        )

        return card