GenshinUID/enkaToData/drawCharCard.py
2022-06-19 21:02:52 +08:00

552 lines
24 KiB
Python

import math
import json
from io import BytesIO
from pathlib import Path
from base64 import b64encode
from PIL import Image, ImageDraw, ImageFont
from httpx import get
from nonebot import logger
R_PATH = Path(__file__).parents[0]
TEXT_PATH = R_PATH / 'texture2D'
ICON_PATH = R_PATH / 'icon'
GACHA_PATH = R_PATH / 'gachaImg'
PLAYER_PATH = R_PATH / 'player'
RELIC_PATH = R_PATH / 'relicIcon'
MAP_PATH = R_PATH / 'map'
ETC_PATH = R_PATH / 'etc'
COLOR_MAP = {'Anemo' : (3, 90, 77), 'Cryo': (5, 85, 151), 'Dendro': (4, 87, 3),
'Electro': (47, 1, 85), 'Geo': (85, 34, 1), 'Hydro': (4, 6, 114), 'Pyro': (88, 4, 4)}
SCORE_VALUE_MAP = {'暴击率': 2, '暴击伤害': 1, '元素精通': 0.25, '元素充能效率': 0.65, '百分比血量': 0.86,
'百分比攻击力': 1, '百分比防御力': 0.7, '血量': 0.014, '攻击力': 0.12, '防御力': 0.18}
# 引入dmgMap
with open(ETC_PATH / 'dmgMap.json', 'r', encoding='UTF-8') as f:
dmgMap = json.load(f)
# 引入offset
with open(ETC_PATH / 'avatarOffsetMap.json', 'r', encoding='UTF-8') as f:
avatarOffsetMap = json.load(f)
def genshin_font_origin(size: int) -> ImageFont:
return ImageFont.truetype(str(TEXT_PATH / 'yuanshen_origin.ttf'), size=size)
def get_star_png(star: int) -> Image:
png = Image.open(TEXT_PATH / 's-{}.png'.format(str(star)))
return png
def strLenth(r: str, size: int, limit: int = 540) -> str:
result = ''
temp = 0
for i in r:
if temp >= limit:
result += '\n' + i
temp = 0
else:
result += i
if i.isdigit():
temp += round(size / 10 * 6)
elif i == '/':
temp += round(size / 10 * 2.2)
elif i == '.':
temp += round(size / 10 * 3)
elif i == '%':
temp += round(size / 10 * 9.4)
else:
temp += size
return result
async def get_artifacts_score(subName: str, subValue: int) -> int:
score = subValue * SCORE_VALUE_MAP[subName]
return score
async def get_first_main(mainName: str) -> str:
if '伤害加成' in mainName:
equipMain = mainName[0]
elif '元素' in mainName:
equipMain = mainName[2]
elif '百分比' in mainName:
if '血量' in mainName:
equipMain = ''
else:
equipMain = mainName[3]
else:
equipMain = mainName[0]
return equipMain
async def get_char_percent(raw_data: dict) -> str:
char_name = raw_data['avatarName']
weaponName = raw_data['weaponInfo']['weaponName']
weaponType = raw_data['weaponInfo']['weaponType']
fight_prop = raw_data['avatarFightProp']
hp = fight_prop['hp']
attack = fight_prop['atk']
defense = fight_prop['def']
em = fight_prop['elementalMastery']
critrate = fight_prop['critRate']
critdmg = fight_prop['critDmg']
ce = fight_prop['energyRecharge']
dmgBonus = fight_prop['dmgBonus'] if fight_prop['physicalDmgBonus'] <= fight_prop['dmgBonus'] else fight_prop['physicalDmgBonus']
healBouns = fight_prop['healBonus']
hp_green = fight_prop['addHp']
attack_green = fight_prop['addAtk']
defense_green = fight_prop['addDef']
equipMain = ''
for aritifact in raw_data['equipList']:
mainName = aritifact['reliquaryMainstat']['statName']
artifactsPos = aritifact['aritifactPieceName']
if artifactsPos == '时之沙':
equipMain += await get_first_main(mainName)
elif artifactsPos == '空之杯':
equipMain += await get_first_main(mainName)
elif artifactsPos == '理之冠':
equipMain += await get_first_main(mainName)
if 'equipSets' in raw_data:
equipSets = raw_data['equipSets']
else:
artifact_set_list = []
for i in raw_data['equipList']:
artifact_set_list.append(i['aritifactSetsName'])
equipSetList = set(artifact_set_list)
equipSets = {'type':'','set':''}
for equip in equipSetList:
if artifact_set_list.count(equip) >= 4:
equipSets['type'] = '4'
equipSets['set'] = equip
break
elif artifact_set_list.count(equip) == 1:
pass
elif artifact_set_list.count(equip) >= 2:
equipSets['type'] += '2'
equipSets['set'] += equip
if equipSets['type'] in ['2','']:
seq = ''
else:
seq = '{}|{}|{}'.format(weaponName.replace('','').replace('',''),equipSets['set'],equipMain)
if char_name in dmgMap:
for action in dmgMap[char_name]:
if action['seq'] == seq:
cal = action
break
else:
if '钟离' in char_name:
cal = dmgMap[char_name][-1]
else:
cal = dmgMap[char_name][0]
print(seq)
print(cal)
if cal['action'] == 'E刹那之花':
effect_prop = defense
elif cal['key'] == '攻击力':
effect_prop = attack
elif cal['key'] == '防御力':
effect_prop = defense
elif cal['key'] == '血量':
effect_prop = hp
else:
effect_prop = attack
dmgBonus_value_cal = 0
dmgBonus_cal = dmgBonus
if '夜兰' in char_name:
effect_prop = hp
elif '胡桃' in char_name:
effect_prop += 0.4 * hp if 0.4 * hp <= fight_prop['baseAtk'] * 4 else fight_prop['baseAtk'] * 4
elif '一斗' in char_name:
effect_prop += 0.9792 * defense
dmgBonus_value_cal += 0.35 * defense
elif '诺艾尔' in char_name:
effect_prop = attack
effect_prop += 1.3 * defense
if '踩班' in cal['action']:
effect_prop += 1202
effect_prop += fight_prop['baseAtk'] * 0.25
if '蒸发' in cal['action'] or '融化' in cal['action']:
if '蒸发' in cal['action']:
if raw_data['avatarElement'] == 'Pyro':
k = 1.5
else:
k = 2
elif '融化' in cal['action']:
if raw_data['avatarElement'] == 'Pyro':
k = 2
else:
k = 1.5
if equipSets['type'] in ['2','']:
a = 0
else:
if '魔女' in equipSets['set']:
a = 0.15
else:
a = 0
add_dmg = k*(1+(2.78*em)/(em+1400)+a)
else:
add_dmg = 1
if equipSets['type'] in ['2','','22']:
pass
else:
if '追忆' in equipSets['set']:
dmgBonus_cal += 0.5
elif '绝缘' in equipSets['set']:
Bouns = ce * 0.25 if ce * 0.25 <= 0.75 else 0.75
dmgBonus_cal += Bouns
elif '乐团' in equipSets['set']:
if weaponType in ['法器', '']:
dmgBonus_cal += 0.35
elif '华馆' in equipSets['set']:
if raw_data['avatarElement'] == 'Geo':
effect_prop += 0.24 * defense
dmgBonus_cal += 0.24
critdmg_cal = critdmg
healBouns_cal = healBouns
if '' in char_name:
dmgBonus_cal += 0.906
elif '绫华' in char_name:
dmgBonus_cal += 0.18
elif '宵宫' in char_name:
dmgBonus_cal += 0.5
elif '九条' in char_name:
effect_prop += 0.9129 * fight_prop['baseAtk']
critdmg_cal += 0.6
if '雾切' in weaponName:
dmgBonus_cal += 0.28
elif '弓藏' in weaponName and ('' in cal['action'] or '' in cal['action'] or '两段' in cal['action']):
dmgBonus_cal += 0.8
elif '飞雷' in weaponName and ('' in cal['action'] or '' in cal['action'] or '两段' in cal['action']):
dmgBonus_cal += 0.4
elif '阿莫斯' in weaponName:
dmgBonus_cal += 0.52
elif '破魔' in weaponName:
dmgBonus_cal += 0.18*2
elif '赤角石溃杵' in weaponName and ('' in cal['action'] or '' in cal['action'] or '两段' in cal['action']):
dmgBonus_value_cal += 0.4 * defense
elif '螭骨剑' in weaponName:
dmgBonus_cal += 0.4
elif '试作澹月' in weaponName:
effect_prop += fight_prop['baseAtk'] * 0.72
elif '冬极' in weaponName:
effect_prop += fight_prop['baseAtk'] * 0.48
dmgBonus_cal += 0.12
if '治疗' in cal['action']:
if equipSets['type'] in ['2','']:
healBouns_cal += 0
else:
if '少女' in equipSets['set']:
healBouns_cal += 0.2
if cal['action'] == '扩散':
dmg = 868 * 1.15 * (1+0.6+(16*em)/(em+2000))
elif '霄宫' in char_name:
dmg = effect_prop * cal['power'] * (1 + critdmg_cal) * (1 + dmgBonus_cal) * 0.5 * 0.9 * add_dmg * 1.5879
elif '班尼特' in char_name and 'Q治疗' in cal['action']:
power = cal['power'].split('+')
dmg = (effect_prop * float(power[0]) / 100 + float(power[1])) * (1 + healBouns_cal)
elif '心海' in char_name and cal['action'] == '开Q普攻':
dmg = (attack * cal['power'] + hp*(0.0971 + 0.15 * healBouns_cal)) * (1 + dmgBonus_cal) * 0.5 * 0.9 * add_dmg
elif '心海' in char_name and cal['action'] == '水母回血':
dmg = (862 + 0.0748 * hp) * (1 + healBouns_cal)
elif char_name in ['芭芭拉', '早柚', '', '七七']:
power = cal['power'].split('+')
dmg = (effect_prop * float(power[0]) / 100 + float(power[1])) * (1 + healBouns_cal)
elif '绫人' in char_name:
dmg = (effect_prop * cal['power'] + 0.0222 * hp) * (1 + critdmg_cal) * (1 + dmgBonus_cal) * 0.5 * 0.9 * add_dmg * 1.5879
elif char_name in ['荒泷一斗', '诺艾尔']:
dmg = (effect_prop * cal['power'] + dmgBonus_value_cal) * (1 + critdmg_cal) * (1 + dmgBonus_cal) * 0.5 * 0.9
elif '迪奥娜' in char_name:
dmg = (effect_prop * cal['power'] + 1905) * 1.9
elif '钟离' in char_name and 'E实际盾值' in cal['action']:
dmg = (2506 + hp * cal['power']) * 1.5 * 1.3
elif cal['action'] == 'Q开盾天星':
effect_prop = attack
dmg = (effect_prop * cal['power'] + 0.33 * hp) * (1 + critdmg_cal) * (1 + dmgBonus_cal) * 0.5 * 0.9 * add_dmg
elif '凝光' in char_name:
dmg = effect_prop * cal['power'] * (1 + critdmg_cal * critrate) * (1 + dmgBonus_cal) * 0.5 * 0.9 * add_dmg
elif isinstance(cal['power'], str):
if cal['power'] == '攻击力':
dmg = attack
elif cal['power'] == '防御力':
dmg = defense
else:
power = cal['power'].split('+')
dmg = effect_prop * float(power[0]) / 100 + float(power[1])
elif cal['val'] != 'any':
dmg = effect_prop * cal['power'] * (1 + critdmg_cal) * (1 + dmgBonus_cal) * 0.5 * 0.9 * add_dmg
else:
dmg = attack
print(dmg)
if cal['val'] != 'any':
percent = '{:.2f}'.format(dmg / cal['val'] * 100)
elif cal['power'] == '攻击力':
percent = '{:.2f}'.format(dmg / cal['atk'] * 100)
elif '云堇' in char_name:
percent = '{:.2f}'.format(dmg / cal['other2'] * 100)
elif cal['power'] == '防御力':
percent = '{:.2f}'.format(dmg / cal['other'] * 100)
else:
percent = 0.00
return percent
async def draw_char_card(raw_data: dict, charUrl: str = None) -> bytes:
img = Image.open(TEXT_PATH / '{}.png'.format(raw_data['avatarElement']))
char_info_1 = Image.open(TEXT_PATH / 'char_info_1.png')
char_info_mask = Image.open(TEXT_PATH / 'char_info_mask.png')
char_name = raw_data['avatarName']
char_level = raw_data['avatarLevel']
char_fetter = raw_data['avatarFetter']
#based_w, based_h = 320, 1024
based_w, based_h = 600, 1200
if charUrl:
offset_x, offset_y = 200, 0
char_img = Image.open(BytesIO(get(charUrl).content)).convert('RGBA')
else:
if char_name in avatarOffsetMap:
offset_x, offset_y = avatarOffsetMap[char_name][0], avatarOffsetMap[char_name][1]
else:
offset_x, offset_y = 200, 0
char_img = Image.open(GACHA_PATH / 'UI_Gacha_AvatarImg_{}.png'.format(raw_data['avatarEnName'])) #角色图像
# 确定图片的长宽
w, h = char_img.size
if (w, h) != (based_w, based_h):
#offset_all = offset_x if offset_x >= offset_y else offset_y
based_new_w, based_new_h = based_w + offset_x, based_h + offset_y
based_scale = '%.3f' % (based_new_w / based_new_h)
scale_f = '%.3f' % (w / h)
new_w = math.ceil(based_new_h * float(scale_f))
new_h = math.ceil(based_new_w / float(scale_f))
if scale_f > based_scale:
bg_img2 = char_img.resize((new_w, based_new_h), Image.Resampling.LANCZOS)
x1 = new_w/2 - based_new_w /2 + offset_x
y1 = 0 + offset_y / 2
x2 = new_w/2 + based_new_w /2
y2 = based_new_h - offset_y / 2
else:
bg_img2 = char_img.resize((based_new_w , new_h), Image.Resampling.LANCZOS)
x1 = 0 + offset_x
y1 = new_h/2 - based_new_h/2 + offset_y / 2
x2 = based_new_w
y2 = new_h/2 + based_new_h/2 - offset_y / 2
char_img = bg_img2.crop((x1, y1, x2, y2))
img_temp = Image.new('RGBA', (based_w, based_h), (0,0,0,0))
img_temp.paste(char_img,(0,0),char_info_mask)
img.paste(img_temp, (0, 0), img_temp)
img.paste(char_info_1, (0, 0), char_info_1)
lock_img = Image.open(TEXT_PATH / 'icon_lock.png')
# 命座处理
for talent_num in range(0, 6):
if talent_num + 1 <= len(raw_data['talentList']):
talent = raw_data['talentList'][talent_num]
# img.paste(color_holo_img, (13,270 + talent_num * 66), holo_img)
talent_img = Image.open(ICON_PATH / '{}.png'.format(talent['talentIcon']))
talent_img_new = talent_img.resize((50, 50), Image.Resampling.LANCZOS).convert("RGBA")
img.paste(talent_img_new, (850, 375 + talent_num * 81), talent_img_new)
else:
img.paste(lock_img, (850, 375 + talent_num * 81), lock_img)
# 天赋处理
skillList = raw_data['avatarSkill']
a_skill_name = skillList[0]['skillName'].replace('普通攻击·', '')
a_skill_level = skillList[0]['skillLevel']
e_skill_name = skillList[1]['skillName']
e_skill_level = skillList[1]['skillLevel']
q_skill_name = skillList[-1]['skillName']
q_skill_level = skillList[-1]['skillLevel']
for skill_num, skill in enumerate(skillList[0:2] + [skillList[-1]]):
skill_img = Image.open(ICON_PATH / '{}.png'.format(skill['skillIcon']))
skill_img_new = skill_img.resize((50, 50), Image.Resampling.LANCZOS).convert("RGBA")
img.paste(skill_img_new, (78, 756 + 101 * skill_num), skill_img_new)
# 武器部分
weapon_img = Image.open(TEXT_PATH / 'char_info_weapon.png')
weapon_star_img = get_star_png(raw_data['weaponInfo']['weaponStar'])
weaponName = raw_data['weaponInfo']['weaponName']
weaponAtk = raw_data['weaponInfo']['weaponStats'][0]['statValue']
weaponLevel = raw_data['weaponInfo']['weaponLevel']
weaponAffix = raw_data['weaponInfo']['weaponAffix']
weaponEffect = raw_data['weaponInfo']['weaponEffect']
weapon_type = raw_data['weaponInfo']['weaponType']
weapon_img.paste(weapon_star_img, (25, 235), weapon_star_img)
weapon_text = ImageDraw.Draw(weapon_img)
weapon_text.text((35, 80), weaponName, (255, 255, 255), genshin_font_origin(50), anchor='lm')
weapon_text.text((35, 120), weapon_type, (255, 255, 255), genshin_font_origin(20), anchor='lm')
weapon_text.text((35, 160), '基础攻击力', (255, 255, 255), genshin_font_origin(32), anchor='lm')
weapon_text.text((368, 160), str(weaponAtk), (255, 255, 255), genshin_font_origin(32), anchor='rm')
if len(raw_data['weaponInfo']['weaponStats']) == 2:
weapon_sub_info = raw_data['weaponInfo']['weaponStats'][1]['statName']
weapon_sub_value = raw_data['weaponInfo']['weaponStats'][1]['statValue']
weapon_text.text((35, 211), weapon_sub_info, (255, 255, 255), genshin_font_origin(32), anchor='lm')
weapon_text.text((368, 211), str(weapon_sub_value), (255, 255, 255), genshin_font_origin(32), anchor='rm')
else:
weapon_text.text((35, 211), '该武器无副词条', (255, 255, 255), genshin_font_origin(32), anchor='lm')
weapon_text.text((73, 303), f'Lv.{weaponLevel}', (255, 255, 255), genshin_font_origin(28), anchor='mm')
weapon_text.text((130, 305), f'精炼{str(weaponAffix)}', (255, 239, 173), genshin_font_origin(28), anchor='lm')
weaponEffect = strLenth(weaponEffect, 25, 455)
weapon_text.text((25, 335), weaponEffect, (255, 255, 255), genshin_font_origin(25))
img.paste(weapon_img, (387, 590), weapon_img)
# 圣遗物部分
artifactsAllScore = 0
for aritifact in raw_data['equipList']:
artifacts_img = Image.open(TEXT_PATH / 'char_info_artifacts.png')
artifacts_piece_img = Image.open(RELIC_PATH / '{}.png'.format(aritifact['icon']))
artifacts_piece_new_img = artifacts_piece_img.resize((75, 75), Image.Resampling.LANCZOS).convert("RGBA")
#artifacts_piece_new_img.putalpha(
# artifacts_piece_new_img.getchannel('A').point(lambda x: round(x * 0.5) if x > 0 else 0))
artifacts_img.paste(artifacts_piece_new_img, (195, 35), artifacts_piece_new_img)
aritifactStar_img = get_star_png(aritifact['aritifactStar'])
artifactsPos = aritifact['aritifactPieceName']
artifacts_img.paste(aritifactStar_img, (20, 165), aritifactStar_img)
artifacts_text = ImageDraw.Draw(artifacts_img)
artifacts_text.text((30, 66), aritifact['aritifactName'][:4], (255, 255, 255), genshin_font_origin(34), anchor='lm')
artifacts_text.text((30, 102), artifactsPos, (255, 255, 255), genshin_font_origin(20), anchor='lm')
mainValue = aritifact['reliquaryMainstat']['statValue']
mainName = aritifact['reliquaryMainstat']['statName']
mainLevel = aritifact['aritifactLevel']
if mainName in ['攻击力', '血量', '防御力', '元素精通']:
mainValueStr = str(mainValue)
else:
mainValueStr = str(mainValue) + '%'
if '伤害加成' in mainName:
mainName = mainName.replace('伤害加成', '伤加成').replace('元素', '').replace('', '')
mainNameNew = mainName.replace('百分比', '')
artifacts_text.text((30, 141), mainNameNew, (255, 255, 255), genshin_font_origin(28), anchor='lm')
artifacts_text.text((263, 141), mainValueStr, (255, 255, 255), genshin_font_origin(28), anchor='rm')
artifacts_text.text((55, 219), '+{}'.format(str(mainLevel)), (255, 255, 255), genshin_font_origin(24),
anchor='mm')
artifactsScore = 0
for index, i in enumerate(aritifact['reliquarySubstats']):
subName = i['statName']
subValue = i['statValue']
if subName in ['攻击力', '血量', '防御力', '元素精通']:
subValueStr = str(subValue)
else:
subValueStr = str(subValue) + '%'
artifactsScore += await get_artifacts_score(subName, subValue)
subNameStr = subName.replace('百分比', '').replace('元素', '')
artifacts_text.text((20, 256 + index * 33), '·{}'.format(subNameStr), (255, 255, 255),
genshin_font_origin(25), anchor='lm')
artifacts_text.text((268, 256 + index * 33), '{}'.format(subValueStr), (255, 255, 255),
genshin_font_origin(25), anchor='rm')
artifactsAllScore += artifactsScore
artifacts_text.text((268, 190), f'{math.ceil(artifactsScore)}', (255, 255, 255), genshin_font_origin(23),
anchor='rm')
if artifactsPos == '生之花':
img.paste(artifacts_img, (18, 1075), artifacts_img)
elif artifactsPos == '死之羽':
img.paste(artifacts_img, (318, 1075), artifacts_img)
elif artifactsPos == '时之沙':
img.paste(artifacts_img, (618, 1075), artifacts_img)
elif artifactsPos == '空之杯':
img.paste(artifacts_img, (18, 1447), artifacts_img)
elif artifactsPos == '理之冠':
img.paste(artifacts_img, (318, 1447), artifacts_img)
# 角色基本信息
img_text = ImageDraw.Draw(img)
img_text.text((411, 72), char_name, (255, 255, 255), genshin_font_origin(55), anchor='lm')
img_text.text((411, 122), '等级{}'.format(char_level), (255, 255, 255), genshin_font_origin(40), anchor='lm')
img_text.text((747, 126), str(char_fetter), (255, 255, 255), genshin_font_origin(28), anchor='lm')
# aeq
# img_text.text((110, 771), a_skill_name, (255, 255, 255), genshin_font_origin(26), anchor='lm')
img_text.text((103, 812), f'{str(a_skill_level)}', (255, 255, 255), genshin_font_origin(30), anchor='mm')
# img_text.text((110, 872), e_skill_name, (255, 255, 255), genshin_font_origin(26), anchor='lm')
img_text.text((103, 915), f'{str(e_skill_level)}', (255, 255, 255), genshin_font_origin(30), anchor='mm')
# img_text.text((110, 973), q_skill_name, (255, 255, 255), genshin_font_origin(26), anchor='lm')
img_text.text((103, 1016), f'{str(q_skill_level)}', (255, 255, 255), genshin_font_origin(30), anchor='mm')
fight_prop = raw_data['avatarFightProp']
hp = fight_prop['hp']
attack = fight_prop['atk']
defense = fight_prop['def']
em = fight_prop['elementalMastery']
critrate = fight_prop['critRate']
critdmg = fight_prop['critDmg']
ce = fight_prop['energyRecharge']
dmgBonus = fight_prop['dmgBonus'] if fight_prop['physicalDmgBonus'] <= fight_prop['dmgBonus'] else fight_prop['physicalDmgBonus']
hp_green = fight_prop['addHp']
attack_green = fight_prop['addAtk']
defense_green = fight_prop['addDef']
# 属性
img_text.text((785, 174), str(round(hp)), (255, 255, 255), genshin_font_origin(28), anchor='rm')
img_text.text((785, 227), str(round(attack)), (255, 255, 255), genshin_font_origin(28), anchor='rm')
img_text.text((785, 280), str(round(defense)), (255, 255, 255), genshin_font_origin(28), anchor='rm')
img_text.text((785, 333), str(round(em)), (255, 255, 255), genshin_font_origin(28), anchor='rm')
img_text.text((785, 386), f'{str(round(critrate * 100, 2))}%', (255, 255, 255), genshin_font_origin(28),
anchor='rm')
img_text.text((785, 439), f'{str(round(critdmg * 100, 2))}%', (255, 255, 255), genshin_font_origin(28), anchor='rm')
img_text.text((785, 492), f'{str(round(ce * 100, 1))}%', (255, 255, 255), genshin_font_origin(28), anchor='rm')
img_text.text((785, 545), f'{str(round(dmgBonus * 100, 1))}%', (255, 255, 255), genshin_font_origin(28),
anchor='rm')
img_text.text((805, 174), f'(+{str(round(hp_green))})', (95, 251, 80), genshin_font_origin(28), anchor='lm')
img_text.text((805, 227), f'(+{str(round(attack_green))})', (95, 251, 80), genshin_font_origin(28), anchor='lm')
img_text.text((805, 280), f'(+{str(round(defense_green))})', (95, 251, 80), genshin_font_origin(28), anchor='lm')
uid = raw_data['playerUid']
data_time = raw_data['dataTime']
# uid
img_text.text((350, 1035), f'UID{uid}', (255, 255, 255), genshin_font_origin(24), anchor='rm')
# 数据最后更新时间
img_text.text((780, 600), f'数据最后更新于{data_time}', (255, 255, 255), genshin_font_origin(22), anchor='rm')
# 角色评分
img_text.text((768, 1557), f'{round(artifactsAllScore, 1)}', (255, 255, 255), genshin_font_origin(50), anchor='mm')
percent = await get_char_percent(raw_data)
img_text.text((768, 1690), f'{str(percent)+"%"}', (255, 255, 255), genshin_font_origin(50), anchor='mm')
img = img.convert('RGB')
result_buffer = BytesIO()
img.save(result_buffer, format='JPEG', subsampling=0, quality=90)
imgmes = 'base64://' + b64encode(result_buffer.getvalue()).decode()
res = imgmes
return res