mirror of
https://github.com/baiqwerdvd/StarRailUID.git
synced 2025-05-06 19:53:44 +08:00
🎨 适配新版GsCore
This commit is contained in:
parent
d298424796
commit
ba13c517d8
@ -20,12 +20,18 @@ class Equipment(TypedDict):
|
|||||||
|
|
||||||
|
|
||||||
class Relic(TypedDict):
|
class Relic(TypedDict):
|
||||||
subAffixList: List[subAffixList]
|
subAffixList: List[SubAffix]
|
||||||
tid: int
|
tid: int
|
||||||
mainAffixId: int
|
mainAffixId: int
|
||||||
type: int
|
type: int
|
||||||
|
|
||||||
|
|
||||||
|
class SubAffix(TypedDict):
|
||||||
|
affixID: int
|
||||||
|
cnt: int
|
||||||
|
step: int
|
||||||
|
|
||||||
|
|
||||||
class Avatar(TypedDict):
|
class Avatar(TypedDict):
|
||||||
skillTreeList: List[Behavior]
|
skillTreeList: List[Behavior]
|
||||||
rank: Optional[int]
|
rank: Optional[int]
|
||||||
|
@ -4,12 +4,15 @@ from typing import Union, Optional
|
|||||||
from PIL import Image, ImageDraw
|
from PIL import Image, ImageDraw
|
||||||
from gsuid_core.logger import logger
|
from gsuid_core.logger import logger
|
||||||
from gsuid_core.utils.error_reply import get_error
|
from gsuid_core.utils.error_reply import get_error
|
||||||
|
from gsuid_core.utils.image.image_tools import (
|
||||||
|
get_qq_avatar,
|
||||||
|
draw_pic_with_ring,
|
||||||
|
)
|
||||||
|
|
||||||
from .utils import get_icon
|
from .utils import get_icon
|
||||||
from ..utils.convert import GsCookie
|
from ..utils.convert import GsCookie
|
||||||
from ..utils.image.convert import convert_img
|
from ..utils.image.convert import convert_img
|
||||||
from ..sruid_utils.api.mys.models import AbyssAvatar
|
from ..sruid_utils.api.mys.models import AbyssAvatar
|
||||||
from ..utils.image.image_tools import get_qq_avatar, draw_pic_with_ring
|
|
||||||
from ..utils.fonts.starrail_fonts import (
|
from ..utils.fonts.starrail_fonts import (
|
||||||
sr_font_22,
|
sr_font_22,
|
||||||
sr_font_28,
|
sr_font_28,
|
||||||
@ -190,7 +193,7 @@ async def draw_abyss_img(
|
|||||||
char_pic = await get_qq_avatar(avatar_url=_id)
|
char_pic = await get_qq_avatar(avatar_url=_id)
|
||||||
else:
|
else:
|
||||||
char_pic = await get_qq_avatar(qid=qid)
|
char_pic = await get_qq_avatar(qid=qid)
|
||||||
char_pic = await draw_pic_with_ring(char_pic, 250)
|
char_pic = await draw_pic_with_ring(char_pic, 250, None, False)
|
||||||
|
|
||||||
img.paste(char_pic, (325, 132), char_pic)
|
img.paste(char_pic, (325, 132), char_pic)
|
||||||
|
|
||||||
|
@ -1,18 +1,34 @@
|
|||||||
|
import re
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
import re
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, Optional, Union
|
from typing import Dict, Union, Optional
|
||||||
|
|
||||||
|
from mpmath import mp, nstr
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
from gsuid_core.logger import logger
|
from gsuid_core.logger import logger
|
||||||
from gsuid_core.utils.image.convert import convert_img
|
from gsuid_core.utils.image.convert import convert_img
|
||||||
from gsuid_core.utils.image.image_tools import draw_text_by_line
|
from gsuid_core.utils.image.image_tools import draw_text_by_line
|
||||||
from mpmath import mp, nstr
|
|
||||||
from PIL import Image, ImageDraw
|
|
||||||
|
|
||||||
|
from .to_data import api_to_dict
|
||||||
|
from .mono.Character import Character
|
||||||
from ..utils.error_reply import CHAR_HINT
|
from ..utils.error_reply import CHAR_HINT
|
||||||
from ..utils.excel.read_excel import light_cone_ranks
|
|
||||||
from ..utils.fonts.first_world import fw_font_28
|
from ..utils.fonts.first_world import fw_font_28
|
||||||
|
from ..utils.excel.read_excel import light_cone_ranks
|
||||||
|
from ..utils.map.name_covert import name_to_avatar_id, alias_to_char_name
|
||||||
|
from ..utils.map.SR_MAP_PATH import (
|
||||||
|
RelicId2Rarity,
|
||||||
|
AvatarRelicScore,
|
||||||
|
avatarId2Name,
|
||||||
|
avatarId2DamageType,
|
||||||
|
)
|
||||||
|
from ..utils.resource.RESOURCE_PATH import (
|
||||||
|
RELIC_PATH,
|
||||||
|
SKILL_PATH,
|
||||||
|
PLAYER_PATH,
|
||||||
|
WEAPON_PATH,
|
||||||
|
CHAR_PORTRAIT_PATH,
|
||||||
|
)
|
||||||
from ..utils.fonts.starrail_fonts import (
|
from ..utils.fonts.starrail_fonts import (
|
||||||
sr_font_20,
|
sr_font_20,
|
||||||
sr_font_23,
|
sr_font_23,
|
||||||
@ -22,22 +38,6 @@ from ..utils.fonts.starrail_fonts import (
|
|||||||
sr_font_34,
|
sr_font_34,
|
||||||
sr_font_38,
|
sr_font_38,
|
||||||
)
|
)
|
||||||
from ..utils.map.name_covert import alias_to_char_name, name_to_avatar_id
|
|
||||||
from ..utils.map.SR_MAP_PATH import (
|
|
||||||
AvatarRelicScore,
|
|
||||||
RelicId2Rarity,
|
|
||||||
avatarId2DamageType,
|
|
||||||
avatarId2Name,
|
|
||||||
)
|
|
||||||
from ..utils.resource.RESOURCE_PATH import (
|
|
||||||
CHAR_PORTRAIT_PATH,
|
|
||||||
PLAYER_PATH,
|
|
||||||
RELIC_PATH,
|
|
||||||
SKILL_PATH,
|
|
||||||
WEAPON_PATH,
|
|
||||||
)
|
|
||||||
from .mono.Character import Character
|
|
||||||
from .to_data import api_to_dict
|
|
||||||
|
|
||||||
mp.dps = 14
|
mp.dps = 14
|
||||||
|
|
||||||
@ -103,7 +103,11 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
|
|||||||
char_img_draw.text(
|
char_img_draw.text(
|
||||||
(620, 207), char.char_name, (255, 255, 255), sr_font_38, 'lm'
|
(620, 207), char.char_name, (255, 255, 255), sr_font_38, 'lm'
|
||||||
)
|
)
|
||||||
char_name_len = sr_font_38.getsize(char.char_name)[0]
|
if hasattr(sr_font_38, 'getsize'):
|
||||||
|
char_name_len = sr_font_38.getsize(char.char_name)[0]
|
||||||
|
else:
|
||||||
|
bbox = sr_font_38.getbbox(char.char_name)
|
||||||
|
char_name_len = bbox[2] - bbox[0]
|
||||||
|
|
||||||
# 放等级
|
# 放等级
|
||||||
char_img_draw.text(
|
char_img_draw.text(
|
||||||
@ -346,9 +350,13 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
|
|||||||
sr_font_34,
|
sr_font_34,
|
||||||
'lm',
|
'lm',
|
||||||
)
|
)
|
||||||
weapon_name_len = sr_font_34.getsize(char.equipment["equipmentName"])[
|
if hasattr(sr_font_34, 'getsize'):
|
||||||
0
|
weapon_name_len = sr_font_34.getsize(
|
||||||
]
|
char.equipment["equipmentName"]
|
||||||
|
)[0]
|
||||||
|
else:
|
||||||
|
bbox = sr_font_34.getbbox(char.equipment["equipmentName"])
|
||||||
|
weapon_name_len = bbox[2] - bbox[0]
|
||||||
# 放阶
|
# 放阶
|
||||||
rank_img = Image.open(TEXT_PATH / 'ImgNewBg.png')
|
rank_img = Image.open(TEXT_PATH / 'ImgNewBg.png')
|
||||||
rank_img_draw = ImageDraw.Draw(rank_img)
|
rank_img_draw = ImageDraw.Draw(rank_img)
|
||||||
|
@ -6,6 +6,11 @@ from typing import List, Tuple, Union
|
|||||||
|
|
||||||
from PIL import Image, ImageDraw
|
from PIL import Image, ImageDraw
|
||||||
from gsuid_core.logger import logger
|
from gsuid_core.logger import logger
|
||||||
|
from gsuid_core.utils.image.image_tools import (
|
||||||
|
get_color_bg,
|
||||||
|
get_qq_avatar,
|
||||||
|
draw_pic_with_ring,
|
||||||
|
)
|
||||||
|
|
||||||
from ..utils.image.convert import convert_img
|
from ..utils.image.convert import convert_img
|
||||||
from ..utils.map.name_covert import name_to_avatar_id, name_to_weapon_id
|
from ..utils.map.name_covert import name_to_avatar_id, name_to_weapon_id
|
||||||
@ -14,11 +19,6 @@ from ..utils.resource.RESOURCE_PATH import (
|
|||||||
WEAPON_PATH,
|
WEAPON_PATH,
|
||||||
CHAR_ICON_PATH,
|
CHAR_ICON_PATH,
|
||||||
)
|
)
|
||||||
from ..utils.image.image_tools import (
|
|
||||||
get_color_bg,
|
|
||||||
get_qq_avatar,
|
|
||||||
draw_pic_with_ring,
|
|
||||||
)
|
|
||||||
from ..utils.fonts.starrail_fonts import (
|
from ..utils.fonts.starrail_fonts import (
|
||||||
sr_font_20,
|
sr_font_20,
|
||||||
sr_font_24,
|
sr_font_24,
|
||||||
@ -324,7 +324,7 @@ async def draw_gachalogs_img(uid: str, user_id: str) -> Union[bytes, str]:
|
|||||||
char_pic = await get_qq_avatar(avatar_url=_id)
|
char_pic = await get_qq_avatar(avatar_url=_id)
|
||||||
else:
|
else:
|
||||||
char_pic = await get_qq_avatar(qid=user_id)
|
char_pic = await get_qq_avatar(qid=user_id)
|
||||||
char_pic = await draw_pic_with_ring(char_pic, 206)
|
char_pic = await draw_pic_with_ring(char_pic, 206, None, False)
|
||||||
|
|
||||||
# 获取背景图片各项参数
|
# 获取背景图片各项参数
|
||||||
img = Abg3_img.copy()
|
img = Abg3_img.copy()
|
||||||
|
@ -5,11 +5,14 @@ from typing import List, Union, Optional
|
|||||||
from PIL import Image, ImageDraw
|
from PIL import Image, ImageDraw
|
||||||
from gsuid_core.logger import logger
|
from gsuid_core.logger import logger
|
||||||
from gsuid_core.utils.error_reply import get_error
|
from gsuid_core.utils.error_reply import get_error
|
||||||
|
from gsuid_core.utils.image.image_tools import (
|
||||||
|
get_qq_avatar,
|
||||||
|
draw_pic_with_ring,
|
||||||
|
)
|
||||||
|
|
||||||
from .utils import get_icon
|
from .utils import get_icon
|
||||||
from ..utils.convert import GsCookie
|
from ..utils.convert import GsCookie
|
||||||
from ..utils.image.convert import convert_img
|
from ..utils.image.convert import convert_img
|
||||||
from ..utils.image.image_tools import get_qq_avatar, draw_pic_with_ring
|
|
||||||
from ..sruid_utils.api.mys.models import (
|
from ..sruid_utils.api.mys.models import (
|
||||||
RogueAvatar,
|
RogueAvatar,
|
||||||
RogueMiracles,
|
RogueMiracles,
|
||||||
@ -283,7 +286,7 @@ async def draw_rogue_img(
|
|||||||
char_pic = await get_qq_avatar(avatar_url=_id)
|
char_pic = await get_qq_avatar(avatar_url=_id)
|
||||||
else:
|
else:
|
||||||
char_pic = await get_qq_avatar(qid=qid)
|
char_pic = await get_qq_avatar(qid=qid)
|
||||||
char_pic = await draw_pic_with_ring(char_pic, 250)
|
char_pic = await draw_pic_with_ring(char_pic, 250, None, False)
|
||||||
|
|
||||||
img.paste(char_pic, (325, 132), char_pic)
|
img.paste(char_pic, (325, 132), char_pic)
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import re
|
|||||||
from gsuid_core.sv import SV
|
from gsuid_core.sv import SV
|
||||||
from gsuid_core.bot import Bot
|
from gsuid_core.bot import Bot
|
||||||
from gsuid_core.models import Event
|
from gsuid_core.models import Event
|
||||||
|
from gsuid_core.logger import logger
|
||||||
|
|
||||||
from ..utils.convert import get_uid
|
from ..utils.convert import get_uid
|
||||||
from ..utils.sr_prefix import PREFIX
|
from ..utils.sr_prefix import PREFIX
|
||||||
@ -21,5 +22,6 @@ async def send_role_info(bot: Bot, ev: Event):
|
|||||||
if uid is None:
|
if uid is None:
|
||||||
return '你还没有绑定UID噢,请使用[sr绑定uid123]完成绑定!'
|
return '你还没有绑定UID噢,请使用[sr绑定uid123]完成绑定!'
|
||||||
|
|
||||||
|
logger.info(f'[sr查询信息]UID: {uid}')
|
||||||
await bot.logger.info('开始执行[sr查询信息]')
|
await bot.logger.info('开始执行[sr查询信息]')
|
||||||
await bot.send(await get_role_img(uid))
|
await bot.send(await get_role_img(uid))
|
||||||
|
@ -13,7 +13,7 @@ from ..sruid_utils.api.mys.models import AbyssData, RogueData
|
|||||||
|
|
||||||
@overload
|
@overload
|
||||||
async def get_uid(
|
async def get_uid(
|
||||||
bot: Bot, ev: Event, only_uid: bool = False
|
bot: Bot, ev: Event, get_user_id: bool = False, only_uid: bool = False
|
||||||
) -> Optional[str]:
|
) -> Optional[str]:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@ -1,22 +1,20 @@
|
|||||||
import math
|
|
||||||
import random
|
|
||||||
from io import BytesIO
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Tuple, Union, Optional
|
from typing import Union, Optional
|
||||||
|
|
||||||
from httpx import get
|
from PIL import Image
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from gsuid_core.utils.image.image_tools import TEXT_PATH, CustomizeImage
|
||||||
|
|
||||||
|
from ..resource.RESOURCE_PATH import CU_BG_PATH
|
||||||
from ...starrailuid_config.sr_config import srconfig
|
from ...starrailuid_config.sr_config import srconfig
|
||||||
from ..resource.RESOURCE_PATH import CU_BG_PATH, TEXT2D_PATH
|
|
||||||
|
|
||||||
BG_PATH = Path(__file__).parent / 'bg'
|
BG_PATH = Path(__file__).parent / 'bg'
|
||||||
TEXT_PATH = Path(__file__).parent / 'texture2d'
|
|
||||||
ring_pic = Image.open(TEXT_PATH / 'ring.png')
|
|
||||||
mask_pic = Image.open(TEXT_PATH / 'mask.png')
|
|
||||||
NM_BG_PATH = BG_PATH / 'nm_bg'
|
NM_BG_PATH = BG_PATH / 'nm_bg'
|
||||||
SP_BG_PATH = BG_PATH / 'sp_bg'
|
SP_BG_PATH = BG_PATH / 'sp_bg'
|
||||||
|
|
||||||
|
if list(CU_BG_PATH.iterdir()) != []:
|
||||||
|
bg_path = CU_BG_PATH
|
||||||
|
else:
|
||||||
|
bg_path = NM_BG_PATH
|
||||||
|
|
||||||
if list(CU_BG_PATH.iterdir()) != []:
|
if list(CU_BG_PATH.iterdir()) != []:
|
||||||
bg_path = CU_BG_PATH
|
bg_path = CU_BG_PATH
|
||||||
@ -24,60 +22,11 @@ else:
|
|||||||
bg_path = NM_BG_PATH
|
bg_path = NM_BG_PATH
|
||||||
|
|
||||||
|
|
||||||
def draw_text_by_line(
|
async def get_simple_bg(
|
||||||
img: Image.Image,
|
based_w: int, based_h: int, image: Union[str, None, Image.Image] = None
|
||||||
pos: Tuple[int, int],
|
|
||||||
text: str,
|
|
||||||
font: ImageFont.FreeTypeFont,
|
|
||||||
fill: Union[Tuple[int, int, int, int], str],
|
|
||||||
max_length: float,
|
|
||||||
center=False,
|
|
||||||
line_space: Optional[float] = None,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
在图片上写长段文字, 自动换行
|
|
||||||
max_length单行最大长度, 单位像素
|
|
||||||
line_space 行间距, 单位像素, 默认是字体高度的0.3倍
|
|
||||||
"""
|
|
||||||
x, y = pos
|
|
||||||
_, h = font.getsize('X')
|
|
||||||
if line_space is None:
|
|
||||||
y_add = math.ceil(1.3 * h)
|
|
||||||
else:
|
|
||||||
y_add = math.ceil(h + line_space)
|
|
||||||
draw = ImageDraw.Draw(img)
|
|
||||||
row = "" # 存储本行文字
|
|
||||||
length = 0 # 记录本行长度
|
|
||||||
for character in text:
|
|
||||||
w, h = font.getsize(character) # 获取当前字符的宽度
|
|
||||||
if length + w * 2 <= max_length:
|
|
||||||
row += character
|
|
||||||
length += w
|
|
||||||
else:
|
|
||||||
row += character
|
|
||||||
if center:
|
|
||||||
font_size = font.getsize(row)
|
|
||||||
x = math.ceil((img.size[0] - font_size[0]) / 2)
|
|
||||||
draw.text((x, y), row, font=font, fill=fill)
|
|
||||||
row = ""
|
|
||||||
length = 0
|
|
||||||
y += y_add
|
|
||||||
if row != "":
|
|
||||||
if center:
|
|
||||||
font_size = font.getsize(row)
|
|
||||||
x = math.ceil((img.size[0] - font_size[0]) / 2)
|
|
||||||
draw.text((x, y), row, font=font, fill=fill)
|
|
||||||
|
|
||||||
|
|
||||||
async def get_qq_avatar(
|
|
||||||
qid: Optional[Union[int, str]] = None, avatar_url: Optional[str] = None
|
|
||||||
) -> Image.Image:
|
) -> Image.Image:
|
||||||
if qid:
|
CIL = CustomizeImage(NM_BG_PATH)
|
||||||
avatar_url = f'http://q1.qlogo.cn/g?b=qq&nk={qid}&s=640'
|
return CIL.get_image(image, based_w, based_h)
|
||||||
elif avatar_url is None:
|
|
||||||
avatar_url = 'https://q1.qlogo.cn/g?b=qq&nk=3399214199&s=640'
|
|
||||||
char_pic = Image.open(BytesIO(get(avatar_url).content)).convert('RGBA')
|
|
||||||
return char_pic
|
|
||||||
|
|
||||||
|
|
||||||
async def get_color_bg(
|
async def get_color_bg(
|
||||||
@ -94,233 +43,13 @@ async def get_color_bg(
|
|||||||
image = Image.open(path2)
|
image = Image.open(path2)
|
||||||
elif path.exists():
|
elif path.exists():
|
||||||
image = Image.open(path)
|
image = Image.open(path)
|
||||||
CI_img = CustomizeImage(image, based_w, based_h)
|
CI_img = CustomizeImage(bg_path)
|
||||||
img = CI_img.bg_img
|
img = CI_img.get_image(image, based_w, based_h)
|
||||||
color = CI_img.bg_color
|
color = CI_img.get_bg_color(img)
|
||||||
if not without_mask:
|
if not without_mask:
|
||||||
color_mask = Image.new('RGBA', (based_w, based_h), color)
|
color_mask = Image.new('RGBA', (based_w, based_h), color)
|
||||||
enka_mask = Image.open(TEXT2D_PATH / 'mask.png').resize(
|
enka_mask = Image.open(TEXT_PATH / 'bg_mask.png').resize(
|
||||||
(based_w, based_h)
|
(based_w, based_h)
|
||||||
)
|
)
|
||||||
img.paste(color_mask, (0, 0), enka_mask)
|
img.paste(color_mask, (0, 0), enka_mask)
|
||||||
return img
|
return img
|
||||||
|
|
||||||
|
|
||||||
async def get_simple_bg(
|
|
||||||
based_w: int, based_h: int, image: Union[str, None, Image.Image] = None
|
|
||||||
) -> Image.Image:
|
|
||||||
if image:
|
|
||||||
if isinstance(image, str):
|
|
||||||
edit_bg = Image.open(BytesIO(get(image).content)).convert('RGBA')
|
|
||||||
elif isinstance(image, Image.Image):
|
|
||||||
edit_bg = image.convert('RGBA')
|
|
||||||
else:
|
|
||||||
bg_path = random.choice(list(NM_BG_PATH.iterdir()))
|
|
||||||
edit_bg = Image.open(bg_path).convert('RGBA')
|
|
||||||
|
|
||||||
# 确定图片的长宽
|
|
||||||
bg_img = crop_center_img(edit_bg, based_w, based_h)
|
|
||||||
return bg_img
|
|
||||||
|
|
||||||
|
|
||||||
def crop_center_img(
|
|
||||||
img: Image.Image, based_w: int, based_h: int
|
|
||||||
) -> Image.Image:
|
|
||||||
# 确定图片的长宽
|
|
||||||
based_scale = '%.3f' % (based_w / based_h)
|
|
||||||
w, h = img.size
|
|
||||||
scale_f = '%.3f' % (w / h)
|
|
||||||
new_w = math.ceil(based_h * float(scale_f))
|
|
||||||
new_h = math.ceil(based_w / float(scale_f))
|
|
||||||
if scale_f > based_scale:
|
|
||||||
resize_img = img.resize((new_w, based_h), Image.ANTIALIAS)
|
|
||||||
x1 = int(new_w / 2 - based_w / 2)
|
|
||||||
y1 = 0
|
|
||||||
x2 = int(new_w / 2 + based_w / 2)
|
|
||||||
y2 = based_h
|
|
||||||
else:
|
|
||||||
resize_img = img.resize((based_w, new_h), Image.ANTIALIAS)
|
|
||||||
x1 = 0
|
|
||||||
y1 = int(new_h / 2 - based_h / 2)
|
|
||||||
x2 = based_w
|
|
||||||
y2 = int(new_h / 2 + based_h / 2)
|
|
||||||
crop_img = resize_img.crop((x1, y1, x2, y2))
|
|
||||||
return crop_img
|
|
||||||
|
|
||||||
|
|
||||||
async def draw_pic_with_ring(
|
|
||||||
pic: Image.Image,
|
|
||||||
size: int,
|
|
||||||
bg_color: Optional[Tuple[int, int, int]] = None,
|
|
||||||
):
|
|
||||||
'''
|
|
||||||
:说明:
|
|
||||||
绘制一张带白色圆环的1:1比例图片。
|
|
||||||
|
|
||||||
:参数:
|
|
||||||
* pic: `Image.Image`: 要修改的图片。
|
|
||||||
* size: `int`: 最后传出图片的大小(1:1)。
|
|
||||||
* bg_color: `Optional[Tuple[int, int, int]]`: 是否指定圆环内背景颜色。
|
|
||||||
|
|
||||||
:返回:
|
|
||||||
* img: `Image.Image`: 图片对象
|
|
||||||
'''
|
|
||||||
img = Image.new('RGBA', (size, size))
|
|
||||||
mask = mask_pic.resize((size, size))
|
|
||||||
# ring = ring_pic.resize((size, size))
|
|
||||||
resize_pic = crop_center_img(pic, size, size)
|
|
||||||
if bg_color:
|
|
||||||
img_color = Image.new('RGBA', (size, size), bg_color)
|
|
||||||
img_color.paste(resize_pic, (0, 0), resize_pic)
|
|
||||||
img.paste(img_color, (0, 0), mask)
|
|
||||||
else:
|
|
||||||
img.paste(resize_pic, (0, 0), mask)
|
|
||||||
# img.paste(ring, (0, 0), ring)
|
|
||||||
return img
|
|
||||||
|
|
||||||
|
|
||||||
class CustomizeImage:
|
|
||||||
def __init__(
|
|
||||||
self, image: Union[str, Image.Image], based_w: int, based_h: int
|
|
||||||
) -> None:
|
|
||||||
self.bg_img = self.get_image(image, based_w, based_h)
|
|
||||||
self.bg_color = self.get_bg_color(self.bg_img, is_light=True)
|
|
||||||
self.text_color = self.get_text_color(self.bg_color)
|
|
||||||
self.highlight_color = self.get_highlight_color(self.bg_color)
|
|
||||||
self.char_color = self.get_char_color(self.bg_color)
|
|
||||||
self.bg_detail_color = self.get_bg_detail_color(self.bg_color)
|
|
||||||
self.char_high_color = self.get_char_high_color(self.bg_color)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_image(
|
|
||||||
image: Union[str, Image.Image], based_w: int, based_h: int
|
|
||||||
) -> Image.Image:
|
|
||||||
# 获取背景图片
|
|
||||||
if isinstance(image, Image.Image):
|
|
||||||
edit_bg = image
|
|
||||||
elif image:
|
|
||||||
edit_bg = Image.open(BytesIO(get(image).content)).convert('RGBA')
|
|
||||||
else:
|
|
||||||
path = random.choice(list(bg_path.iterdir()))
|
|
||||||
edit_bg = Image.open(path).convert('RGBA')
|
|
||||||
|
|
||||||
# 确定图片的长宽
|
|
||||||
bg_img = crop_center_img(edit_bg, based_w, based_h)
|
|
||||||
return bg_img
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_dominant_color(pil_img: Image.Image) -> Tuple[int, int, int]:
|
|
||||||
img = pil_img.copy()
|
|
||||||
img = img.convert("RGBA")
|
|
||||||
img = img.resize((1, 1), resample=0)
|
|
||||||
dominant_color = img.getpixel((0, 0))
|
|
||||||
return dominant_color
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_bg_color(
|
|
||||||
edit_bg: Image.Image, is_light: Optional[bool] = False
|
|
||||||
) -> Tuple[int, int, int]:
|
|
||||||
# 获取背景主色
|
|
||||||
color = 8
|
|
||||||
q = edit_bg.quantize(colors=color, method=2)
|
|
||||||
bg_color = (0, 0, 0)
|
|
||||||
if is_light:
|
|
||||||
based_light = 195
|
|
||||||
else:
|
|
||||||
based_light = 120
|
|
||||||
temp = 9999
|
|
||||||
for i in range(color):
|
|
||||||
bg = tuple(
|
|
||||||
q.getpalette()[ # type:ignore
|
|
||||||
i * 3 : (i * 3) + 3 # noqa:E203
|
|
||||||
]
|
|
||||||
)
|
|
||||||
light_value = bg[0] * 0.3 + bg[1] * 0.6 + bg[2] * 0.1
|
|
||||||
if abs(light_value - based_light) < temp: # noqa:E203
|
|
||||||
bg_color = bg
|
|
||||||
temp = abs(light_value - based_light)
|
|
||||||
return bg_color
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_text_color(bg_color: Tuple[int, int, int]) -> Tuple[int, int, int]:
|
|
||||||
# 通过背景主色(bg_color)确定文字主色
|
|
||||||
r = 125
|
|
||||||
if max(*bg_color) > 255 - r:
|
|
||||||
r *= -1
|
|
||||||
text_color = (
|
|
||||||
math.floor(bg_color[0] + r if bg_color[0] + r <= 255 else 255),
|
|
||||||
math.floor(bg_color[1] + r if bg_color[1] + r <= 255 else 255),
|
|
||||||
math.floor(bg_color[2] + r if bg_color[2] + r <= 255 else 255),
|
|
||||||
)
|
|
||||||
return text_color
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_char_color(bg_color: Tuple[int, int, int]) -> Tuple[int, int, int]:
|
|
||||||
r = 140
|
|
||||||
if max(*bg_color) > 255 - r:
|
|
||||||
r *= -1
|
|
||||||
char_color = (
|
|
||||||
math.floor(bg_color[0] + 5 if bg_color[0] + r <= 255 else 255),
|
|
||||||
math.floor(bg_color[1] + 5 if bg_color[1] + r <= 255 else 255),
|
|
||||||
math.floor(bg_color[2] + 5 if bg_color[2] + r <= 255 else 255),
|
|
||||||
)
|
|
||||||
return char_color
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_char_high_color(
|
|
||||||
bg_color: Tuple[int, int, int]
|
|
||||||
) -> Tuple[int, int, int]:
|
|
||||||
r = 140
|
|
||||||
d = 20
|
|
||||||
if max(*bg_color) > 255 - r:
|
|
||||||
r *= -1
|
|
||||||
char_color = (
|
|
||||||
math.floor(bg_color[0] + d if bg_color[0] + r <= 255 else 255),
|
|
||||||
math.floor(bg_color[1] + d if bg_color[1] + r <= 255 else 255),
|
|
||||||
math.floor(bg_color[2] + d if bg_color[2] + r <= 255 else 255),
|
|
||||||
)
|
|
||||||
return char_color
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_bg_detail_color(
|
|
||||||
bg_color: Tuple[int, int, int]
|
|
||||||
) -> Tuple[int, int, int]:
|
|
||||||
r = 140
|
|
||||||
if max(*bg_color) > 255 - r:
|
|
||||||
r *= -1
|
|
||||||
bg_detail_color = (
|
|
||||||
math.floor(bg_color[0] - 20 if bg_color[0] + r <= 255 else 255),
|
|
||||||
math.floor(bg_color[1] - 20 if bg_color[1] + r <= 255 else 255),
|
|
||||||
math.floor(bg_color[2] - 20 if bg_color[2] + r <= 255 else 255),
|
|
||||||
)
|
|
||||||
return bg_detail_color
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_highlight_color(
|
|
||||||
color: Tuple[int, int, int]
|
|
||||||
) -> Tuple[int, int, int]:
|
|
||||||
red_color = color[0]
|
|
||||||
green_color = color[1]
|
|
||||||
blue_color = color[2]
|
|
||||||
|
|
||||||
highlight_color = {
|
|
||||||
'red': red_color - 127 if red_color > 127 else 127,
|
|
||||||
'green': green_color - 127 if green_color > 127 else 127,
|
|
||||||
'blue': blue_color - 127 if blue_color > 127 else 127,
|
|
||||||
}
|
|
||||||
|
|
||||||
max_color = max(highlight_color.values())
|
|
||||||
|
|
||||||
name = ''
|
|
||||||
for _highlight_color in highlight_color:
|
|
||||||
if highlight_color[_highlight_color] == max_color:
|
|
||||||
name = str(_highlight_color)
|
|
||||||
|
|
||||||
if name == 'red':
|
|
||||||
return red_color, highlight_color['green'], highlight_color['blue']
|
|
||||||
elif name == 'green':
|
|
||||||
return highlight_color['red'], green_color, highlight_color['blue']
|
|
||||||
elif name == 'blue':
|
|
||||||
return highlight_color['red'], highlight_color['green'], blue_color
|
|
||||||
else:
|
|
||||||
return 0, 0, 0 # Error
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.8 KiB |
@ -45,7 +45,7 @@
|
|||||||
"天才俱乐部第83席",
|
"天才俱乐部第83席",
|
||||||
"天才俱乐部第八十三席",
|
"天才俱乐部第八十三席",
|
||||||
"黑塔女士",
|
"黑塔女士",
|
||||||
"转圈圈"
|
"转圈圈"
|
||||||
],
|
],
|
||||||
"1003": [
|
"1003": [
|
||||||
"姬子",
|
"姬子",
|
||||||
@ -128,7 +128,7 @@
|
|||||||
"骚狐狸"
|
"骚狐狸"
|
||||||
],
|
],
|
||||||
"8002": [
|
"8002": [
|
||||||
"开拓者",
|
"开拓者",
|
||||||
"开拓者物理",
|
"开拓者物理",
|
||||||
"爷",
|
"爷",
|
||||||
"星爷",
|
"星爷",
|
||||||
@ -143,7 +143,7 @@
|
|||||||
"毁灭主"
|
"毁灭主"
|
||||||
],
|
],
|
||||||
"8004": [
|
"8004": [
|
||||||
"开拓者",
|
"开拓者",
|
||||||
"开拓者火",
|
"开拓者火",
|
||||||
"火主",
|
"火主",
|
||||||
"存护主"
|
"存护主"
|
||||||
|
@ -76,7 +76,10 @@ class MysApi(_MysApi):
|
|||||||
is_os = self.check_os(uid)
|
is_os = self.check_os(uid)
|
||||||
if is_os:
|
if is_os:
|
||||||
HEADER = copy.deepcopy(self._HEADER_OS)
|
HEADER = copy.deepcopy(self._HEADER_OS)
|
||||||
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
|
ck = await self.get_ck(uid, 'OWNER')
|
||||||
|
if ck is None:
|
||||||
|
return -51
|
||||||
|
HEADER['Cookie'] = ck
|
||||||
HEADER['DS'] = generate_os_ds()
|
HEADER['DS'] = generate_os_ds()
|
||||||
header = HEADER
|
header = HEADER
|
||||||
data = await self.simple_mys_req(
|
data = await self.simple_mys_req(
|
||||||
@ -105,10 +108,14 @@ class MysApi(_MysApi):
|
|||||||
return -51
|
return -51
|
||||||
header['Cookie'] = sk
|
header['Cookie'] = sk
|
||||||
header['x-rpc-channel'] = 'beta'
|
header['x-rpc-channel'] = 'beta'
|
||||||
header['x-rpc-device_id'] = await self.get_user_device_id(uid)
|
device_id = await self.get_user_device_id(uid)
|
||||||
|
header['x-rpc-device_id'] = (
|
||||||
|
'233333' if device_id is None else device_id
|
||||||
|
)
|
||||||
header['x-rpc-app_version'] = '2.53.0'
|
header['x-rpc-app_version'] = '2.53.0'
|
||||||
header['x-rpc-device_model'] = 'Mi 10'
|
header['x-rpc-device_model'] = 'Mi 10'
|
||||||
header['x-rpc-device_fp'] = await self.get_user_fp(uid)
|
fp = await self.get_user_fp(uid)
|
||||||
|
header['x-rpc-device_fp'] = 'Asmr489' if fp is None else fp
|
||||||
header['x-rpc-client_type'] = '2'
|
header['x-rpc-client_type'] = '2'
|
||||||
header['DS'] = get_ds_token2()
|
header['DS'] = get_ds_token2()
|
||||||
header['Referer'] = 'https://app.mihoyo.com'
|
header['Referer'] = 'https://app.mihoyo.com'
|
||||||
@ -126,7 +133,10 @@ class MysApi(_MysApi):
|
|||||||
is_os = self.check_os(uid)
|
is_os = self.check_os(uid)
|
||||||
if is_os:
|
if is_os:
|
||||||
HEADER = copy.deepcopy(self._HEADER_OS)
|
HEADER = copy.deepcopy(self._HEADER_OS)
|
||||||
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
|
ck = await self.get_ck(uid, 'OWNER')
|
||||||
|
if ck is None:
|
||||||
|
return -51
|
||||||
|
HEADER['Cookie'] = ck
|
||||||
HEADER['DS'] = generate_os_ds()
|
HEADER['DS'] = generate_os_ds()
|
||||||
header = HEADER
|
header = HEADER
|
||||||
data = await self.simple_mys_req(
|
data = await self.simple_mys_req(
|
||||||
@ -159,7 +169,10 @@ class MysApi(_MysApi):
|
|||||||
server_id = RECOGNIZE_SERVER.get(str(uid)[0])
|
server_id = RECOGNIZE_SERVER.get(str(uid)[0])
|
||||||
if self.check_os(uid):
|
if self.check_os(uid):
|
||||||
HEADER = copy.deepcopy(self._HEADER_OS)
|
HEADER = copy.deepcopy(self._HEADER_OS)
|
||||||
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
|
ck = await self.get_ck(uid, 'OWNER')
|
||||||
|
if ck is None:
|
||||||
|
return -51
|
||||||
|
HEADER['Cookie'] = ck
|
||||||
HEADER['DS'] = generate_os_ds()
|
HEADER['DS'] = generate_os_ds()
|
||||||
header = HEADER
|
header = HEADER
|
||||||
url = self.MAPI['STAR_RAIL_GACHA_LOG_URL_OS']
|
url = self.MAPI['STAR_RAIL_GACHA_LOG_URL_OS']
|
||||||
@ -200,7 +213,10 @@ class MysApi(_MysApi):
|
|||||||
is_os = self.check_os(uid)
|
is_os = self.check_os(uid)
|
||||||
if is_os:
|
if is_os:
|
||||||
HEADER = copy.deepcopy(self._HEADER_OS)
|
HEADER = copy.deepcopy(self._HEADER_OS)
|
||||||
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
|
ck = await self.get_ck(uid, 'OWNER')
|
||||||
|
if ck is None:
|
||||||
|
return -51
|
||||||
|
HEADER['Cookie'] = ck
|
||||||
HEADER['DS'] = generate_os_ds()
|
HEADER['DS'] = generate_os_ds()
|
||||||
header = HEADER
|
header = HEADER
|
||||||
data = await self.simple_mys_req(
|
data = await self.simple_mys_req(
|
||||||
@ -259,7 +275,10 @@ class MysApi(_MysApi):
|
|||||||
'lang': 'zh-cn',
|
'lang': 'zh-cn',
|
||||||
}
|
}
|
||||||
HEADER = copy.deepcopy(self._HEADER_OS)
|
HEADER = copy.deepcopy(self._HEADER_OS)
|
||||||
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
|
ck = await self.get_ck(uid, 'OWNER')
|
||||||
|
if ck is None:
|
||||||
|
return -51
|
||||||
|
HEADER['Cookie'] = ck
|
||||||
HEADER['DS'] = generate_os_ds()
|
HEADER['DS'] = generate_os_ds()
|
||||||
header = HEADER
|
header = HEADER
|
||||||
else:
|
else:
|
||||||
@ -287,7 +306,10 @@ class MysApi(_MysApi):
|
|||||||
is_os = self.check_os(uid)
|
is_os = self.check_os(uid)
|
||||||
if is_os:
|
if is_os:
|
||||||
HEADER = copy.deepcopy(self._HEADER_OS)
|
HEADER = copy.deepcopy(self._HEADER_OS)
|
||||||
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
|
ck = await self.get_ck(uid, 'OWNER')
|
||||||
|
if ck is None:
|
||||||
|
return -51
|
||||||
|
HEADER['Cookie'] = ck
|
||||||
HEADER['DS'] = generate_os_ds()
|
HEADER['DS'] = generate_os_ds()
|
||||||
header = HEADER
|
header = HEADER
|
||||||
data = await self.simple_mys_req(
|
data = await self.simple_mys_req(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user