#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os,traceback,sys
from multiprocessing import Pool


def pngOptimize(filenameAndPath):
	try:
		os.spawnlp(os.P_WAIT,'optipng','optipng','-o7','-q',filenameAndPath) 
		os.spawnlp(os.P_WAIT,'pngout','pngout','-q', filenameAndPath)
		return (True,filenameAndPath,os.getpid())
	except:
		return (False,filenameAndPath,os.getpid(),traceback.format_exc())

#this will shrink jpegs but potentially make them unreadable with photoshop use at your own risk or consider changing this code
#to save to a different filename (change the last parameter to the os.spawnlp function call to something like filenameAndPath + ".rescanned.jpeg"
def jpegOptimize(filenameAndPath):
	try:
		os.spawnlp(os.P_WAIT,'jpgcrush','jpgcrush',filenameAndPath) 
		return (True,filenameAndPath,os.getpid())
	except:
		return (False,filenameAndPath,os.getpid(),traceback.format_exc())



#a mapping of file extensions to functions which will act on those filetypes, file extensions must be in lower case.
fileOptimizers = {'png': pngOptimize,'jpg': jpegOptimize, 'jpeg':jpegOptimize}

def optimizeFile(filenamePathAndExt): 
	"for the given file run optimization programs associated with its type"
	filenameAndPath = filenamePathAndExt[0]
	Ext = filenamePathAndExt[1]
	try:
		#os.spawnlp(os.P_WAIT,'optipng','optipng','-o7','-q',filenameAndPath) 
		#os.spawnlp(os.P_WAIT,'pngout','pngout','-q', filenameAndPath)
		fileOptimizers[Ext](filenameAndPath)
		return (True,filenameAndPath,str(os.getpid()))
	except:
		return (False,filenameAndPath,os.getpid(),traceback.format_exc())
 
def generateInterestingFileListing(directory):
	"Recursively identify all files with file extenstions contained within the interestingFileTypes list"
	path = os.path.normpath(directory)
	if not os.path.isdir(path):
		raise Error, "Directory %s not found" % path

#we can use a for loop to continually get more data from a walk object until there is none left
	for currPath, currDirs, currFiles in os.walk(path):  
		for file in currFiles:
#no need for us to test and see if the file is a directory as fileGenerator is taking care of that for us. Also no need for recursion.
			extension = file.split(".")[-1].lower()
			if(extension in fileOptimizers.keys()):
				yield((currPath+"/"+file, extension))

def main(dir):
	"run associated optimization programs on all files within the given directory"
	pool = Pool() #we'll use the default number of processes
	results = pool.imap_unordered(optimizeFile,generateInterestingFileListing(dir))
	pool.close()
	pool.join()
	successes = []
	failures = []	
	for result in results:
		if result[0] == True:
			successes.append(result)
		else:
			failures.append(result)
	for success in successes:
		print success[1] + " optimized by "+str(success[2])
	for failure in failures:
		print failure[1] + " failed due to exception "+failure[3]+ " in process "+str(failure[2])	
if __name__ == "__main__":
	main(os.getcwd())
