Spaces:
Sleeping
Sleeping
| from typing import Literal | |
| from pil_utils import BuildImage | |
| from pydantic import Field | |
| from meme_generator import MemeArgsModel, MemeArgsParser, MemeArgsType, add_meme | |
| from meme_generator.utils import ( | |
| FrameAlignPolicy, | |
| Maker, | |
| make_gif_or_combined_gif, | |
| make_jpg_or_gif, | |
| ) | |
| help = "生成模式" | |
| parser = MemeArgsParser(prefix_chars="-/") | |
| group = parser.add_mutually_exclusive_group() | |
| group.add_argument( | |
| "--mode", | |
| type=str, | |
| choices=["normal", "circle", "loop"], | |
| default="normal", | |
| help=help, | |
| ) | |
| group.add_argument( | |
| "--circle", "/套娃", action="store_const", const="circle", dest="mode" | |
| ) | |
| group.add_argument("--loop", "/循环", action="store_const", const="loop", dest="mode") | |
| class Model(MemeArgsModel): | |
| mode: Literal["normal", "loop", "circle"] = Field("normal", description=help) | |
| def always_normal(img: BuildImage): | |
| def make(img: BuildImage) -> BuildImage: | |
| img_big = img.convert("RGBA").resize_width(500) | |
| img_small = img.convert("RGBA").resize_width(100) | |
| h1 = img_big.height | |
| h2 = max(img_small.height, 80) | |
| frame = BuildImage.new("RGBA", (500, h1 + h2 + 10), "white") | |
| frame.paste(img_big, alpha=True).paste( | |
| img_small, (290, h1 + 5 + (h2 - img_small.height) // 2), alpha=True | |
| ) | |
| frame.draw_text( | |
| (20, h1 + 5, 280, h1 + h2 + 5), "要我一直", halign="right", max_fontsize=60 | |
| ) | |
| frame.draw_text( | |
| (400, h1 + 5, 480, h1 + h2 + 5), "吗", halign="left", max_fontsize=60 | |
| ) | |
| return frame | |
| return make_jpg_or_gif(img, make) | |
| def always_always(img: BuildImage, loop: bool = False): | |
| tmp_img = img.convert("RGBA").resize_width(500) | |
| img_h = tmp_img.height | |
| text_h = tmp_img.resize_width(100).height + tmp_img.resize_width(20).height + 10 | |
| text_h = max(text_h, 80) | |
| frame_h = img_h + text_h | |
| text_frame = BuildImage.new("RGBA", (500, frame_h), "white") | |
| text_frame.draw_text( | |
| (0, img_h, 280, frame_h), "要我一直", halign="right", max_fontsize=60 | |
| ).draw_text((400, img_h, 500, frame_h), "吗", halign="left", max_fontsize=60) | |
| frame_num = 20 | |
| coeff = 5 ** (1 / frame_num) | |
| def maker(i: int) -> Maker: | |
| def make(img: BuildImage) -> BuildImage: | |
| img = img.convert("RGBA").resize_width(500) | |
| base_frame = text_frame.copy().paste(img, alpha=True) | |
| frame = BuildImage.new("RGBA", base_frame.size, "white") | |
| r = coeff**i | |
| for _ in range(4): | |
| x = round(358 * (1 - r)) | |
| y = round(frame_h * (1 - r)) | |
| w = round(500 * r) | |
| h = round(frame_h * r) | |
| frame.paste(base_frame.resize((w, h)), (x, y)) | |
| r /= 5 | |
| return frame | |
| return make | |
| if not loop: | |
| return make_jpg_or_gif(img, maker(0)) | |
| return make_gif_or_combined_gif( | |
| img, maker, frame_num, 0.1, FrameAlignPolicy.extend_loop | |
| ) | |
| def always(images: list[BuildImage], texts, args: Model): | |
| img = images[0] | |
| mode = args.mode | |
| if mode == "normal": | |
| return always_normal(img) | |
| elif mode == "circle": | |
| return always_always(img, loop=False) | |
| else: | |
| return always_always(img, loop=True) | |
| add_meme( | |
| "always", | |
| always, | |
| min_images=1, | |
| max_images=1, | |
| args_type=MemeArgsType( | |
| parser, Model, [Model(mode="normal"), Model(mode="circle"), Model(mode="loop")] | |
| ), | |
| keywords=["一直"], | |
| ) | |