Move updatewrsledruncache.py to scripts folder.
[philipp/winterrodeln/wrpylib.git] / scripts / createthumbnails.py
1 #!/usr/bin/python2.7
2 # -*- coding: iso-8859-15 -*-
3 """Creates the image thumbnails or icons for sledruns to be used in the sledmap application.
4 Can be used in a python session or at the command line.
5
6 usage: createthumbnails.py [-h] {thumbnail,icon} inifile [inifile ...]
7
8 Creates the image thumbnails or icons for sledruns to be used in the sledmap
9 application.
10
11 positional arguments:
12   {thumbnail,icon}  thumbnails or icons?
13   inifile           inifile.ini (See:
14                     http://www.winterrodeln.org/trac/wiki/ConfigIni)
15
16 optional arguments:
17   -h, --help        show this help message and exit
18
19
20 Command line usage:
21 $ export LANG=de_AT.utf8
22 $ export LC_CTYPE=de_AT.utf8
23 $ python createthumbnails.py thumbnail inifile1.ini ...
24 $ # or:
25 $ python createthumbnails.py icon inifile1.ini ...
26
27 One or more .ini configuration files can be given.
28 At the end, the following entries have to be present:
29
30     [mysql]
31     host=localhost
32     dbname=philipp_winterrodeln_wiki
33     user_name=philipp_www
34     user_pass=YYYYYY
35
36     [mediawiki]
37     imagedir=/home/philipp/www/winterrodeln.org/mediawiki/images
38
39     [sledmap]
40     sledrunimagedir=/home/philipp/www/winterrodeln.org/karte/mediawiki_images
41     sledrunicondir=/home/philipp/www/winterrodeln.org/karte/mediawiki_icons
42
43 """
44 from __future__ import division
45 import argparse
46 import sys
47 import os
48 import ConfigParser
49 import hashlib
50 import MySQLdb
51 from PIL import Image, ImageFilter
52
53
54 def image_to_icon(im, width, height):
55     """The icon will have a size of width times height and contains a centered sub-part of the image."""
56     if im.size[0]/float(width) > im.size[1]/float(height):
57         # scale image to height
58         im.thumbnail((int(round(im.size[0]*im.size[1]/height)), height), Image.ANTIALIAS)
59         # crop image (left, upper, right (excl), lower (excl))
60         left = (im.size[0]-width)//2
61         im = im.crop((left, 0, left+width, height))
62     else:
63         # scale image to width
64         im.thumbnail((width, int(round(im.size[1]*im.size[0]/width))), Image.ANTIALIAS)
65         # crop image (left, upper, right (excl), lower (excl))
66         upper = (im.size[1]-height)//2
67         im = im.crop((0, upper, width, upper+height))
68     # sharpen
69     im = im.filter(ImageFilter.SHARPEN)
70     return im
71
72
73 def image_to_thumbnail(im, width, height):
74     """The thumbnail will have a equal or smaller width and height as given. The aspect ratio stays the same."""
75     im.thumbnail((width, height), Image.ANTIALIAS)
76     im = im.filter(ImageFilter.SHARPEN)
77     return im
78
79
80 def update_image_dir(mcon, mediawiki_image_dir, dest_dir, image_function, ignore_existing=True):
81     """Takes all image names from the mysql database (mcon), reads it from mediawiki_image_dir, 
82     processed it as given in the image_function and stores it in the dest_dir with the original filename.
83     It does not delete the images that might be present in dest_dir, but overwrites the images with the 
84     same filenames.
85
86     :param mcon: mysql connection
87     :param mediawiki_image_dir: directory of the mediawiki image directory
88     :param dest_dir: output directory
89     :param image_function: python function that takes a PIL Image as parameter and returns a modified PIL Image.
90     :param ignore_existing: True (default) if already existing image file names in the dest dir should be ignored.
91     """
92     cu = mcon.cursor()
93     sql = "select image from wrsledruncache where image is not null order by image"
94     cu.execute(sql)
95     for image, in cu:
96         image = image.replace(u' ', u'_')
97         # Create md5sum out of the image filename
98         md5 = hashlib.md5()
99         md5.update(image.encode('UTF8'))
100         hd = md5.hexdigest()
101         # Build source and destination path names
102         source_file = os.path.join(mediawiki_image_dir, hd[0], hd[0:2], image)
103         dest_file = os.path.join(dest_dir, image)
104         if ignore_existing and os.path.exists(dest_file): continue
105         print(u'{0}...'.format(image))
106         im = Image.open(source_file)
107         im = image_function(im)
108         im.save(dest_file, "JPEG")
109
110
111 def update_image_dir_by_inifile(inifile, mode):
112     """ Same as update_image_dir but reads the arguments from an .ini file.
113
114     :param inifile: filename of an .ini file or a list of .ini files.
115     :param mode: 'thumbnail' or 'icon'
116     """
117     config = ConfigParser.SafeConfigParser()
118     config.read(inifile)
119
120     host = config.get('mysql', 'host')
121     dbname = config.get('mysql', 'dbname')
122     user = config.get('mysql', 'user_name')
123     passwd = config.get('mysql', 'user_pass')
124     mcon = MySQLdb.connect(host=host, db=dbname, user=user, passwd=passwd, charset='utf8')
125
126     mediawiki_image_dir = config.get('mediawiki', 'imagedir')
127     if mode == 'thumbnail':
128         dest_dir = config.get('sledmap', 'sledrunimagedir')
129         image_function = lambda img: image_to_thumbnail(img, 200, 200)
130     elif mode == 'icon':
131         dest_dir = config.get('sledmap', 'sledrunicondir')
132         image_function = lambda img: image_to_icon(img, 80, 80)
133     update_image_dir(mcon, mediawiki_image_dir, dest_dir, image_function)
134
135     mcon.close()
136
137
138 if __name__=='__main__':
139     parser = argparse.ArgumentParser(description='Creates the image thumbnails or icons for sledruns to be used in the sledmap application.')
140     parser.add_argument('type', choices=['thumbnail', 'icon'], help='thumbnails or icons?')
141     parser.add_argument('inifile', nargs='+', help='inifile.ini (See: http://www.winterrodeln.org/trac/wiki/ConfigIni)')
142     args = parser.parse_args()
143
144     update_image_dir_by_inifile(args.inifile, args.type)
145