all repos — python-meme-bot @ 75653e1ef66c3befa54eb0c628b04e430d091db4

Telegram Bot that uses PIL to compute light image processing.

Effects.py (view raw)

  1from PIL import Image, ImageDraw, ImageFont, ImageEnhance
  2import textwrap, os, random, time, math
  3
  4random.seed(time.time())
  5
  6BASE_WIDTH = 1200
  7IMPACT_FONT_FILE = os.path.join("fonts", "impact.ttf")
  8ARIAL_FONT_FILE = os.path.join("fonts", "opensans.ttf")
  9
 10def _darken_image(image: Image, amount=0.5):
 11    return ImageEnhance.Brightness(image).enhance(amount)
 12
 13def _draw_line(d: ImageDraw, x: int, y: int, line: str, font: ImageFont, letter_spacing: int = 9, fill = (255, 255, 255), stroke_width: int = 9, stroke_fill = (0, 0, 0)):
 14    
 15    for i in range(len(line)):
 16                d.text((x, y), line[i], fill=fill, stroke_width=stroke_width, font=font, stroke_fill=stroke_fill)
 17                x += font.getlength(line[i]) + letter_spacing
 18
 19def tt_bt_effect(text: str, img: Image):
 20    LETTER_SPACING = 9
 21    LINE_SPACING = 10  
 22    FILL = (255, 255, 255)
 23    STROKE_WIDTH = 9
 24    STROKE_FILL = (0, 0, 0)
 25    FONT_BASE = 100
 26    MARGIN = 10
 27    
 28    def _draw_tt_bt(text, img, bottom=False):
 29        split_caption = textwrap.wrap(text.upper(), width=20)
 30        if split_caption == []:
 31            return
 32        font_size = FONT_BASE + 10 if len(split_caption) <= 1 else FONT_BASE
 33        font = ImageFont.truetype(font=IMPACT_FONT_FILE, size=font_size)
 34        img_width, img_height = img.size
 35
 36        d = ImageDraw.Draw(img)
 37        txt_height = d.textbbox((0, 0), split_caption[0], font=font)[3]
 38
 39        if bottom:
 40            factor = -1
 41            split_caption.reverse()
 42            y = (img_height - (img_height / MARGIN)) - (txt_height / 2)
 43        else:
 44            factor = 1
 45            y = (img_height / MARGIN) - (txt_height / 1.5)
 46
 47        for line in split_caption:
 48            txt_width = d.textbbox((0, 0), line, font=font)[2]
 49
 50            x = (img_width - txt_width - (len(line) * LETTER_SPACING))/2
 51
 52            _draw_line(d, x, y, line, font, LETTER_SPACING, FILL, STROKE_WIDTH, STROKE_FILL)
 53
 54            y += (txt_height + LINE_SPACING) * factor
 55    
 56    lines = [x for x in text.split("\n") if x]
 57    
 58    tt = lines[0] if len(lines) > 0 else None
 59    bt = lines[1] if len(lines) > 1 else None
 60    
 61    img = img.resize((BASE_WIDTH, int(img.size[1] * float(BASE_WIDTH / img.size[0]))))
 62    
 63    if tt is None and bt is None:
 64        return img
 65    
 66    if (tt is not None):
 67        _draw_tt_bt(tt, img)
 68    if (bt is not None):
 69        _draw_tt_bt(bt, img, bottom=True)
 70        
 71    img = img.resize((int(BASE_WIDTH/2), int(float(img.size[1]) * (BASE_WIDTH/2) / img.size[0])))
 72    
 73    if img.mode in ("RGBA", "P"):
 74        img = img.convert("RGB")
 75    
 76    return img
 77
 78def splash_effect(text: str, img: Image):
 79    LETTER_SPACING = 1
 80    LINE_SPACING = 3  
 81    FILL = (255, 255, 255)
 82    STROKE_WIDTH = 1
 83    STROKE_FILL = (0, 0, 0)
 84    FONT_FIRST = 50
 85    FONT_BASE = 75
 86    MARGIN = 10
 87    LINE_WIDTH = 20
 88    
 89    lines = [x for x in text.split("\n") if x]
 90    first_line = lines.pop(0)
 91    text = "\n".join(lines)
 92    
 93    img = img.resize((BASE_WIDTH, int(img.size[1] * float(BASE_WIDTH / img.size[0]))))
 94    
 95    img = _darken_image(img)
 96    
 97    text = textwrap.wrap(text.upper(), width=LINE_WIDTH)
 98    if text == []:
 99        return
