You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
185 lines
6.1 KiB
185 lines
6.1 KiB
7 months ago
|
from .abc import Meme
|
||
|
from PIL import Image, ImageDraw, ImageFont
|
||
|
import typing
|
||
|
|
||
|
from pseudbot.meme.post import Post
|
||
|
from pseudbot.util import (
|
||
|
alpha_comp_prep,
|
||
|
circle_pfp,
|
||
|
get_iphone_time_s,
|
||
|
text_wrap,
|
||
|
tuple_add,
|
||
|
)
|
||
|
|
||
|
|
||
|
class PhoneScreenshot(Meme):
|
||
|
from .post_styles import styles, time_style
|
||
|
|
||
|
def __init__(
|
||
|
self,
|
||
|
top_text: dict = None,
|
||
|
bottom_text: str = None,
|
||
|
style: str = "discord",
|
||
|
width: int = 1200,
|
||
|
height: int = 2340,
|
||
|
notification: str = None,
|
||
|
):
|
||
|
self.top_text = top_text
|
||
|
self.bottom_text = bottom_text
|
||
|
self.style = style
|
||
|
self.width = width
|
||
|
self.height = height
|
||
|
self.notification = notification
|
||
|
|
||
|
self.style_methods = {"discord": self.mk_pixmap}
|
||
|
|
||
|
self.init_style_posts()
|
||
|
|
||
|
if self.notification is not None:
|
||
|
self.notification_style = {
|
||
|
"offset": (102, 91),
|
||
|
"no_text_img": "templates/iphone/iphone-noti-grindr-text.png",
|
||
|
"icon": {
|
||
|
"offset": (26, 34),
|
||
|
"size": (62, 62),
|
||
|
"files": {
|
||
|
"grindr": "templates/iphone/icons/notification/grindr.png"
|
||
|
},
|
||
|
},
|
||
|
"text": {
|
||
|
"app_name": {
|
||
|
"font": "phone_sans",
|
||
|
"style": "Regular",
|
||
|
"size": 35,
|
||
|
"offset": (106, 53),
|
||
|
},
|
||
|
"heading": {
|
||
|
"font": "phone_sans",
|
||
|
"style": "Regular",
|
||
|
"size": 35,
|
||
|
"offset": (34, 128),
|
||
|
},
|
||
|
"body": {
|
||
|
"font": "phone_sans",
|
||
|
"style": "Regular",
|
||
|
"size": 35,
|
||
|
"offset": (34, 181),
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
def overlay_noti(base_img: Image) -> Image:
|
||
|
return base_img
|
||
|
|
||
|
def mk_bars(self) -> Image:
|
||
|
base_img = Image.new("RGBA", (self.width, self.height), (0, 0, 0, 0))
|
||
|
|
||
|
for bar in self.styles[self.style]["bars"]:
|
||
|
is_top = False
|
||
|
is_bottom = False
|
||
|
do_time = False
|
||
|
bg_img_path = bar["bg_img"]
|
||
|
|
||
|
if "top" in bar:
|
||
|
if bar["top"] is True:
|
||
|
is_top = True
|
||
|
do_time = True
|
||
|
if self.notification is not None:
|
||
|
do_time = False
|
||
|
if "alt_bg_img" in bar:
|
||
|
bg_img_path = self.bar["alt_bg_img"]
|
||
|
|
||
|
if "bottom" in bar:
|
||
|
if bar["bottom"] is True:
|
||
|
is_bottom = True
|
||
|
|
||
|
with Image.open(bg_img_path).convert("RGBA") as _bar_img:
|
||
|
with alpha_comp_prep(
|
||
|
Image.open(bg_img_path).convert("RGBA"),
|
||
|
size=base_img.size,
|
||
|
offset=bar["offset"],
|
||
|
) as bar_img:
|
||
|
if "text" in bar:
|
||
|
try:
|
||
|
if bar["text"]["content"] in self.top_text:
|
||
|
if "format" in bar["text"]:
|
||
|
bar_text = bar["text"]["format"].replace(
|
||
|
"%%%",
|
||
|
self.top_text[bar["text"]["content"]],
|
||
|
)
|
||
|
else:
|
||
|
bar_text = self.top_text[
|
||
|
bar["text"]["content"]
|
||
|
]
|
||
|
else:
|
||
|
bar_text = bar["text"]["default"]
|
||
|
except KeyError:
|
||
|
bar_text = "default text"
|
||
|
|
||
|
bar_img = self.draw_text(
|
||
|
img=bar_img,
|
||
|
text=bar_text,
|
||
|
offset=tuple_add(
|
||
|
bar["text"]["offset"], bar["offset"]
|
||
|
),
|
||
|
size=bar["text"]["size"],
|
||
|
fill=bar["text"]["color"],
|
||
|
variation=bar["text"]["style"],
|
||
|
fontname=bar["text"]["font"],
|
||
|
)
|
||
|
|
||
|
if do_time is True:
|
||
|
bar_img = self.draw_text(
|
||
|
img=bar_img,
|
||
|
text=get_iphone_time_s(),
|
||
|
offset=self.time_style["offset"],
|
||
|
size=self.time_style["size"],
|
||
|
fill=self.time_style["fill"][self.style],
|
||
|
variation=self.time_style["style"],
|
||
|
fontname=self.time_style["font"],
|
||
|
)
|
||
|
|
||
|
base_img = Image.alpha_composite(base_img, bar_img)
|
||
|
|
||
|
if is_bottom is True:
|
||
|
self.bottom_y_offset = 0 - _bar_img.size[1]
|
||
|
|
||
|
if self.notification is not None:
|
||
|
base_img = self.overlay_noti(base_img)
|
||
|
|
||
|
return base_img
|
||
|
|
||
|
def arrange_posts(self) -> Image:
|
||
|
post_base = Image.new(
|
||
|
"RGBA",
|
||
|
(self.width, self.height),
|
||
|
self.styles[self.style]["background"],
|
||
|
)
|
||
|
|
||
|
x_offset = 33
|
||
|
y_offset = self.height
|
||
|
|
||
|
if hasattr(self, "bottom_y_offset"):
|
||
|
y_offset = y_offset + self.bottom_y_offset
|
||
|
|
||
|
for post in reversed(self.posts):
|
||
|
p = Post(
|
||
|
top_text={"posts": [post]},
|
||
|
bottom_text=self.bottom_text,
|
||
|
style=self.style,
|
||
|
)
|
||
|
post_img = p.get_pixmap()
|
||
|
y_offset = y_offset - post_img.size[1]
|
||
|
post_base.paste(post_img, box=(x_offset, y_offset))
|
||
|
|
||
|
if y_offset < 0:
|
||
|
break
|
||
|
|
||
|
return post_base
|
||
|
|
||
|
def mk_pixmap(self):
|
||
|
bars = self.mk_bars() # Must be done before making posts!
|
||
|
posts = self.arrange_posts()
|
||
|
|
||
|
self.image = Image.alpha_composite(posts, bars)
|