117 lines
4.5 KiB
Python
117 lines
4.5 KiB
Python
import logging
|
|
import os
|
|
import re
|
|
import textwrap
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
def scale_box(inbox, imgsize):
|
|
(i1x, i1y, i2x, i2y) = inbox
|
|
(w, h) = imgsize
|
|
return (i1x*w, i1y*h,
|
|
i2x*w, i2y*h)
|
|
|
|
def max_size(draw, inbox, text, font, size):
|
|
anchor='lt'
|
|
if '\n' in text:
|
|
anchor=None
|
|
f = ImageFont.truetype(font, size)
|
|
(i1x, i1y, i2x, i2y) = inbox
|
|
(b1x, b1y, b2x, b2y) = draw.textbbox((i1x, i1y), text,
|
|
font=f, anchor=anchor)
|
|
if (b1x < i1x or b1y < i1y or
|
|
b2x > i2x or b2y > i2y):
|
|
return max_size(draw, inbox, text, font, size-5)
|
|
return size
|
|
|
|
def fix_outliers(text):
|
|
modifiers = [('[ÖQ]', 'O'),
|
|
('[ÅÄ]', 'A'),
|
|
('[yqpg]', 'u'),
|
|
('j', 'i')]
|
|
for (pat, rep) in modifiers:
|
|
text = re.sub(pat, rep, text)
|
|
return text
|
|
|
|
|
|
class Thumbnailer:
|
|
def __init__(self, config, ldap):
|
|
self.base = config['base']
|
|
self.fill = config['textcolor']
|
|
self.ldap = ldap
|
|
self.logger = logging.getLogger('play-daemon')
|
|
self.thumbname = 'thumb.png'
|
|
self.font = 'verdana.ttf'
|
|
self.titlebox = (1/8, 0.4,
|
|
7/8, 0.5)
|
|
self.descrbox = (1/8, 0.55,
|
|
7/8, 0.8)
|
|
|
|
def create_if_missing(self, package):
|
|
if not package['thumb']:
|
|
title = package['title']['sv']
|
|
description = package['description']
|
|
courses = ', '.join(package['courses'])
|
|
presenters = ', '.join([self.ldap.get_name(uid)
|
|
for uid in package['presenters']])
|
|
extras = []
|
|
if courses:
|
|
extras.append(courses)
|
|
if presenters:
|
|
extras.append(presenters)
|
|
extra = ': '.join(extras)
|
|
workbase = package['workbase']
|
|
|
|
pres_id = package['id']
|
|
self.logger.debug('%s - Creating thumbnail', pres_id)
|
|
self.logger.debug('%s - Title: %s', pres_id, title)
|
|
self.logger.debug('%s - Description: %s', pres_id, description)
|
|
self.logger.debug('%s - Extra: %s', pres_id, extra)
|
|
package['thumb'] = self.make_thumb(workbase,
|
|
title, description, extra)
|
|
self.logger.info('%s - Thumbnail created', pres_id)
|
|
return package
|
|
|
|
def make_thumb(self, workbase, title, description, extra):
|
|
with Image.open(self.base) as im:
|
|
draw = ImageDraw.Draw(im)
|
|
|
|
# Size and draw title
|
|
s_titlebox = scale_box(self.titlebox, im.size)
|
|
(t1x, t1y, t2x, t2y) = s_titlebox
|
|
title_size = max_size(draw, s_titlebox, fix_outliers(title),
|
|
self.font, 140)
|
|
draw.text((t1x, t2y), title, fill=self.fill, anchor='ls',
|
|
font=ImageFont.truetype(self.font, title_size))
|
|
|
|
# Size and draw description
|
|
s_descrbox = scale_box(self.descrbox, im.size)
|
|
(d1x, d1y, d2x, d2y) = s_descrbox
|
|
descr = textwrap.fill(description)
|
|
descr_size = max_size(draw, s_descrbox, descr, self.font, 75)
|
|
f = ImageFont.truetype(self.font, descr_size)
|
|
draw.multiline_text((d1x, d1y), descr, fill=self.fill, font=f)
|
|
|
|
# Size and draw extra
|
|
if extra:
|
|
# Get effective size of the description text
|
|
(b1x, b1y, b2x, b2y) = draw.textbbox((d1x, d1y),
|
|
descr,
|
|
font=f)
|
|
# Create a preliminary bounding box for extra
|
|
extrabox = (d1x, b2y,
|
|
d2x, im.height)
|
|
# Make sure the text fits in the box
|
|
extra_size = max_size(draw, extrabox, extra,
|
|
self.font, 50)
|
|
# Offset the extra box by one line height
|
|
extrabox = (extrabox[0], extrabox[1] + extra_size,
|
|
extrabox[2], extrabox[3])
|
|
(p1x, p1y, p2x, p2y) = extrabox
|
|
f = ImageFont.truetype(self.font, extra_size)
|
|
# Draw it
|
|
draw.text((p1x, p1y), extra, fill=self.fill,
|
|
font=f, anchor='lt')
|
|
|
|
im.save(os.path.join(workbase, self.thumbname))
|
|
return self.thumbname
|