✨ 全新的帮助图绘制函数, 用于统一管理插件帮助
@ -1,16 +1,13 @@
|
||||
import asyncio
|
||||
import inspect
|
||||
|
||||
from gsuid_core.aps import scheduler
|
||||
from gsuid_core.logger import logger
|
||||
from gsuid_core.server import GsServer
|
||||
from gsuid_core.help.draw_help import get_help_img
|
||||
|
||||
gss = GsServer()
|
||||
if not gss.is_load:
|
||||
gss.is_load = True
|
||||
gss.load_plugins()
|
||||
asyncio.run(get_help_img())
|
||||
|
||||
repeat_jobs = {}
|
||||
for i in scheduler.get_jobs():
|
||||
|
@ -1,232 +0,0 @@
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple, Union, Optional
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
from gsuid_core.sv import SV, Plugins
|
||||
|
||||
# from gsuid_core.utils.image.image_tools import get_color_bg
|
||||
from gsuid_core.utils.fonts.fonts import core_font
|
||||
from gsuid_core.utils.plugins_config.gs_config import pic_gen_config
|
||||
|
||||
pic_quality: int = pic_gen_config.get_config('PicQuality').data
|
||||
TEXT_PATH = Path(__file__).parent / 'texture2d'
|
||||
CORE_HELP_IMG = Path(__file__).parent / 'core_help.jpg'
|
||||
|
||||
plugin_title = 92
|
||||
sv_title = 67
|
||||
|
||||
tag_color = {
|
||||
'prefix': (137, 228, 124),
|
||||
'suffix': (124, 180, 228),
|
||||
'file': (190, 228, 217),
|
||||
'keyword': (217, 228, 254),
|
||||
'fullmatch': (228, 124, 124),
|
||||
'regex': (225, 228, 124),
|
||||
'command': (228, 124, 124),
|
||||
'message': (176, 150, 198),
|
||||
'other': (228, 190, 191),
|
||||
}
|
||||
|
||||
tag_text: Dict[str, str] = {
|
||||
'prefix': '前缀',
|
||||
'suffix': '后缀',
|
||||
'file': '文件',
|
||||
'keyword': '包含',
|
||||
'fullmatch': '完全',
|
||||
'regex': '正则',
|
||||
'command': '命令',
|
||||
'message': '消息',
|
||||
'other': '其他',
|
||||
}
|
||||
|
||||
tags: Dict[str, Optional[Image.Image]] = {
|
||||
'prefix': None,
|
||||
'suffix': None,
|
||||
'file': None,
|
||||
'keyword': None,
|
||||
'fullmatch': None,
|
||||
'regex': None,
|
||||
'command': None,
|
||||
'other': None,
|
||||
'message': None,
|
||||
}
|
||||
|
||||
|
||||
def get_tag(tag_type: str) -> Image.Image:
|
||||
cache = tags[tag_type]
|
||||
if cache is not None:
|
||||
return cache
|
||||
text = tag_text[tag_type]
|
||||
tag = Image.new('RGBA', (60, 40))
|
||||
tag_draw = ImageDraw.Draw(tag)
|
||||
tag_draw.rounded_rectangle((7, 5, 53, 35), 10, tag_color[tag_type])
|
||||
tag_draw.text((30, 20), text, (62, 62, 62), core_font(22), 'mm')
|
||||
tags[tag_type] = tag
|
||||
return tag
|
||||
|
||||
|
||||
def get_command_bg(command: str, tag_type: str):
|
||||
img = Image.new('RGBA', (220, 40))
|
||||
img_draw = ImageDraw.Draw(img)
|
||||
img_draw.rounded_rectangle((6, 5, 160, 35), 10, (230, 202, 167))
|
||||
img_draw.text((83, 20), command, (62, 62, 62), core_font(20), 'mm')
|
||||
tag = get_tag(tag_type)
|
||||
img.paste(tag, (160, 0), tag)
|
||||
return img
|
||||
|
||||
|
||||
def _c(data: Union[int, str, bool]) -> Tuple[int, int, int]:
|
||||
gray_color = (184, 184, 184)
|
||||
|
||||
if isinstance(data, bool):
|
||||
color = tag_color['prefix'] if data else gray_color
|
||||
elif isinstance(data, str):
|
||||
color = (
|
||||
tag_color['prefix']
|
||||
if data == 'ALL'
|
||||
else tag_color['command'] if data == 'GROUP' else tag_color['file']
|
||||
)
|
||||
else:
|
||||
colors = list(tag_color.values())
|
||||
if data <= len(colors) and data >= 0:
|
||||
color = colors[data]
|
||||
else:
|
||||
color = tag_color['other']
|
||||
return color
|
||||
|
||||
|
||||
def _t(data: Union[int, str, bool]) -> str:
|
||||
if isinstance(data, bool):
|
||||
text = '开启' if data else '关闭'
|
||||
elif isinstance(data, str):
|
||||
text = (
|
||||
'不限' if data == 'ALL' else '群聊' if data == 'GROUP' else '私聊'
|
||||
)
|
||||
else:
|
||||
texts = [
|
||||
'主人',
|
||||
'超管',
|
||||
'群主',
|
||||
'管理',
|
||||
'频管',
|
||||
'子管',
|
||||
'正常',
|
||||
'低',
|
||||
'黑',
|
||||
]
|
||||
if data <= len(texts) and data >= 0:
|
||||
text = [
|
||||
'主人',
|
||||
'超管',
|
||||
'群主',
|
||||
'管理',
|
||||
'频管',
|
||||
'子管',
|
||||
'正常',
|
||||
'低',
|
||||
'黑',
|
||||
][data]
|
||||
else:
|
||||
text = '最低'
|
||||
return text
|
||||
|
||||
|
||||
def get_plugin_bg(plugin: Plugins, sv_list: List[SV]):
|
||||
plugin_name = plugin.name
|
||||
img_list: List[Image.Image] = []
|
||||
|
||||
for sv in sv_list:
|
||||
sv_img = Image.new(
|
||||
'RGBA',
|
||||
(
|
||||
900,
|
||||
sv_title + ((len(sv.TL) + 3) // 4) * 40,
|
||||
),
|
||||
)
|
||||
sv_img_draw = ImageDraw.Draw(sv_img)
|
||||
|
||||
index = 0
|
||||
for type in sv.TL:
|
||||
for trigger_name in sv.TL[type]:
|
||||
tg_img = get_command_bg(
|
||||
trigger_name, sv.TL[type][trigger_name].type
|
||||
)
|
||||
sv_img.paste(
|
||||
tg_img,
|
||||
(6 + 220 * (index % 4), 67 + 40 * (index // 4)),
|
||||
tg_img,
|
||||
)
|
||||
index += 1
|
||||
index = 0
|
||||
|
||||
sv_img_draw.rounded_rectangle((15, 19, 25, 50), 10, (62, 62, 62))
|
||||
sv_img_draw.text((45, 31), sv.name, (62, 62, 62), core_font(36), 'lm')
|
||||
|
||||
sv_img_draw.rounded_rectangle((710, 15, 760, 50), 10, _c(sv.enabled))
|
||||
sv_img_draw.rounded_rectangle((770, 15, 820, 50), 10, _c(sv.pm))
|
||||
sv_img_draw.rounded_rectangle((830, 15, 880, 50), 10, _c(sv.area))
|
||||
|
||||
sv_img_draw.text(
|
||||
(735, 32), _t(sv.enabled), (62, 62, 62), core_font(22), 'mm'
|
||||
)
|
||||
sv_img_draw.text(
|
||||
(795, 32), _t(sv.pm), (62, 62, 62), core_font(22), 'mm'
|
||||
)
|
||||
sv_img_draw.text(
|
||||
(855, 32), _t(sv.area), (62, 62, 62), core_font(22), 'mm'
|
||||
)
|
||||
img_list.append(sv_img)
|
||||
|
||||
img = Image.new(
|
||||
'RGBA',
|
||||
(
|
||||
900,
|
||||
plugin_title + sum([i.size[1] for i in img_list]),
|
||||
),
|
||||
)
|
||||
img_draw = ImageDraw.Draw(img)
|
||||
img_draw.rounded_rectangle((10, 26, 890, 76), 10, (230, 202, 167))
|
||||
img_draw.text((450, 51), plugin_name, (62, 62, 62), core_font(42), 'mm')
|
||||
|
||||
temp = 0
|
||||
for _img in img_list:
|
||||
img.paste(_img, (0, 92 + temp), _img)
|
||||
temp += _img.size[1]
|
||||
|
||||
return img
|
||||
|
||||
|
||||
async def get_help_img() -> Image.Image:
|
||||
from gsuid_core.sv import SL
|
||||
|
||||
content = SL.detail_lst
|
||||
img_list: List[Image.Image] = []
|
||||
for plugin in content:
|
||||
plugin_img = get_plugin_bg(plugin, content[plugin])
|
||||
img_list.append(plugin_img)
|
||||
|
||||
x = 900
|
||||
y = 200 + sum([i.size[1] for i in img_list])
|
||||
# img = await get_color_bg(x, y)
|
||||
img = Image.new('RGBA', (x, y), (255, 255, 255))
|
||||
title = Image.open(TEXT_PATH / 'title.png')
|
||||
|
||||
# white = Image.new('RGBA', img.size, (255, 255, 255, 120))
|
||||
# img.paste(white, (0, 0), white)
|
||||
img.paste(title, (0, 50), title)
|
||||
|
||||
temp = 0
|
||||
for _img in img_list:
|
||||
img.paste(_img, (0, 340 + temp), _img)
|
||||
temp += _img.size[1]
|
||||
|
||||
img = img.convert('RGB')
|
||||
img.save(
|
||||
CORE_HELP_IMG,
|
||||
format='JPEG',
|
||||
quality=pic_quality,
|
||||
subsampling=0,
|
||||
)
|
||||
|
||||
return img
|
223
gsuid_core/help/draw_new_plugin_help.py
Normal file
@ -0,0 +1,223 @@
|
||||
import random
|
||||
from pathlib import Path
|
||||
from copy import deepcopy
|
||||
from typing import Dict, Literal, Optional
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
from gsuid_core.help.model import PluginHelp
|
||||
from gsuid_core.data_store import get_res_path
|
||||
from gsuid_core.utils.fonts.fonts import core_font
|
||||
from gsuid_core.utils.image.convert import convert_img
|
||||
from gsuid_core.utils.plugins_config.gs_config import pic_gen_config
|
||||
from gsuid_core.utils.image.image_tools import (
|
||||
crop_center_img,
|
||||
draw_color_badge,
|
||||
)
|
||||
|
||||
cache: Dict[str, int] = {}
|
||||
ICON_PATH = Path(__file__).parent / 'new_icon'
|
||||
TEXT_PATH = Path(__file__).parent / 'texture2d'
|
||||
pic_quality: int = pic_gen_config.get_config('PicQuality').data
|
||||
|
||||
|
||||
def find_icon(name: str, icon_path: Path = ICON_PATH):
|
||||
for icon in icon_path.glob('*.png'):
|
||||
if icon.stem == name:
|
||||
_r = icon
|
||||
break
|
||||
else:
|
||||
for icon in icon_path.glob('*.png'):
|
||||
if icon.stem in name:
|
||||
_r = icon
|
||||
break
|
||||
else:
|
||||
if (icon_path / '通用.png').exists():
|
||||
_r = icon_path / '通用.png'
|
||||
else:
|
||||
_r = random.choice(list(icon_path.iterdir()))
|
||||
return Image.open(_r)
|
||||
|
||||
|
||||
async def get_new_help(
|
||||
plugin_name: str,
|
||||
plugin_info: Dict[str, str],
|
||||
plugin_icon: Image.Image,
|
||||
plugin_help: Dict[str, PluginHelp],
|
||||
plugin_prefix: str = '',
|
||||
help_mode: Literal['dark', 'light'] = 'dark',
|
||||
banner_bg: Optional[Image.Image] = None,
|
||||
banner_sub_text: str = '💖且听风吟。',
|
||||
help_bg: Optional[Image.Image] = None,
|
||||
cag_bg: Optional[Image.Image] = None,
|
||||
item_bg: Optional[Image.Image] = None,
|
||||
icon_path: Path = ICON_PATH,
|
||||
footer: Optional[Image.Image] = None,
|
||||
enable_cache: bool = True,
|
||||
):
|
||||
help_path = get_res_path('help') / f'{plugin_name}.jpg'
|
||||
|
||||
if (
|
||||
help_path.exists()
|
||||
and plugin_name in cache
|
||||
and cache[plugin_name]
|
||||
and enable_cache
|
||||
):
|
||||
return await convert_img(Image.open(help_path))
|
||||
|
||||
if banner_bg is None:
|
||||
banner_bg = Image.open(TEXT_PATH / 'banner_bg.jpg')
|
||||
if help_bg is None:
|
||||
help_bg = Image.open(TEXT_PATH / 'help_bg.jpg')
|
||||
if cag_bg is None:
|
||||
cag_bg = Image.open(TEXT_PATH / 'cag_bg.png')
|
||||
if footer is None:
|
||||
footer = Image.open(TEXT_PATH / f'footer_{help_mode}.png')
|
||||
if item_bg is None:
|
||||
item_bg = Image.open(TEXT_PATH / f'item_{help_mode}.png')
|
||||
|
||||
if help_mode == 'dark':
|
||||
main_color = (255, 255, 255)
|
||||
sub_color = (206, 206, 206)
|
||||
else:
|
||||
main_color = (0, 0, 0)
|
||||
sub_color = (102, 102, 102)
|
||||
|
||||
banner_bg = banner_bg.convert('RGBA')
|
||||
help_bg = help_bg.convert('RGBA')
|
||||
cag_bg = cag_bg.convert('RGBA')
|
||||
item_bg = item_bg.convert('RGBA')
|
||||
footer = footer.convert('RGBA')
|
||||
|
||||
plugin_icon = plugin_icon.resize((128, 128))
|
||||
|
||||
# 准备计算整体帮助图大小
|
||||
w, h = 1545, 300 + footer.height
|
||||
|
||||
cag_num = len(plugin_help)
|
||||
h += cag_num * 100
|
||||
for cag in plugin_help:
|
||||
cag_data = plugin_help[cag]['data']
|
||||
sv_num = len(cag_data)
|
||||
h += (((sv_num - 1) // 3) + 1) * 175
|
||||
|
||||
# 基准图
|
||||
img = crop_center_img(help_bg, w, h)
|
||||
|
||||
# 绘制banner
|
||||
banner_bg.paste(plugin_icon, (89, 88), plugin_icon)
|
||||
banner_draw = ImageDraw.Draw(banner_bg)
|
||||
|
||||
_banner_name = plugin_name + '帮助'
|
||||
banner_draw.text(
|
||||
(262, 128),
|
||||
_banner_name,
|
||||
main_color,
|
||||
font=core_font(50),
|
||||
anchor='lm',
|
||||
)
|
||||
banner_draw.text(
|
||||
(262, 183),
|
||||
banner_sub_text,
|
||||
sub_color,
|
||||
font=core_font(30),
|
||||
anchor='lm',
|
||||
)
|
||||
x1, y1, x2, y2 = core_font(50).getbbox(_banner_name)
|
||||
plugin_name_len = int(x2 - x1)
|
||||
|
||||
for key, value in plugin_info.items():
|
||||
if value == 'any' or not value:
|
||||
value = (252, 69, 69)
|
||||
badge = draw_color_badge(
|
||||
key,
|
||||
value,
|
||||
core_font(30),
|
||||
(255, 255, 255),
|
||||
)
|
||||
banner_bg.paste(
|
||||
badge,
|
||||
(262 + plugin_name_len + 10, 128 - badge.height // 2),
|
||||
badge,
|
||||
)
|
||||
|
||||
plugin_name_len += badge.width + 10
|
||||
|
||||
img.paste(banner_bg, (0, 0), banner_bg)
|
||||
|
||||
# 开始粘贴服务
|
||||
hs = 0
|
||||
for cag in plugin_help:
|
||||
sv = plugin_help[cag]
|
||||
cag_bar = deepcopy(cag_bg)
|
||||
cag_desc = sv['desc']
|
||||
cag_data = sv['data']
|
||||
cag_draw = ImageDraw.Draw(cag_bar)
|
||||
|
||||
cag_draw.text(
|
||||
(136, 50),
|
||||
cag,
|
||||
main_color,
|
||||
font=core_font(45),
|
||||
anchor='lm',
|
||||
)
|
||||
bbox = core_font(45).getbbox(cag)
|
||||
cag_name_len = int(bbox[2] - bbox[0])
|
||||
|
||||
cag_draw.text(
|
||||
(136 + cag_name_len + 15, 55),
|
||||
cag_desc,
|
||||
sub_color,
|
||||
font=core_font(30),
|
||||
anchor='lm',
|
||||
)
|
||||
img.paste(cag_bar, (0, 280 + hs), cag_bar)
|
||||
|
||||
for i, command in enumerate(cag_data):
|
||||
command_name = command['name']
|
||||
# command_desc = command['desc']
|
||||
command_eg = command['eg']
|
||||
command_bg = deepcopy(item_bg)
|
||||
|
||||
icon = find_icon(command_name, icon_path)
|
||||
command_bg.paste(icon, (6, 12), icon)
|
||||
|
||||
command_draw = ImageDraw.Draw(command_bg)
|
||||
|
||||
command_draw.text(
|
||||
(160, 67),
|
||||
plugin_prefix + command_name,
|
||||
main_color,
|
||||
font=core_font(40),
|
||||
anchor='lm',
|
||||
)
|
||||
|
||||
command_draw.text(
|
||||
(160, 116),
|
||||
plugin_prefix + command_eg,
|
||||
sub_color,
|
||||
font=core_font(26),
|
||||
anchor='lm',
|
||||
)
|
||||
|
||||
x, y = 45 + (i % 3) * 490, 370 + (i // 3) * 175 + hs
|
||||
img.paste(command_bg, (x, y), command_bg)
|
||||
|
||||
hs += (((len(cag_data) - 1) // 3) + 1) * 175 + 100
|
||||
|
||||
img.paste(
|
||||
footer,
|
||||
((w - footer.width) // 2, h - footer.height - 20),
|
||||
footer,
|
||||
)
|
||||
|
||||
img = img.convert('RGB')
|
||||
img.save(
|
||||
help_path,
|
||||
'JPEG',
|
||||
quality=pic_quality,
|
||||
subsampling=0,
|
||||
)
|
||||
cache[plugin_name] = 1
|
||||
|
||||
return await convert_img(img)
|
BIN
gsuid_core/help/texture2d/banner_bg.jpg
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
gsuid_core/help/texture2d/bg.jpg
Normal file
After Width: | Height: | Size: 158 KiB |
BIN
gsuid_core/help/texture2d/cag_bg.png
Normal file
After Width: | Height: | Size: 888 B |
BIN
gsuid_core/help/texture2d/footer_dark.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
gsuid_core/help/texture2d/footer_light.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
gsuid_core/help/texture2d/item_dark.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
gsuid_core/help/texture2d/item_light.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 62 KiB |
@ -2,8 +2,6 @@ from gsuid_core.sv import SV
|
||||
from gsuid_core.bot import Bot
|
||||
from gsuid_core.models import Event
|
||||
from gsuid_core.logger import logger
|
||||
from gsuid_core.utils.image.convert import convert_img
|
||||
from gsuid_core.help.draw_help import CORE_HELP_IMG, get_help_img
|
||||
|
||||
sv_core_help_img = SV('Core帮助')
|
||||
|
||||
@ -11,10 +9,4 @@ sv_core_help_img = SV('Core帮助')
|
||||
@sv_core_help_img.on_fullmatch(('core帮助', 'Core帮助'))
|
||||
async def send_core_htlp_msg(bot: Bot, ev: Event):
|
||||
logger.info('[早柚核心] 开始执行[帮助图]')
|
||||
if CORE_HELP_IMG.exists():
|
||||
img = await convert_img(CORE_HELP_IMG)
|
||||
else:
|
||||
img = await get_help_img()
|
||||
img = await convert_img(img)
|
||||
logger.info('[早柚核心] 帮助图获取成功!')
|
||||
await bot.send(img)
|
||||
await bot.send('该功能已删除...')
|
||||
|
@ -11,5 +11,5 @@ AMBR_GCG_DETAIL = AMBR_BASE_URL + '/v2/chs/gcg/{}?vh=37F4'
|
||||
AMBR_MONSTER_LIST = AMBR_BASE_URL + '/v2/chs/monster?vh=37F4'
|
||||
AMBR_ICON_URL = AMBR_BASE_URL + '/assets/UI'
|
||||
AMBR_MONSTER_ICON_URL = f'{AMBR_ICON_URL}/monster/'
|
||||
AMBR_DAILY_URL = AMBR_BASE_URL + '/v2/chs/dailyDungeon?vh=37F4'
|
||||
AMBR_UPGRADE_URL = AMBR_BASE_URL + '/v2/chs/upgrade?vh=40F3'
|
||||
AMBR_DAILY_URL = AMBR_BASE_URL + '/api/v2/chs/dailyDungeon?vh=37F4'
|
||||
AMBR_UPGRADE_URL = AMBR_BASE_URL + '/api/v2/chs/upgrade?vh=40F3'
|
||||
|
BIN
gsuid_core/utils/fonts/MiSans-Bold.ttf
Normal file
@ -2,7 +2,7 @@ from pathlib import Path
|
||||
|
||||
from PIL import ImageFont
|
||||
|
||||
FONT_ORIGIN_PATH = Path(__file__).parent / 'yuanshen_origin.ttf'
|
||||
FONT_ORIGIN_PATH = Path(__file__).parent / 'MiSans-Bold.ttf'
|
||||
|
||||
|
||||
def core_font(size: int) -> ImageFont.FreeTypeFont:
|
||||
|
@ -6,6 +6,7 @@ from typing import Tuple, Union, Optional
|
||||
|
||||
import httpx
|
||||
from httpx import get
|
||||
from utils.fonts.fonts import core_font
|
||||
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
||||
|
||||
from gsuid_core.models import Event
|
||||
@ -20,6 +21,31 @@ def get_div():
|
||||
return Image.open(TEXT_PATH / 'div.png')
|
||||
|
||||
|
||||
def draw_color_badge(
|
||||
text: str,
|
||||
color: Union[Tuple[int, int, int], str] = (252, 69, 69),
|
||||
font: ImageFont.FreeTypeFont = core_font(30),
|
||||
font_color: Tuple[int, int, int] = (255, 255, 255),
|
||||
):
|
||||
x1, y1, x2, y2 = font.getbbox(text)
|
||||
offset_x = int((x2 - x1) * 0.3)
|
||||
offset_y = int((y2 - y1) * 0.5)
|
||||
x3, y3, x4, y4 = x1 - offset_x, y1 - offset_y, x2 + offset_x, y2 + offset_y
|
||||
w, h = int(x4 - x3), int(y4 - y3)
|
||||
center_x, center_y = int(w // 2), int(h // 2)
|
||||
img = Image.new('RGBA', (w, h), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(img)
|
||||
draw.rounded_rectangle((0, 0, w, h), fill=color, radius=20)
|
||||
draw.text(
|
||||
(center_x, center_y),
|
||||
text,
|
||||
font=font,
|
||||
fill=font_color,
|
||||
anchor='mm',
|
||||
)
|
||||
return img
|
||||
|
||||
|
||||
def get_status_icon(status: Union[int, bool]) -> Image.Image:
|
||||
if status:
|
||||
img = Image.open(TEXT_PATH / 'yes.png')
|
||||
@ -89,9 +115,9 @@ async def shift_image_hue(img: Image.Image, angle: float = 30) -> Image.Image:
|
||||
|
||||
for y in range(img.height):
|
||||
for x in range(img.width):
|
||||
h, s, v = pixels[x, y]
|
||||
h, s, v = pixels[x, y] # type: ignore
|
||||
h = (h + hue_shift) % 360
|
||||
pixels[x, y] = (h, s, v)
|
||||
pixels[x, y] = (h, s, v) # type: ignore
|
||||
|
||||
img = img.convert('RGBA')
|
||||
img.putalpha(alpha)
|
||||
@ -394,7 +420,16 @@ class CustomizeImage:
|
||||
img = img.convert("RGBA")
|
||||
img = img.resize((1, 1), resample=0)
|
||||
dominant_color = img.getpixel((0, 0))
|
||||
return dominant_color
|
||||
if isinstance(dominant_color, float):
|
||||
_dominant_color = tuple(
|
||||
[int(dominant_color * 255) for _ in range(3)]
|
||||
) # type: ignore
|
||||
elif dominant_color is None or isinstance(dominant_color, int):
|
||||
_dominant_color: Tuple[int, int, int] = (255, 255, 255)
|
||||
else:
|
||||
_dominant_color = dominant_color # type: ignore
|
||||
|
||||
return _dominant_color
|
||||
|
||||
@staticmethod
|
||||
def get_bg_color(
|
||||
|