Skip to content

Instantly share code, notes, and snippets.

@jeffrey4l
Last active December 17, 2015 21:59
Show Gist options
  • Save jeffrey4l/5678793 to your computer and use it in GitHub Desktop.
Save jeffrey4l/5678793 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
#-*- coding:utf-8 -*-
#Author: Lei Zhang <[email protected]>
import sys
import os
import signal
import argparse
from math import floor
from shutil import copyfile, rmtree
from traceback import print_exc
import multiprocessing
from multiprocessing import Pool
from cStringIO import StringIO
from PIL import Image
def log_status(func):
def _(src, dest, cfg):
ret = None
process = multiprocessing.current_process()
msg = StringIO()
msg.write('[%s-%s]convert %s...' % (process.name, process.pid, src))
try:
if not cfg.dry:
ret = func(src, dest, cfg)
except Exception, e:
msg.write('Error')
print_exc(e, msg)
print msg.getvalue()
else:
msg.write('Ok')
print msg.getvalue()
return ret
return _
def file_filter(filename):
file, ext = os.path.splitext(filename)
if ext.lower() in ('.jpg') and os.path.isfile(filename):
return True
return False
BASE=2000.0
def run(src, dest, cfg):
convert(src, dest, cfg)
@log_status
def convert(src, dest, cfg):
im = Image.open(src)
width, heigh = im.size
if min(width, heigh) < BASE:
copyfile(src, dest)
return
rate = min(width, heigh) / BASE
new_size = ( int(floor(width/rate)), int(floor(heigh/rate)))
resize_img = im.resize(new_size, Image.ANTIALIAS)
resize_img.save(dest, quality=98)
def mkdirs(path, clean=False):
if os.path.exists(path):
if not clean:
return
else:
rmtree(path)
os.makedirs(path)
def main(cfg):
pool = Pool(cfg.thread_num)
# handle Ctrl+C sinal
def handler(signum, frame):
pool.terminator()
signal.signal(signal.SIGINT, handler)
def callback(context, dirname, names):
pool = context['pool']
dest = os.path.abspath(context['cfg'].dest)
abssrc = os.path.abspath(cfg.src)
dirname = os.path.abspath(dirname)
dest = os.path.join(dest, dirname[len(abssrc)+1:])
if not cfg.dry:
mkdirs(dest)
for name in names:
src_full = os.path.join(dirname, name)
dest_full = os.path.join(dest, name)
if not file_filter(src_full):
break
pool.apply_async(run, (src_full, dest_full, cfg))
context = dict(pool=pool, cfg=cfg)
os.path.walk(cfg.src, callback, context)
pool.close()
pool.join()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='')
parser.add_argument('-n', '--dry-run', default=False, action="store_true",\
dest='dry')
parser.add_argument('-t', '--thread-nums', default=4, metavar='N', dest='thread_num')
parser.add_argument('src')
parser.add_argument('dest')
cfg = parser.parse_args(sys.argv[1:])
main(cfg)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment