| 1 | #!/usr/bin/python |
|---|
| 2 | # -*- coding: ISO-8859-1 -*- |
|---|
| 3 | |
|---|
| 4 | """ |
|---|
| 5 | makes thumbs with the PIL |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | Last commit info: |
|---|
| 9 | ---------------------------------- |
|---|
| 10 | $LastChangedDate$ |
|---|
| 11 | $Rev$ |
|---|
| 12 | $Author$ |
|---|
| 13 | |
|---|
| 14 | Created by Jens Diemer |
|---|
| 15 | |
|---|
| 16 | license: |
|---|
| 17 | GNU General Public License v2 or above |
|---|
| 18 | http://www.opensource.org/licenses/gpl-license.php |
|---|
| 19 | """ |
|---|
| 20 | |
|---|
| 21 | __version__= "$Rev$" |
|---|
| 22 | |
|---|
| 23 | |
|---|
| 24 | import sys, os, time, fnmatch, urllib, string |
|---|
| 25 | |
|---|
| 26 | |
|---|
| 27 | try: |
|---|
| 28 | import Image, ImageFont, ImageDraw |
|---|
| 29 | |
|---|
| 30 | # PIL's Fehler "Suspension not allowed here" work around: |
|---|
| 31 | # s. http://mail.python.org/pipermail/image-sig/1999-August/000816.html |
|---|
| 32 | import ImageFile |
|---|
| 33 | ImageFile.MAXBLOCK = 1000000 # default is 64k |
|---|
| 34 | except ImportError: |
|---|
| 35 | print "Import Error:" |
|---|
| 36 | print "You must install PIL, The Python Image Library" |
|---|
| 37 | print "http://www.pythonware.com/products/pil/index.htm" |
|---|
| 38 | sys.exit() |
|---|
| 39 | |
|---|
| 40 | |
|---|
| 41 | |
|---|
| 42 | class thumb_maker_cfg: |
|---|
| 43 | # Standardwerte |
|---|
| 44 | path_to_convert = os.getcwd() |
|---|
| 45 | path_output = path_to_convert |
|---|
| 46 | make_thumbs = True |
|---|
| 47 | thumb_size = (160, 120) |
|---|
| 48 | thumb_suffix = "_thumb" |
|---|
| 49 | |
|---|
| 50 | make_smaller = False |
|---|
| 51 | smaller_size = (640, 480) |
|---|
| 52 | suffix = "_WEB" |
|---|
| 53 | image_text = "" |
|---|
| 54 | text_color = "#000000" |
|---|
| 55 | |
|---|
| 56 | jpegQuality = 85 |
|---|
| 57 | |
|---|
| 58 | clean_filenames = True |
|---|
| 59 | |
|---|
| 60 | rename_rules = [ |
|---|
| 61 | (" ", "_"), |
|---|
| 62 | ("� "ae"), |
|---|
| 63 | ("�"oe"), |
|---|
| 64 | ("�e"), |
|---|
| 65 | ("�, "Ae"), |
|---|
| 66 | ("�, "Oe"), |
|---|
| 67 | ("�, "Ue"), |
|---|
| 68 | ("�, "ss"), |
|---|
| 69 | ] |
|---|
| 70 | |
|---|
| 71 | |
|---|
| 72 | |
|---|
| 73 | |
|---|
| 74 | class thumb_maker: |
|---|
| 75 | def __init__(self, cfg): |
|---|
| 76 | self.cfg = cfg |
|---|
| 77 | self.skip_file_pattern = [ |
|---|
| 78 | "*%s.*" % self.cfg.thumb_suffix, |
|---|
| 79 | "*%s.*" % self.cfg.suffix |
|---|
| 80 | ] |
|---|
| 81 | |
|---|
| 82 | def go(self): |
|---|
| 83 | """ Aktion starten """ |
|---|
| 84 | time_begin = time.time() |
|---|
| 85 | |
|---|
| 86 | if not os.path.isdir(self.cfg.path_output): |
|---|
| 87 | print "Make output dir '%s'..." % self.cfg.path_output, |
|---|
| 88 | try: |
|---|
| 89 | os.makedirs(self.cfg.path_output) |
|---|
| 90 | except Exception, e: |
|---|
| 91 | print "Error!" |
|---|
| 92 | print "Can't make ouput dir:", e |
|---|
| 93 | sys.exit() |
|---|
| 94 | else: |
|---|
| 95 | print "OK" |
|---|
| 96 | |
|---|
| 97 | print "work path:", self.cfg.path_to_convert |
|---|
| 98 | |
|---|
| 99 | for root,dirs,files in os.walk(self.cfg.path_to_convert): |
|---|
| 100 | print root |
|---|
| 101 | print "_"*80 |
|---|
| 102 | for file_name in files: |
|---|
| 103 | abs_file = os.path.join(self.cfg.path_to_convert, root, file_name) |
|---|
| 104 | |
|---|
| 105 | self.process_file(abs_file) |
|---|
| 106 | |
|---|
| 107 | print "-"*80 |
|---|
| 108 | print "all files converted in %0.2fsec." % (time.time() - time_begin) |
|---|
| 109 | |
|---|
| 110 | def process_file(self, abs_file): |
|---|
| 111 | path, im_name = os.path.split(abs_file) |
|---|
| 112 | print abs_file |
|---|
| 113 | try: |
|---|
| 114 | im_obj = Image.open(abs_file) |
|---|
| 115 | except IOError: |
|---|
| 116 | # Ist wohl kein Bild, oder unbekanntes Format |
|---|
| 117 | #~ print "Not a image, skip.\n" |
|---|
| 118 | return |
|---|
| 119 | except OverflowError, e: |
|---|
| 120 | print ">>> OverflowError: %s" % e |
|---|
| 121 | print "Not a picture ? (...%s)" % abs_file[10:] |
|---|
| 122 | print |
|---|
| 123 | return |
|---|
| 124 | |
|---|
| 125 | print "%-40s - %4s %12s %s" % ( |
|---|
| 126 | im_name, im_obj.format, im_obj.size, im_obj.mode |
|---|
| 127 | ) |
|---|
| 128 | |
|---|
| 129 | if self.cfg.clean_filenames == True: |
|---|
| 130 | # Dateinamen s�ern |
|---|
| 131 | im_name = self.clean_filename(im_name) |
|---|
| 132 | |
|---|
| 133 | # Kleinere Bilder f�eb erstellen |
|---|
| 134 | if self.cfg.make_smaller == True: |
|---|
| 135 | self.convert( |
|---|
| 136 | im_obj = im_obj, |
|---|
| 137 | im_path = self.cfg.path_output, |
|---|
| 138 | im_name = im_name, |
|---|
| 139 | suffix = self.cfg.suffix, |
|---|
| 140 | size = self.cfg.smaller_size, |
|---|
| 141 | text = self.cfg.image_text, |
|---|
| 142 | color = self.cfg.text_color, |
|---|
| 143 | ) |
|---|
| 144 | |
|---|
| 145 | # Thumbnails erstellen |
|---|
| 146 | if self.cfg.make_thumbs == True: |
|---|
| 147 | self.convert( |
|---|
| 148 | im_obj = im_obj, |
|---|
| 149 | im_path = self.cfg.path_output, |
|---|
| 150 | im_name = im_name, |
|---|
| 151 | suffix = self.cfg.thumb_suffix, |
|---|
| 152 | size = self.cfg.thumb_size, |
|---|
| 153 | ) |
|---|
| 154 | print "-"*3 |
|---|
| 155 | |
|---|
| 156 | def convert(self, |
|---|
| 157 | im_obj, # Das PIL-Image-Objekt |
|---|
| 158 | im_path,# Der Pfad in dem das neue Bild gespeichert werden soll |
|---|
| 159 | im_name,# Der vollst�ige Name der Source-Datei |
|---|
| 160 | suffix, # Der Anhang f� Namen |
|---|
| 161 | size, # Die max. gr�des Bildes als Tuple |
|---|
| 162 | text="",# Text der unten rechts ins Bild eingeblendet wird |
|---|
| 163 | color="#00000", # Textfarbe |
|---|
| 164 | ): |
|---|
| 165 | """ Rechnet das Bild kleiner und f�zu den Text """ |
|---|
| 166 | |
|---|
| 167 | name, ext = os.path.splitext(im_name) |
|---|
| 168 | out_name = name + suffix + ".jpg" |
|---|
| 169 | out_abs_name = os.path.join(im_path, out_name) |
|---|
| 170 | |
|---|
| 171 | for skip_pattern in self.skip_file_pattern: |
|---|
| 172 | if fnmatch.fnmatch(im_name, skip_pattern): |
|---|
| 173 | #~ print "Skip file." |
|---|
| 174 | return |
|---|
| 175 | |
|---|
| 176 | if os.path.isfile(out_abs_name): |
|---|
| 177 | print "File '%s' exists! Skip." % out_name |
|---|
| 178 | return |
|---|
| 179 | |
|---|
| 180 | print "resize (max %ix%i)..." % size, |
|---|
| 181 | try: |
|---|
| 182 | im_obj.thumbnail(size, Image.ANTIALIAS) |
|---|
| 183 | except Exception, e: |
|---|
| 184 | print ">>>Error: %s" % e |
|---|
| 185 | return |
|---|
| 186 | else: |
|---|
| 187 | print "OK, real size %ix%i" % im_obj.size |
|---|
| 188 | |
|---|
| 189 | if im_obj.mode!="RGB": |
|---|
| 190 | print "convert to RGB...", |
|---|
| 191 | im_obj = im_obj.convert("RGB") |
|---|
| 192 | print "OK" |
|---|
| 193 | |
|---|
| 194 | if text != "": |
|---|
| 195 | # unter Linux ganzen Pfad angeben: |
|---|
| 196 | font_obj = ImageFont.truetype('arial.ttf', 12) |
|---|
| 197 | ImageDraw.Draw(im_obj).text( |
|---|
| 198 | (10, 10), text, font=font_obj, fill=color |
|---|
| 199 | ) |
|---|
| 200 | |
|---|
| 201 | print "save '%s'..." % out_name, |
|---|
| 202 | try: |
|---|
| 203 | im_obj.save( |
|---|
| 204 | out_abs_name, "JPEG", quality=self.cfg.jpegQuality, |
|---|
| 205 | optimize=True, progressive=False |
|---|
| 206 | ) |
|---|
| 207 | except Exception, e: |
|---|
| 208 | print "ERROR:", e |
|---|
| 209 | else: |
|---|
| 210 | print "OK" |
|---|
| 211 | |
|---|
| 212 | def clean_filename(self, file_name): |
|---|
| 213 | """ Dateinamen f�eb s�ern """ |
|---|
| 214 | |
|---|
| 215 | if urllib.quote(file_name) == file_name: |
|---|
| 216 | # Gibt nix zu ersetzten! |
|---|
| 217 | return file_name |
|---|
| 218 | |
|---|
| 219 | fn, ext = os.path.splitext(file_name) |
|---|
| 220 | |
|---|
| 221 | for rule in self.cfg.rename_rules: |
|---|
| 222 | fn = fn.replace(rule[0], rule[1]) |
|---|
| 223 | |
|---|
| 224 | allowed_chars = string.ascii_letters + string.digits |
|---|
| 225 | allowed_chars += ".-_#" |
|---|
| 226 | |
|---|
| 227 | # Nur ASCII Zeichen erlauben und gleichzeitig trennen |
|---|
| 228 | parts = [""] |
|---|
| 229 | for char in fn: |
|---|
| 230 | if not char in allowed_chars: |
|---|
| 231 | parts.append("") |
|---|
| 232 | else: |
|---|
| 233 | parts[-1] += char |
|---|
| 234 | |
|---|
| 235 | # Erster Buchstabe immer gro�geschrieben |
|---|
| 236 | parts = [i[0].upper() + i[1:] for i in parts if i!=""] |
|---|
| 237 | fn = "".join(parts) |
|---|
| 238 | |
|---|
| 239 | return fn + ext |
|---|
| 240 | |
|---|
| 241 | |
|---|
| 242 | |
|---|
| 243 | if __name__ == "__main__": |
|---|
| 244 | thumb_maker_cfg.path_to_convert = r"D:\MyPics" |
|---|
| 245 | thumb_maker_cfg.make_smaller = True |
|---|
| 246 | #~ thumb_maker_cfg.make_smaller = False |
|---|
| 247 | thumb_maker_cfg.smaller_size = (960, 600) |
|---|
| 248 | thumb_maker_cfg.image_text = "Your image Text :)" |
|---|
| 249 | |
|---|
| 250 | thumb_maker(thumb_maker_cfg).go() |
|---|
| 251 | |
|---|
| 252 | |
|---|
| 253 | |
|---|
| 254 | |
|---|
| 255 | |
|---|
| 256 | |
|---|
| 257 | |
|---|
| 258 | |
|---|