diff --git a/async-bot.py b/async-bot.py index 47ed7c1..ac730b5 100644 --- a/async-bot.py +++ b/async-bot.py @@ -3,7 +3,7 @@ from typing import NewType, Optional from socketio import AsyncSimpleClient from aiohttp import ClientSession from aiohttp_socks import ProxyConnector -from PIL import Image, ImageFont, ImageDraw, ImageFilter, ImageSequence +from PIL import Image, ImageFont, ImageDraw, ImageFilter, ImageSequence, ImageChops from base64 import b64decode from random import choice from json import load @@ -28,15 +28,19 @@ class AsyncBotManager: self.animations: list[Animation] = [] - def put_text(self, x: int, y: int, text: str): - with Image.new("LA", (int(self.font.getlength(text) + 12), 16)) as im: + @staticmethod + def get_text_image(text: str, font: ImageFont.ImageFont | ImageFont.FreeTypeFont) -> Image.Image: + with Image.new("LA", (int(font.getlength(text) + 12), 16)) as im: draw = ImageDraw.Draw(im) draw.rectangle((0, 0, im.width, im.height), (0, 0)) - draw.text((6, 5), text, font=self.font, fill=(255, 0)) + draw.text((6, 5), text, font=font, fill=(255, 0)) alpha = im.convert("L").filter(ImageFilter.MaxFilter(3)) im.putalpha(alpha) - self.put_image(x, y, im) + return im.copy() + + def put_text(self, x: int, y: int, text: str): + self.put_image(x, y, self.get_text_image(text, self.font)) def put_image(self, ox: int, oy: int, im: Image.Image): for y in range(im.height): @@ -54,18 +58,25 @@ class AsyncBotManager: self.difference[index] = value def add_animation( - self, ox: int, oy: int, image: Image.Image, spf: float = 1 + self, ox: int, oy: int, frames: list[Image.Image], spf: float = 1 ) -> None: animation = Animation(([], spf)) - for frame in ImageSequence.Iterator(image): + alpha = Image.new("L", frames[0].size, 0) + for frame in frames: + frame_la = frame.convert("LA") + frame_alpha = frame_la.getchannel("A") + alpha = ImageChops.add(alpha, frame_alpha) + + for frame in frames: frame_la = frame.convert("LA") pixelmap = PixelMap({}) for y in range(frame_la.height): for x in range(frame_la.width): l, a = frame_la.getpixel((x, y)) # type: ignore + ga: int = alpha.getpixel((x, y)) # type: ignore index = x + ox + (y + oy) * 1000 - if a > 128 and index not in self.avoid: - pixelmap[index] = l > 128 + if (a > 128 or ga > 128) and index not in self.avoid: + pixelmap[index] = l > 128 if a > 128 else True animation[0].append(pixelmap) self.animations.append(animation) @@ -188,12 +199,24 @@ async def amain() -> None: for elem in settings["elements"]: if elem["type"] == "text": mgr.put_text(elem["x"], elem["y"], elem["text"]) + elif elem["type"] == "text_anim": + frames: list[Image.Image] = [] + for text in elem["lines"]: + frames.append(mgr.get_text_image(text, mgr.font)) + mgr.add_animation(elem["x"], elem["y"], frames, elem["spf"]) + for frame in frames: + frame.close() elif elem["type"] == "image": with Image.open(elem["path"]).convert("LA") as im: mgr.put_image(elem["x"], elem["y"], im) elif elem["type"] == "animation": with Image.open(elem["path"]) as anim: - mgr.add_animation(elem["x"], elem["y"], anim, elem["spf"]) + frames: list[Image.Image] = [] + for frame in ImageSequence.Iterator(anim): + frames.append(frame.copy()) + mgr.add_animation(elem["x"], elem["y"], frames, elem["spf"]) + for frame in frames: + frame.close() elif elem["type"] == "rgb111": ox, oy = elem["x"], elem["y"] with Image.open(elem["path"]).convert("RGBA") as im: