diff --git a/zhenxun/utils/_build_image.py b/zhenxun/utils/_build_image.py index 5922d448..c69313bc 100644 --- a/zhenxun/utils/_build_image.py +++ b/zhenxun/utils/_build_image.py @@ -42,8 +42,8 @@ class BuildImage: def __init__( self, - width: int = 0, - height: int = 0, + width: float = 0, + height: float = 0, color: ColorAlias = (255, 255, 255), mode: ModeType = "RGBA", font: str | Path | FreeTypeFont = "HYWenHei-85W.ttf", @@ -63,12 +63,14 @@ class BuildImage: else: self.markImg = Image.open(background) if width and height: - self.markImg = self.markImg.resize((width, height), Resampling.LANCZOS) + self.markImg = self.markImg.resize( + (int(width), int(height)), Resampling.LANCZOS + ) else: self.width = self.markImg.width self.height = self.markImg.height elif width and height: - self.markImg = Image.new(mode, (width, height), color) # type: ignore + self.markImg = Image.new(mode, (int(width), int(height)), color) else: raise ValueError("长度和宽度不能为空...") self.draw = ImageDraw.Draw(self.markImg) @@ -238,7 +240,7 @@ class BuildImage: _font = cls.load_font(font, font_size) temp_image = Image.new("RGB", (1, 1), (255, 255, 255)) draw = ImageDraw.Draw(temp_image) - text_box = draw.textbbox((0, 0), str(text), font=_font) # type: ignore + text_box = draw.textbbox((0, 0), text, font=_font) # pyright: ignore[reportArgumentType] text_width = text_box[2] - text_box[0] text_height = text_box[3] - text_box[1] return text_width, text_height + 10 @@ -430,7 +432,7 @@ class BuildImage: self.markImg.show() @run_sync - def resize(self, ratio: float = 0, width: int = 0, height: int = 0) -> Self: + def resize(self, ratio: float = 0, width: float = 0, height: float = 0) -> Self: """ 压缩图片 @@ -451,7 +453,7 @@ class BuildImage: if not width and not height: width = int(self.width * ratio) height = int(self.height * ratio) - self.markImg = self.markImg.resize((width, height), Image.LANCZOS) # type: ignore + self.markImg = self.markImg.resize((int(width), int(height)), Image.LANCZOS) # type: ignore self.width, self.height = self.markImg.size self.draw = ImageDraw.Draw(self.markImg) return self @@ -580,7 +582,7 @@ class BuildImage: @run_sync def line( self, - xy: tuple[int, int, int, int], + xy: tuple[float, float, float, float], fill: tuple[int, int, int] | str = "#D8DEE4", width: int = 1, ) -> Self: diff --git a/zhenxun/utils/_build_mat.py b/zhenxun/utils/_build_mat.py index a3de3087..5946e526 100644 --- a/zhenxun/utils/_build_mat.py +++ b/zhenxun/utils/_build_mat.py @@ -321,8 +321,7 @@ class BuildMat: if not self.build_data.y_index: """没有指定y_index时,使用data自动生成""" max_num = max(self.build_data.data) - if max_num < 5: - max_num = 5 + max_num = max(max_num, 5) s = int(max_num / 5) _y_index = [max_num] for _n in range(4): @@ -334,23 +333,20 @@ class BuildMat: # _tmp = ["_" for _ in range(len(_y_index) - 1)] # _tmp.append(str(_y_index[0])) # _y_index = _tmp - self.build_data.y_index = _y_index # type: ignore + self.build_data.y_index = _y_index for item in self.build_data.y_index: text_size = BuildImage.get_text_size(str(item), font) if text_size[0] > padding_width: padding_width = text_size[0] y_height_list.append(text_size) if self.build_data.mat_type == MatType.BARH: - _tmp = x_width_list - x_width_list = y_height_list - y_height_list = _tmp + x_width_list, y_height_list = y_height_list, x_width_list old_space = self.build_data.space width = padding_width * 2 + self.build_data.space[0] * 2 + 20 height = ( - sum([h[1] + self.build_data.space[1] for h in y_height_list]) + sum(h[1] + self.build_data.space[1] for h in y_height_list) + self.build_data.space[1] * 2 - + 30 - ) + ) + 30 _x_index = self.build_data.x_index _y_index = self.build_data.y_index _barh_max_text_width = 0 @@ -376,7 +372,7 @@ class BuildMat: width += self.build_data.space[0] * (len(_x_index) - 1) else: """非横向柱状图时加字体宽度""" - width += sum([w[0] + self.build_data.space[0] for w in x_width_list]) + width += sum(w[0] + self.build_data.space[0] for w in x_width_list) A = BuildImage( width + 5, diff --git a/zhenxun/utils/_image_template.py b/zhenxun/utils/_image_template.py index 327f7bc2..b3c2f25f 100644 --- a/zhenxun/utils/_image_template.py +++ b/zhenxun/utils/_image_template.py @@ -232,8 +232,8 @@ class ImageTemplate: async def __build_text_image( cls, text: str, - width: int, - height: int, + width: float, + height: float, font: FreeTypeFont, font_color: str | tuple[int, int, int] = (0, 0, 0), color: str | tuple[int, int, int] = (255, 255, 255), diff --git a/zhenxun/utils/image_utils.py b/zhenxun/utils/image_utils.py index d5affc7d..110ed3e5 100644 --- a/zhenxun/utils/image_utils.py +++ b/zhenxun/utils/image_utils.py @@ -65,13 +65,13 @@ async def text2image( top_padding = padding[0] left_padding = padding[1] _font = BuildImage.load_font(font, font_size) + image_list = [] if auto_parse and re.search(r"(.*)", text): _data = [] new_text = "" placeholder_index = 0 for s in text.split(""): - r = re.search(r"(.*)", s) - if r: + if r := re.search(r"(.*)", s): start, end = r.span() if start != 0 and (t := s[:start]): new_text += t @@ -79,14 +79,13 @@ async def text2image( [ (start, end), f"[placeholder_{placeholder_index}]", - r.group(1).strip(), - r.group(2), + r[1].strip(), + r[2], ] ) new_text += f"[placeholder_{placeholder_index}]" placeholder_index += 1 new_text += text.split("")[-1] - image_list = [] current_placeholder_index = 0 # 切分换行,每行为单张图片 for s in new_text.split("\n"): @@ -97,12 +96,9 @@ async def text2image( for _ in range(s.count("[placeholder_")): placeholder = _data[_tmp_index] if "font_size" in placeholder[2]: - r = re.search(r"font_size=['\"]?(\d+)", placeholder[2]) - if r: - w, h = BuildImage.get_text_size( - placeholder[3], font, int(r.group(1)) - ) - img_height = img_height if img_height > h else h + if r := re.search(r"font_size=['\"]?(\d+)", placeholder[2]): + w, h = BuildImage.get_text_size(placeholder[3], font, int(r[1])) + img_height = max(img_height, h) img_width += w else: img_width += BuildImage.get_text_size(placeholder[3], _font)[0] @@ -135,10 +131,8 @@ async def text2image( _font = e.split("=")[-1] if e.startswith("font_size=") or e.startswith("fs="): _font_size = int(e.split("=")[-1]) - if _font_size > 1000: - _font_size = 1000 - if _font_size < 1: - _font_size = 1 + _font_size = min(_font_size, 1000) + _font_size = max(_font_size, 1) if e.startswith("font_color") or e.startswith("fc="): _font_color = e.split("=")[-1] text_img = await BuildImage.build_text_image( @@ -167,7 +161,7 @@ async def text2image( width = 0 for img in image_list: height += img.h - width = width if width > img.w else img.w + width = max(width, img.w) width += pw height += ph A = BuildImage(width + left_padding, height + top_padding, color=color) @@ -179,12 +173,11 @@ async def text2image( width = 0 height = 0 _, h = BuildImage.get_text_size("正", _font) - line_height = int(font_size / 3) - image_list = [] + line_height = font_size // 3 for s in text.split("\n"): w, _ = BuildImage.get_text_size(s.strip() or "正", _font) height += h + line_height - width = width if width > w else w + width = max(width, w) image_list.append( await BuildImage.build_text_image( s.strip(), font, font_size, font_color @@ -205,7 +198,7 @@ async def text2image( return A -def group_image(image_list: list[BuildImage]) -> tuple[list[list[BuildImage]], int]: +def group_image(image_list: list[BuildImage]) -> tuple[list[list[BuildImage]], float]: """ 说明: 根据图片大小进行分组 @@ -240,7 +233,7 @@ def group_image(image_list: list[BuildImage]) -> tuple[list[list[BuildImage]], i break else: break - total_w += max([x.width for x in group]) + 15 + total_w += max(x.width for x in group) + 15 image_group.append(group) while surplus_list: surplus_list = [x for x in surplus_list if x.uid not in is_use] @@ -252,7 +245,7 @@ def group_image(image_list: list[BuildImage]) -> tuple[list[list[BuildImage]], i _w = 0 index = -1 for i, ig in enumerate(image_group): - if s := sum([x.height for x in ig]) > _w: + if s := sum(x.height for x in ig) > _w: _w = s index = i if index != -1: @@ -262,29 +255,29 @@ def group_image(image_list: list[BuildImage]) -> tuple[list[list[BuildImage]], i max_h = 0 max_w = 0 for ig in image_group: - if (_h := sum([x.height + 15 for x in ig])) > max_h: + if (_h := sum(x.height + 15 for x in ig)) > max_h: max_h = _h - max_w += max([x.width for x in ig]) + 30 + max_w += max(x.width for x in ig) + 30 is_use.clear() while abs(max_h - max_w) > 200 and len(image_group) - 1 >= len(image_group[-1]): for img in image_group[-1]: _min_h = 999999 _min_index = -1 for i, ig in enumerate(image_group): - if (_h := sum([x.height for x in ig]) + img.height) < _min_h: + if (_h := sum(x.height for x in ig) + img.height) < _min_h: _min_h = _h _min_index = i is_use.append(_min_index) image_group[_min_index].append(img) - max_w -= max([x.width for x in image_group[-1]]) - 30 + max_w -= max(x.width for x in image_group[-1]) - 30 image_group.pop(-1) - max_h = max([sum([x.height + 15 for x in ig]) for ig in image_group]) + max_h = max(sum(x.height + 15 for x in ig) for ig in image_group) return image_group, max(max_h + 250, max_w + 70) async def build_sort_image( image_group: list[list[BuildImage]], - h: int | None = None, + h: float | None = None, padding_top: int = 200, color: ColorAlias = ( 255, @@ -307,16 +300,15 @@ async def build_sort_image( """ bk_file = None if background_path: - random_bk = os.listdir(background_path) - if random_bk: + if random_bk := os.listdir(background_path): bk_file = random.choice(random_bk) image_w = 0 image_h = 0 if not h: for ig in image_group: - _w = max([x.width + 30 for x in ig]) + _w = max(x.width + 30 for x in ig) image_w += _w + 30 - _h = sum([x.height + 10 for x in ig]) + _h = sum(x.height + 10 for x in ig) if _h > image_h: image_h = _h image_h += padding_top @@ -342,7 +334,7 @@ async def build_sort_image( for img in ig: await A.paste(img, (curr_w, curr_h)) curr_h += img.height + 10 - curr_w += max([x.width for x in ig]) + 30 + curr_w += max(x.width for x in ig) + 30 return A