#!/usr/bin/env python import glob import os import os.path import re import sys import string class PhotoDir: imageFileMatch = re.compile('.*\.(jpg|jpeg|gif|png)$', re.I) thumbSize = (133, 100) imageSize = (640, 640) def __init__(self, srcdir, destdir): if (not os.access(srcdir, os.R_OK)): raise OSError, "Cannot read from '" + srcdir + "'" if (not os.path.exists(destdir)): os.mkdir(destdir) if (not os.access(destdir, os.W_OK)): raise OSError, "Cannot write to '" + destdir + "'" self.__destdir = destdir self.__srcdir = srcdir self.__children = [] for entry in os.listdir(self.__srcdir): if (os.path.isdir(os.path.join(srcdir, entry)) and entry != "thm" and entry != "img"): self.__children.append(PhotoDir(os.path.join(srcdir, entry), os.path.join(destdir, self.__rename(entry))) ) def prepare (self): "Prepare the destination tree." print " |-- Preparing", self.__destdir for path in ["img", "thm"]: path = os.path.join(self.__destdir, path) if (not os.path.isdir(path)): os.mkdir(path) for child in self.__children: PhotoDir.prepare(child) def create(self): "Create the album." print "Creating", self.__destdir prepared = False for path in os.listdir(self.__srcdir): if (os.path.isfile(os.path.join(self.__srcdir, path)) and self.imageFileMatch.search(path)): if (not prepared): self.prepare() prepared = True self.__doFile(path) for child in self.__children: child.create() def __doFile(self, path): print " |--", path src = os.path.join(self.__srcdir, path) newname = self.__rename(path) thm = os.path.join(self.__destdir, os.path.join("thm", newname)) img = os.path.join(self.__destdir, os.path.join("img", newname)) size = self.__getSize(src) scale = self.__calcScale(size) fd = lambda (x, y): str(int(x)) + "x" + str(int(y)) #print ("convert -verbose %s -scale %s> -crop %s %s[0]" % (src, fd(scale), fd(self.thumbSize), thm)) os.spawnlp(os.P_WAIT, "convert", "-verbose" , src, "-scale", fd(scale) + ">", "-crop", fd(self.thumbSize), thm + "[0]") # Imagemagick can make a sequence of files (even though I told it not to...) if (os.path.isfile(thm[:-4] + "-0" + thm[-4:])): os.rename(thm[:-4] + "-0" + thm[-4:], thm) for file in glob.glob(thm[:-4] + '-*' + thm[-4:]): os.unlink(file) os.spawnlp(os.P_WAIT, "convert", "-verbose", src, "-scale", fd(self.imageSize) + ">", img) def __rename(self, path): return string.lower(re.sub(" ", "_", path)) def __getSize(self, path): pipe = os.popen("identify -format '%wx%h' '" + path + "'") line = pipe.readline() pipe.close() geom = re.compile('(\d+)x(\d+)\n').match(line) return (float(geom.group(1)), float(geom.group(2))) def __calcScale(self, size): dx = size[0] / self.thumbSize[0] dy = size[1] / self.thumbSize[1] if (dx > dy): return (size[0], 100.0) else: return (133.0, size[1]) def usage(): print("Stefano Rivera's Photograph Album Generator") print("Usage: " + sys.argv[0] + " src-dir dest-dir\n") sys.exit() ####################################### # Main Code # Check arguments if (len(sys.argv) != 3 or not os.path.isdir(sys.argv[1])): usage() # Create Object x = PhotoDir(sys.argv[1], sys.argv[2]) # GO GO GO! x.create()