42e8070c29996fcab42b8e6f25fb11f0f3e8edb1
[audio.git] / src / youtube / thumbnail.py
1 import yaml
2 from PIL import Image, ImageDraw, ImageFont
3
4
5 def drawbox(img, d, context, get_font_path):
6     for version in d['versions']:
7         if draw_version(img, version, context, get_font_path):
8             break
9
10
11 def split_to_lines(text, draw, font, max_width):
12     words = text.split()
13     current = ''
14     while words:
15         new_words = []
16         new_words.append(words.pop(0))
17         while len(new_words[-1]) == 1 and words:
18             new_words.append(words.pop(0))
19         new_words = ' '.join(new_words)
20         new_line = ' '.join([current, new_words]).strip()
21         width = draw.textsize(new_line, font=font)[0]
22         if width > max_width:
23             yield current
24             current = new_words
25         else:
26             current = new_line
27     if current:
28         yield current
29
30         
31 def draw_version(img, d, context, get_font_path):
32     # todo: do this in a subimg
33     newimg = Image.new(
34         'RGBA',
35         (
36             img.size[0] - d.get('x', 0),
37             d.get('max-height', img.size[1] - d.get('y', 0)),
38         )
39     )
40
41     draw = ImageDraw.Draw(newimg)
42     cursor = 0
43     for item in d['items']:
44         if item.get('vskip'):
45             cursor += item['vskip']
46         text = item['text'].format(**context)
47         if not text:
48             continue
49         if item.get('uppercase'):
50             text = text.upper()
51         font = ImageFont.truetype(get_font_path(item['font-family']), item['font-size'])
52         max_width = item.get('max-width', newimg.size[0])
53
54         for line in split_to_lines(text, draw, font, max_width):
55             realheight = draw.textsize(line, font=font)[1]
56             if cursor + realheight > newimg.size[1]:
57                 return False
58             draw.text((0, cursor), line, font=font, fill=item.get('color'))
59             cursor += item['line-height']
60
61     img.paste(newimg, (d.get('x', 0), d.get('y', 0)), newimg)
62     return True
63
64
65 def create_thumbnail(background_path, defn, context, get_font_path):
66     img = Image.open(background_path)
67     d = yaml.load(defn)
68     for boxdef in d['boxes']:
69         drawbox(img, boxdef, context, get_font_path)
70     return img