mirror of
https://github.com/KimigaiiWuyi/GenshinUID.git
synced 2025-05-31 04:30:29 +08:00
179 lines
6.1 KiB
Python
179 lines
6.1 KiB
Python
import math
|
||
import random
|
||
from io import BytesIO
|
||
from pathlib import Path
|
||
from typing import Tuple, Union
|
||
|
||
from PIL import Image
|
||
from httpx import get
|
||
|
||
BG_PATH = Path(__file__).parent / 'bg'
|
||
|
||
|
||
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(BG_PATH.iterdir()))
|
||
edit_bg = Image.open(bg_path).convert('RGBA')
|
||
|
||
# 确定图片的长宽
|
||
based_scale = '%.3f' % (based_w / based_h)
|
||
|
||
w, h = edit_bg.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:
|
||
bg_img2 = edit_bg.resize((new_w, based_h), Image.ANTIALIAS)
|
||
else:
|
||
bg_img2 = edit_bg.resize((based_w, new_h), Image.ANTIALIAS)
|
||
bg_img = bg_img2.crop((0, 0, based_w, based_h))
|
||
|
||
return bg_img
|
||
|
||
|
||
class CustomizeImage:
|
||
def __init__(self, image: str, 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)
|
||
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: str, based_w: int, based_h: int) -> Image.Image:
|
||
# 获取背景图片
|
||
if image:
|
||
edit_bg = Image.open(BytesIO(get(image).content)).convert('RGBA')
|
||
else:
|
||
bg_path = random.choice(list(BG_PATH.iterdir()))
|
||
edit_bg = Image.open(bg_path).convert('RGBA')
|
||
|
||
# 确定图片的长宽
|
||
based_scale = '%.3f' % (based_w / based_h)
|
||
|
||
w, h = edit_bg.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:
|
||
bg_img2 = edit_bg.resize((new_w, based_h), Image.ANTIALIAS)
|
||
else:
|
||
bg_img2 = edit_bg.resize((based_w, new_h), Image.ANTIALIAS)
|
||
bg_img = bg_img2.crop((0, 0, based_w, based_h))
|
||
|
||
return bg_img
|
||
|
||
@staticmethod
|
||
def get_bg_color(edit_bg: Image.Image) -> Tuple[int, int, int]:
|
||
# 获取背景主色
|
||
color = 8
|
||
q = edit_bg.quantize(colors=color, method=2)
|
||
bg_color = (0, 0, 0)
|
||
based_light = 195
|
||
temp = 9999
|
||
for i in range(0, 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:
|
||
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
|