100    text.insert(0, first_line)
101    
102    while True:
103        font_first = ImageFont.truetype(font=ARIAL_FONT_FILE, size=int(FONT_BASE - (FONT_BASE / 2)))
104        font_base = ImageFont.truetype(font=ARIAL_FONT_FILE, size=FONT_BASE)
105
106        img_width, img_height = img.size
107        d = ImageDraw.Draw(img)
108
109        _, _, first_txt_width, first_txt_height = d.textbbox((0, 0), text[0], font=font_first)
110        _, _, max_txt_width, txt_height = d.textbbox((0, 0), text[1], font=font_base)
111
112        total_height = (txt_height + LINE_SPACING) * (len(text) - 1) + LINE_SPACING + first_txt_height
113
114        if (total_height < img_height / 2) or (FONT_BASE < 10):
115            break
116        
117        FONT_BASE = FONT_BASE - 5
118        
119    y = (img_height - total_height) / 2
120        
121    for i in range(1, len(text)):
122        temp = int(font_base.getlength(text[i]))
123        if temp > max_txt_width:
124            max_txt_width = temp
125
126    max_txt_width = max_txt_width if max_txt_width > first_txt_width else first_txt_width
127    x_start = (img_width - max_txt_width) / 2
128        
129    for i in range(len(text)):
130        '''
131        if align == "center":
132            txt_width = d.textbbox((0, 0), line, font=font)[2]
133            x = (img_width - txt_width - (len(line) * LETTER_SPACING))/2
134        '''
135        font = font_base if i > 0 else font_first
136        _draw_line(d=d, x=x_start, y=y, line=text[i], font=font, letter_spacing=LETTER_SPACING, fill=FILL, stroke_width=STROKE_WIDTH, stroke_fill=STROKE_FILL)
137
138        y += (txt_height if i > 0 else first_txt_height) + LINE_SPACING
139        
140    img = img.resize((int(BASE_WIDTH/2), int(float(img.size[1]) * (BASE_WIDTH/2) / img.size[0])))
141    
142    if img.mode in ("RGBA", "P"):
143        img = img.convert("RGB")
144    
145    return img
146
147def wot_effect(input_text: str, img: Image):
148    LETTER_SPACING = 1
149    LINE_SPACING = 3  
150    FILL = (255, 255, 255)
151    STROKE_WIDTH = 1
152    STROKE_FILL = (0, 0, 0)
153    FONT_BASE = 50
154    MARGIN = 10
155    LINE_WIDTH = 43
156    
157    img = img.resize((BASE_WIDTH, int(img.size[1] * float(BASE_WIDTH / img.size[0]))))
158    img = _darken_image(img)
159    
160    img_width, img_height = img.size
161    d = ImageDraw.Draw(img)
162    
163    factor = img_width / img_height
164    #print("factor: " + str(factor))
165
166    text = textwrap.wrap(input_text, width=LINE_WIDTH)
167    if text == []:
168        return
169    
170    while True:
171        text = textwrap.wrap(input_text, width=LINE_WIDTH)
172        
173        longest_line = text[0]
174        for line in text:
175            if len(line) > len(longest_line):
176                longest_line = line
177        
178        font = ImageFont.truetype(font=ARIAL_FONT_FILE, size=FONT_BASE)
179        _, _, txt_width, txt_height = d.textbbox((0, 0), longest_line, font=font)
180        total_height = (txt_height + LINE_SPACING) * len(text)
181
182        if total_height < img_height or FONT_BASE < 5:
183            break
184        
185        FONT_BASE -= 3
186        LINE_WIDTH += int(factor * 3)
187        #print(LINE_WIDTH)
188    
189    y = (img_height - total_height) / 2
190        
191    for i in range(len(text)):
192        txt_width = d.textbbox((0, 0), text[i], font=font)[2]
193        x = (img_width - txt_width - (len(text[i]) * LETTER_SPACING))/2
194
195        _draw_line(d=d, x=x, y=y, line=text[i], font=font, letter_spacing=LETTER_SPACING, fill=FILL, stroke_width=STROKE_WIDTH, stroke_fill=STROKE_FILL)
196
197        y += txt_height + LINE_SPACING
198        
199    img = img.resize((int(BASE_WIDTH/2), int(float(img.size[1]) * (BASE_WIDTH/2) / img.size[0])))
200    
201    if img.mode in ("RGBA", "P"):
202        img = img.convert("RGB")
203    
204    return img
205
206def text_effect(text: str, img: Image):
207    LETTER_SPACING = 1
208    LINE_SPACING = 3
209    STROKE_WIDTH = 1
210    STROKE_FILL = (0, 0, 0)
211    FONT_BASE = 75
212    MARGIN = 10
213    LINE_WIDTH = 20
214    
215    img = img.resize((BASE_WIDTH, int(img.size[1] * float(BASE_WIDTH / img.size[0]))))
216    
217    text = textwrap.wrap(text, width=LINE_WIDTH)
218    if text == []:
219        return
220
221    font = ImageFont.truetype(font=ARIAL_FONT_FILE, size=FONT_BASE)
222    
223    img_width, img_height = img.size
224    d = ImageDraw.Draw(img)
225    
226    _, _, max_txt_width, txt_height = d.textbbox((0, 0), text[0], font=font)
227    
228    for line in text:
229        temp = int(font.getlength(line))
230        if temp > max_txt_width:
231            max_txt_width = temp
232    
233    
234    total_height = (txt_height + LINE_SPACING) * len(text)
235    
236    y_inf = 0
237    y_sup = img_height - total_height
238    x_inf = 0
239    x_sup = img_width - max_txt_width - 5
240    
241    fill = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
242    x = random.randint(x_inf, x_sup)
243    y = random.randint(y_inf, y_sup)
244    for i in range(len(text)):
245        _draw_line(d=d, x=x, y=y, line=text[i], font=font, letter_spacing=LETTER_SPACING, fill=fill, stroke_width=STROKE_WIDTH, stroke_fill=STROKE_FILL)
246
247        y += txt_height + LINE_SPACING
248        
249    img = img.resize((int(BASE_WIDTH/2), int(float(img.size[1]) * (BASE_WIDTH/2) / img.size[0])))
250    
251    if img.mode in ("RGBA", "P"):
252        img = img.convert("RGB")
253    
254    return img
255
256def test_multiple(text, effect, modifier=""):
257        imgs = os.listdir("test")
258        for i in range(len(imgs)):
259            image = effect(text, Image.open(os.path.join("test", imgs[i])))
260            image.save(os.path.join("test_output", f'output{modifier}{i}.jpg'), optimize=True, quality=80)
261
262        print("Image test successful")
263
264def test(text, effect, modifier=""):
265        image = effect(text, Image.open("image.png"))
266        image.save('output.jpg', optimize=True, quality=80)
267
268        print("Image test successful")
269
270def main():
271    input_text = '''
272         Ho sodomizzato mio padre.
273
274Mi ha fatto venire in salotto (non c'era nessuno) et mi ha rimproverato perché faccio il neet a casa tutto il giorno.
275
276Di colpo,non só cosa mi abbia preso (di sicuro il fatto che non mi sia strofinato il pisello da 3 giorni),gli ho sculacciato il culone flaccido e gli ho detto che ero Io il nuovo papà in questa casa.Mi ha fissato negli occhi poi si é abbassato al livello del mio pantalone et lo scese.Mi tolse anche le mutandine sotto il mio sguardo scioccato ma non per tanto disgustato.
277
278Mi ha fatto un pompino strabiliante,il migliore mai ricevuto.Si é poi messo contro la poltrona e gli ho strappato il suo jean da obeso.L'ho sodomizzato come se non ci fosse un domani,persino quando spiavo i miei genitori mentre scopavano non gioii cosí tanto,era francamente magnifico.
279
280Mi ha appena inviato un messaggio,vuole il secondo round domani altrimenti mi caccia di casa,sono diventato il suo schiavo sessuale,ma mi piace.Dovrei chiedere alla mamma se vuole partecipate,sarebbe fico,anche se sarà difficile disseppellirla.
281'''
282    
283    test(input_text, wot_effect)
284    test_multiple(input_text, wot_effect)
285    #test_multiple(input_text, splash_effect, "_long")
286    
287if __name__ ==  "__main__":
288    main()