Thumbnail generator.
[audio.git] / src / youtube / thumbnail.py
diff --git a/src/youtube/thumbnail.py b/src/youtube/thumbnail.py
new file mode 100644 (file)
index 0000000..3f67cac
--- /dev/null
@@ -0,0 +1,68 @@
+import yaml
+from PIL import Image, ImageDraw, ImageFont
+
+
+def drawbox(img, d, context, get_font_path):
+    for version in d['versions']:
+        if draw_version(img, version, context, get_font_path):
+            break
+
+
+def split_to_lines(text, draw, font, max_width):
+    words = text.split()
+    current = ''
+    while words:
+        new_words = []
+        new_words.append(words.pop(0))
+        while len(new_words[-1]) == 1 and words:
+            new_words.append(words.pop(0))
+        new_words = ' '.join(new_words)
+        new_line = ' '.join([current, new_words]).strip()
+        width = draw.textsize(new_line, font=font)[0]
+        if width > max_width:
+            yield current
+            current = new_words
+        else:
+            current = new_line
+    if current:
+        yield current
+
+        
+def draw_version(img, d, context, get_font_path):
+    # todo: do this in a subimg
+    newimg = Image.new(
+        'RGBA',
+        (
+            img.size[0] - d.get('x', 0),
+            d.get('max-height', img.size[1] - d.get('y', 0)),
+        )
+    )
+
+    draw = ImageDraw.Draw(newimg)
+    cursor = 0
+    for item in d['items']:
+        if item.get('vskip'):
+            cursor += item['vskip']
+        text = item['text'].format(**context)
+        if item.get('uppercase'):
+            text = text.upper()
+        font = ImageFont.truetype(get_font_path(item['font-family']), item['font-size'])
+        max_width = item.get('max-width', newimg.size[0])
+
+        for line in split_to_lines(text, draw, font, max_width):
+            realheight = draw.textsize(line, font=font)[1]
+            if cursor + realheight > newimg.size[1]:
+                return False
+            print('x', draw.text((0, cursor), line, font=font, fill=item.get('color')))
+            cursor += item['line-height']
+
+    img.paste(newimg, (d.get('x', 0), d.get('y', 0)), newimg)
+    return True
+
+
+def create_thumbnail(background_path, defn, context, get_font_path):
+    img = Image.open(background_path)
+    d = yaml.load(defn)
+    for boxdef in d['boxes']:
+        drawbox(img, boxdef, context, get_font_path)
+    return img