From fd577a9684d927662638840a36c78e1aff5ec7c2 Mon Sep 17 00:00:00 2001 From: LWR Date: Tue, 30 May 2023 00:48:56 +0800 Subject: [PATCH] fix: Fixed the memory leak during image generation --- starbot/painter/DynamicPicGenerator.py | 5 +++++ starbot/painter/LiveReportGenerator.py | 15 +++++++++------ starbot/painter/PicGenerator.py | 16 +++++++++++++--- starbot/painter/RankingGenerator.py | 1 + starbot/utils/utils.py | 2 ++ 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/starbot/painter/DynamicPicGenerator.py b/starbot/painter/DynamicPicGenerator.py index 91b0177..b9c9561 100644 --- a/starbot/painter/DynamicPicGenerator.py +++ b/starbot/painter/DynamicPicGenerator.py @@ -317,6 +317,7 @@ class DynamicPicGenerator: auto_next_line(size[0]) img.paste(pic, (x, y), pic) + pic.close() x = int(x + size[0]) def draw_char(c: str, color: Union[Color, Tuple[int, int, int]] = Color.BLACK): @@ -522,6 +523,10 @@ class DynamicPicGenerator: cover.paste(time, (13, cover.height - time.height - 14), time) cover.paste(tv, (cover.width - tv.width - 16, cover.height - tv.height - 5), tv) + mask.close() + time.close() + tv.close() + cover_draw = ImageDraw.Draw(cover) normal_font = config.get("PAINTER_NORMAL_FONT") time_font = ImageFont.truetype(f"{cls.__resource_base_path}/resource/{normal_font}", 25) diff --git a/starbot/painter/LiveReportGenerator.py b/starbot/painter/LiveReportGenerator.py index 45cc4ec..9abcd2e 100644 --- a/starbot/painter/LiveReportGenerator.py +++ b/starbot/painter/LiveReportGenerator.py @@ -461,6 +461,7 @@ class LiveReportGenerator: unames: 昵称列表,按照数量列表降序排序 counts: 数量列表,降序排序 icon: 大航海图标 + color: 大航海文字颜色 """ count = len(counts) if count == 0 or len(faces) != len(unames) or len(unames) != len(counts): @@ -481,9 +482,9 @@ class LiveReportGenerator: mask_round(faces[i].resize((face_size, face_size)).convert("RGBA")), (x + face_padding, face_padding) ) if i != count - 1: - line.draw_img_alpha(icon, (x, 0)) + line.draw_img_alpha(icon.copy(), (x, 0)) else: - line.set_pos(x=x).draw_img_alpha(icon).set_pos(x=0) + line.set_pos(x=x).draw_img_alpha(icon.copy()).set_pos(x=0) for i, x in enumerate(xs): uname = limit_str_length(unames[i], 8) @@ -523,9 +524,9 @@ class LiveReportGenerator: resource_base_path = os.path.dirname(os.path.dirname(__file__)) icon_map = { - 0: Image.open(f"{resource_base_path}/resource/governor.png").convert("RGBA"), - 1: Image.open(f"{resource_base_path}/resource/commander.png").convert("RGBA"), - 2: Image.open(f"{resource_base_path}/resource/captain.png").convert("RGBA") + 0: f"{resource_base_path}/resource/governor.png", + 1: f"{resource_base_path}/resource/commander.png", + 2: f"{resource_base_path}/resource/captain.png" } color_map = { 0: Color.CRIMSON, @@ -548,9 +549,11 @@ class LiveReportGenerator: faces = [x[0] for x in line] unames = [x[1] for x in line] counts = [x[2] for x in line] + icon = Image.open(icon_map[i]).convert("RGBA") img.draw_img_alpha( - cls.__get_guard_line_pic(pic, width, face_size, faces, unames, counts, icon_map[i], color_map[i]) + cls.__get_guard_line_pic(pic, width, face_size, faces, unames, counts, icon, color_map[i]) ).move_pos(0, -pic.row_space) + icon.close() return img.img diff --git a/starbot/painter/PicGenerator.py b/starbot/painter/PicGenerator.py index e994031..e42b534 100644 --- a/starbot/painter/PicGenerator.py +++ b/starbot/painter/PicGenerator.py @@ -260,6 +260,7 @@ class PicGenerator: """ 在当前绘图坐标绘制一张图片,会自动移动绘图坐标至下次绘图适合位置 也可手动传入绘图坐标,手动传入时不会移动绘图坐标 + 绘制结束后,传入图片会被自动调用 close 方法关闭 Args: img: 图片路径或 Image 图片实例 @@ -273,12 +274,16 @@ class PicGenerator: self.move_pos(0, img.height + self.__ROW_SPACE) else: self.__canvas.paste(img, xy) + + img.close() + return self def draw_img_alpha(self, img: Union[str, Image.Image], xy: Optional[Tuple[int, int]] = None): """ 在当前绘图坐标绘制一张透明背景图片,会自动移动绘图坐标至下次绘图适合位置 也可手动传入绘图坐标,手动传入时不会移动绘图坐标 + 绘制结束后,传入图片会被自动调用 close 方法关闭 Args: img: 透明背景图片路径或 Image 图片实例 @@ -292,6 +297,9 @@ class PicGenerator: self.move_pos(0, img.height + self.__ROW_SPACE) else: self.__canvas.paste(img, xy, img) + + img.close() + return self def draw_img_with_border(self, @@ -303,6 +311,7 @@ class PicGenerator: """ 在当前绘图坐标绘制一张图片并附带圆角矩形边框,会自动移动绘图坐标至下次绘图适合位置 也可手动传入绘图坐标,手动传入时不会移动绘图坐标 + 绘制结束后,传入图片会被自动调用 close 方法关闭 Args: img: 图片路径或 Image 图片实例 @@ -571,22 +580,23 @@ class PicGenerator: def save(self, path: str): """ - 保存图片 + 保存图片,终端操作,保存完成后会关闭图片,无法再对图片进行操作 Args: path: 保存路径 """ self.__canvas.save(path) - return self + self.__canvas.close() def base64(self) -> str: """ - 结束绘图,获取 Base64 字符串 + 获取 Base64 字符串,终端操作,获取后会关闭图片,无法再对图片进行操作 Returns: Base64 字符串 """ io = BytesIO() self.__canvas.save(io, format="PNG") + self.__canvas.close() return base64.b64encode(io.getvalue()).decode() diff --git a/starbot/painter/RankingGenerator.py b/starbot/painter/RankingGenerator.py index 8c7472d..de38ba2 100644 --- a/starbot/painter/RankingGenerator.py +++ b/starbot/painter/RankingGenerator.py @@ -59,6 +59,7 @@ class RankingGenerator: else: mask_draw.polygon(((0, 0), (0, height), (height, height)), 0) bar.putalpha(mask) + mask.close() return bar diff --git a/starbot/utils/utils.py b/starbot/utils/utils.py index fcb702e..cdc0b98 100644 --- a/starbot/utils/utils.py +++ b/starbot/utils/utils.py @@ -127,6 +127,7 @@ def mask_round(img: Image.Image) -> Image.Image: img_width, img_height = img.size mask_draw.ellipse((0, 0, img_width, img_height), fill=255) img.putalpha(mask) + mask.close() return img @@ -146,6 +147,7 @@ def mask_rounded_rectangle(img: Image.Image, radius: int = 10) -> Image.Image: img_width, img_height = img.size mask_draw.rounded_rectangle((0, 0, img_width, img_height), radius, 255) img.putalpha(mask) + mask.close() return img