GenshinUID/utils/draw_image_tools/draw_image_tool.py
2022-08-29 23:26:46 +08:00

179 lines
6.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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