all repos — python-meme-bot @ 33057f0c93db792282fd5a806cea4d7c25b18e8e

Telegram Bot that uses PIL to compute light image processing.

Effects.py (view raw)

 1from PIL import Image, ImageDraw, ImageFont
 2import textwrap, os
 3
 4
 5        
 6
 7
 8def tt_bt_effect(text, img):
 9    IMPACT_FONT_FILE = os.path.join("fonts", "impact.ttf")
10    BASE_WIDTH = 1200
11    LETTER_SPACING = 9
12    LINE_SPACING = 10  
13    FILL = (255, 255, 255)
14    STROKE_WIDTH = 9
15    STROKE_FILL = (0, 0, 0)
16    FONT_BASE = 100
17    MARGIN = 10
18    
19    def _draw_tt_bt(text, img, bottom=False):
20        split_caption = textwrap.wrap(text.upper(), width=20)
21        if split_caption == []:
22            return
23        font_size = FONT_BASE + 10 if len(split_caption) <= 1 else FONT_BASE
24        font = ImageFont.truetype(font=IMPACT_FONT_FILE, size=font_size)
25        img_width, img_height = img.size
26
27        d = ImageDraw.Draw(img)
28        txt_height = d.textbbox((0, 0), split_caption[0], font=font)[3]
29
30        if bottom:
31            factor = -1
32            split_caption.reverse()
33            y = (img_height - (img_height / MARGIN)) - (txt_height / 2)
34        else:
35            factor = 1
36            y = ((img_height / MARGIN)) - (txt_height / 1.5)
37
38        for line in split_caption:
39            txt_width = d.textbbox((0, 0), line, font=font)[2]
40
41            x = (img_width - txt_width - (len(line) * LETTER_SPACING))/2
42
43            for i in range(len(line)):
44                char = line[i]
45                width = font.getlength(char)
46                d.text((x, y), char, fill=FILL, stroke_width=STROKE_WIDTH, font=font, stroke_fill=STROKE_FILL)
47                x += width + LETTER_SPACING
48
49            y = y + (txt_height + LINE_SPACING) * factor
50    
51    lines = [x for x in text.split("\n") if x]
52    
53    tt = lines[0] if len(lines) > 0 else None
54    bt = lines[1] if len(lines) > 1 else None
55    
56    img = img.resize((BASE_WIDTH, int(img.size[1] * float(BASE_WIDTH / img.size[0]))))
57    
58    if tt is None and bt is None:
59        return img
60    
61    if (tt is not None):
62        _draw_tt_bt(tt, img)
63    if (bt is not None):
64        _draw_tt_bt(bt, img, bottom=True)
65        
66    h_size = int(float(img.size[1]) * (BASE_WIDTH/2) / img.size[0])
67    img = img.resize((int(BASE_WIDTH/2), h_size))
68    
69    if img.mode in ("RGBA", "P"):
70        img = img.convert("RGB")
71    
72    return img
73
74def test(text, effect, modifier=""):
75        imgs = os.listdir("test")
76        for i in range(len(imgs)):
77            image = effect(text, Image.open(os.path.join("test", imgs[i])))
78            image.save(os.path.join("test_output", f'output{modifier}{i}.jpg'), optimize=True, quality=80)
79
80        print("Image test successful")
81
82def main():
83    test("top text\nbottom text", tt_bt_effect)
84    test("top text top text top text top text top text\nbottom text bottom text bottom text bottom text bottom text", tt_bt_effect, "_long")
85    
86if __name__ ==  "__main__":
87    main()