tnew xkcd in python; adds title and alt text - scripts - random scripts
 (HTM) git clone git://parazyd.org/scripts.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
 (DIR) commit fa368d5febabb1d62dce55965412d02cf80220aa
 (DIR) parent b8530370f2509a29ab8fb68b9d2ef8a5f588db75
 (HTM) Author: parazyd <parazyd@dyne.org>
       Date:   Fri, 17 Feb 2017 00:47:06 +0100
       
       new xkcd in python; adds title and alt text
       
       Diffstat:
         C xkcd -> obsolete/xkcd               |       0 
         M xkcd                                |     130 +++++++++++++++++++++++++++++--
       
       2 files changed, 125 insertions(+), 5 deletions(-)
       ---
 (DIR) diff --git a/xkcd b/obsolete/xkcd
 (DIR) diff --git a/xkcd b/xkcd
       t@@ -1,7 +1,127 @@
       -#!/bin/sh
       +#!/usr/bin/env python
       +#
       +# grab a random xkcd comic, append title and alttext, and save to a dir
        
       -tot="$(curl -s https://xkcd.com/info.0.json | jq '.num')"
       -[ -n "$tot" ] || exit 1
       -rnd="$(shuf -i 1-${tot} -n 1)"
       +from PIL import Image, ImageDraw, ImageFont
       +from requests import get
       +from random import randrange
       +from textwrap import wrap
       +from json import loads
       +from re import search
       +import os
        
       -curl -s https://xkcd.com/$rnd/info.0.json | jq '.img' | xargs feh
       +download_dir = os.environ['HOME']+'/xkcd/'
       +title_fontsize = 28
       +alt_fontsize = 18
       +line_offset = 10
       +
       +def add_text(image, title, alt, tfont=download_dir+'xkcd.ttf',
       +             afont=download_dir+'xkcd.ttf'):
       +    try:
       +        img = Image.open(image)
       +    except OSError:
       +        return
       +
       +    #tfont = ImageFont.truetype(download_dir+'xkcd.ttf', title_fontsize)
       +    #afont = ImageFont.truetype(download_dir+'xkcd.ttf', alt_fontsize)
       +    tfont = ImageFont.truetype(tfont, title_fontsize)
       +    afont = ImageFont.truetype(afont, alt_fontsize)
       +
       +    twidth, theight = tfont.getsize(title)
       +    awidth, aheight = afont.getsize(alt)
       +    line_padding = 5
       +    draw = ImageDraw.Draw(img)
       +    lines = text_wrap(tfont, title, img.size[0])
       +    lheight = max([tfont.getsize(" ".join(i))[1] for i in lines])
       +    lheight_total = (lheight+line_padding)*(len(lines))+line_padding*4
       +    title_crop = (0, -1*lheight_total, img.size[0], img.size[1])
       +    img = img.crop(title_crop)
       +    w, h = img.size
       +    old_h = h
       +    draw = ImageDraw.Draw(img)
       +    lheight_total = line_padding
       +    for i in lines:
       +        draw.text((w/2-tfont.getsize(" ".join(i))[0]/2,
       +                   lheight_total),
       +                   " ".join(i),
       +                   font=tfont,
       +                   fill=0xffffff)
       +        lheight_total += lheight + line_padding
       +    lheight_total = line_padding
       +    lines = text_wrap(afont, alt, w)
       +    lheight = max([afont.getsize(" ".join(i))[1] for i in lines])
       +    lheight_total = lheight*len(lines)
       +    alt_crop = (0, 0, img.size[0],
       +                img.size[1]+lheight_total+(len(lines)+3)*line_padding)
       +    img = img.crop(alt_crop)
       +    draw = ImageDraw.Draw(img)
       +    lheight_total = old_h + line_padding
       +    for i in lines:
       +        if not i:
       +            continue
       +        draw.text((w/2-afont.getsize(" ".join(i))[0]/2,
       +                   lheight_total),
       +                   " ".join(i),
       +                   font=afont,
       +                   fill=0xffffff)
       +        lheight_total += lheight + line_padding
       +
       +    img.save(image)
       +    print(image)
       +    exit(0)
       +
       +def text_wrap(font, text, image_width, i=0):
       +    lines = [[]]
       +    text = text.split(" ")
       +    while len(text) > 0:
       +        while len(text) > 0 \
       +            and font.getsize(" ".join(lines[i]))[0] < image_width:
       +            if font.getsize(text[0]+" "+" ".join(lines[i]))[0] > image_width * 0.95:
       +                if len(lines[i]) == 0:
       +                    text[0] = text[0][:len(text[0])//2+1] \
       +                        + " " + text[0][:len(text[0])//2+1:]
       +                    text = text[0].split(" ") + text[1:]
       +                break
       +            lines[i].append(text[0])
       +            text.pop(0)
       +        i += 1
       +        lines.append([])
       +    sub = []
       +    for e, i in enumerate(lines):
       +        if font.getsize(" ".join(lines[e]))[0] > image_width:
       +            temp_str = ""
       +            for c in "".join(i):
       +                if font.getsize(temp_str+c)[0] > image_width:
       +                    lines[i] = lines[i][:len(lines[i])//2] \
       +                        + lines[i][len(lines[i])//2:]
       +                    break
       +                temp_str += c
       +            sub.append(temp_str)
       +            del lines[e]
       +    lines = [i for i in lines if len(i) != 0]
       +    for c in [i for i in sub if len(i) != 0]:
       +        lines.append(c)
       +    return lines
       +
       +def main():
       +    info = get("https://xkcd.com/info.0.json").json()
       +    if not info:
       +        exit(1)
       +    info = get("https://xkcd.com/"+str(randrange(1, info['num']) + 1)+"/info.0.json").json()
       +
       +    title = info['safe_title']
       +    alt   = info['alt']
       +    num   = str(info['num'])
       +
       +    image = num+search("\.([a-z])+$", info['img']).group()
       +
       +    with open(download_dir+image, 'wb') as image_file:
       +        req = get(info['img'], stream=True)
       +        for block in req.iter_content(1024):
       +            if block:
       +                image_file.write(block)
       +                image_file.flush()
       +        if not search("\.gif", info['img']):
       +            add_text(download_dir+image, title, alt)
       +
       +main()