#!/usr/bin/env python # # Copyright 2011 Ville Rantanen # # this program is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . import sys,os import re import shutil import subprocess from optparse import OptionParser from math import ceil # (c) ville.rantanen@helsinki.fi webfilesearch=re.compile('.*index.html$|.*gallerystyle.css$|.*galleryscript.js$|.*descriptions.csv$',re.I) imagesearch=re.compile('.*\.jpg$|.*\.jpeg$|.*\.gif$|.*\.png$|.*\.svg$|.*\.pdf$',re.I) vectorsearch=re.compile('.*\.svg$|.*\.pdf$',re.I) excludepaths=re.compile('_med|_tn|\..*') doublequotes=re.compile('"') singlequotes=re.compile("'") stripquotes=re.compile('^"|"$') def getimagelist(path): ''' Returns a list of images matching the regex ''' list=os.listdir(path) imgs=[] for f in list: if (imagesearch.match(os.path.join(path,f))) and (os.path.isfile(os.path.join(path,f))): imgs.append(f) return imgs def getnonimagelist(path): ''' Returns a list of files not matching the image match regex ''' list=os.listdir(path) files=[] for f in list: if (not webfilesearch.match(os.path.join(path,f))) and (not imagesearch.match(os.path.join(path,f))) and (os.path.isfile(os.path.join(path,f))): files.append(f) files.sort() return files def getpathlist(path): ''' Returns a list of subfolders not matching the exclusion regex ''' list=os.listdir(path) paths=[] for d in list: if (not excludepaths.match(d)) and (os.path.isdir(os.path.join(path,d))): paths.append(d) return paths def createthumbs(path,list): ''' Runs imagemagick Convert to create medium sized and thumbnail images ''' if len(list)==0: return if not os.path.exists(os.path.join(path,'_tn')): os.mkdir(os.path.join(path,'_tn')) if not os.path.exists(os.path.join(path,'_med')): os.mkdir(os.path.join(path,'_med')) n=1 nsum=len(list) r=str(options.width) res=r+'x'+r+'>' for i in list: outmedium=os.path.join(path,'_med','med_'+i+'.jpg') outthumb=os.path.join(path,'_tn','tn_'+i+'.jpg') inpath=os.path.join(path,i) if (options.force) and os.path.exists(outmedium): os.unlink(outmedium) if (options.force) and os.path.exists(outthumb): os.unlink(outthumb) if (not os.path.exists(outmedium)): print('Medium.. '+i+' '+str(n)+'/'+str(nsum)) create_medium_bitmap(inpath,outmedium,r,link=options.link,vector=vectorsearch.match(i)) if (not os.path.exists(outthumb)): print('Thumbnail.. '+i+' '+str(n)+'/'+str(nsum)) create_thumb_bitmap(outmedium,outthumb,vector=vectorsearch.match(i)) n+=1 return def create_medium_bitmap(infile,outfile,r,link=False,vector=False): if link: os.symlink(infile,outfile) return res=r+'x'+r+'>' if vector: convargs=['convert','-density','300x300',infile+'[0]','-background','white','-flatten','-resize',res,'-quality','97',outfile] else: convargs=['convert','-define','jpeg:size='+r+'x'+r,infile+'[0]','-background','white','-flatten','-resize',res,'-quality','85',outfile] convp=subprocess.call(convargs) return def create_thumb_bitmap(infile,outfile,vector=False): if vector: convargs=['convert','-density','300x300',infile,'-background','white','-flatten','-thumbnail','90x90^','-gravity','Center','-crop','90x90+0+0','+repage','-quality','75',outfile] else: convargs=['convert','-define','jpeg:size=300x300',infile,'-background','white','-flatten','-thumbnail','90x90^','-gravity','Center','-crop','90x90+0+0','+repage','-quality','75',outfile] convp=subprocess.call(convargs) return def cleanthumbs(path): ''' clears _med and _tn for unused thumbs ''' print('clearing unused thumbs...') if os.path.exists(os.path.join(path,'_tn')): clearfolder(path,os.path.join(path,'_tn'),re.compile("(^tn_)(.*)(.jpg)")) if os.path.exists(os.path.join(path,'_med')): clearfolder(path,os.path.join(path,'_med'),re.compile("(^med_)(.*)(.jpg)")) return def clearfolder(path,tnpath,regex): ''' clears given folder ''' list=getimagelist(tnpath) for i in list: f=regex.match(i) try: if not os.path.exists(os.path.join(path,f.group(2))): print('removing '+i) os.remove(os.path.join(tnpath,i)) except: continue return def traverse(path): ''' The recursive main function to create the thumbs and seek sub folders ''' print(path) pathlist=getpathlist(path) imagelist=getimagelist(path) print(str(len(pathlist))+' paths') print(str(len(imagelist))+' images') if options.clean: cleanthumbs(path) createthumbs(path,imagelist) if options.recursive: for p in pathlist: traverse(os.path.join(path,p)) return def execute(): ''' Main execution ''' usage='''Usage: %prog [options] folder folder is the root folder of the image album.''' parser=OptionParser(usage=usage) parser.add_option("-f",action="store_true",dest="force",default=False, help="Force regeneration of thumbnails and medium sized") parser.add_option("-c",action="store_true",dest="clean",default=False, help="Clean unused thumbnails") parser.add_option("-l",action="store_true",dest="link",default=False, help="Create symbolic link as medium size image instead of downscaling one.") parser.add_option("-r",action="store_true",dest="recursive",default=False, help="Recurse in to subfolders") parser.add_option("-w",type="int",dest="width",default=850, help="Medium image size") global options (options,args)=parser.parse_args() if len(args) != 1: parser.error("incorrect number of arguments") startpath=os.path.abspath(args[0]) traverse(startpath) return execute() sys.exit(0)