Ross Wan's World!

Python, Ajax, PHP and Linux.

PIL: 批量生成缩略图

Posted by Ross Wan 于 2011/08/29

很久之前, 在 Python 2.5 下写了一个基于 PIL 的批量生成缩略图的脚本, 现将其修改移植到 Python 3下, 其中作了不少修改和完善:

#!bin/pyhton3
# coding=utf8

import os, sys, getopt, functools
from PIL import Image

# 源图片路径
SRC = os.getcwd()
# 目标保存图片的路径
DEST = os.getcwd()
# 缩略图保存的文件夹名称, 最终缩略图的保存路径为 sys.path.join(DEST, THUMB_DIR).
THUMB_DIR = '缩略图'
# 缩放比例
RATE = 0.15
# 缩略图的命名, 在原文件名前加上 THUMB_PREFFIX, 如"thumb_"
THUMB_PREFFIX = ''
# 是否递归搜索子文件夹
IS_RECURSIVE = True

def coroutine(func):
    """ 用于协程的装饰器 """
    @functools.wraps('func')
    def start(*args, **kwargs):
        g = func(*args, **kwargs)
        next(g)
        return g
    return start

@coroutine
def thumb(save_path, rate, thumb_preffix=''):
    img_exts = ('.jpg', '.jepg', '.gif', '.png', '.bmp')
    saved_filenames = set()
    repeatd_times = 0
    while 1:
        img_path = (yield)
        img_ext = os.path.splitext(img_path)[1].lower()
        if not img_ext in img_exts:
            continue
        print(img_path)
        save_filename = '%s%s%s' % (thumb_preffix, os.path.splitext(os.path.split(img_path)[1])[0], img_ext)
        if save_filename in saved_filenames:
            repeatd_times += 1
            save_filename = '%s_%s%s' % (os.path.splitext(save_filename)[0], repeatd_times, img_ext)
        img = Image.open(img_path)
        img.thumbnail((int(img.size[0]*rate), int(img.size[1]*rate)), 1)
        img.save(os.path.join(save_path, save_filename))
        saved_filenames.add(save_filename)
        print('%s %s' % ('Thumb', save_filename))

def process(src, func, is_recursive=True):
    files = []
    dirs = []
    for f in os.listdir(src):
        path = os.path.join(src, f)
        if os.path.isfile(path):
            files.append(path)
        elif is_recursive and os.path.isdir(path) and f.lower() not in ('缩略图', 'thumb', 'thumbs', 'thumbnail', 'thumbnails'):
            dirs.append(path)
    for path in files:
        func.send(path)
    for path in dirs:
        process(path, func, is_recursive)

if __name__ == '__main__':
    src, dest, thumb_dir, rate, thumb_preffix, is_recursive = SRC, DEST, THUMB_DIR, RATE, THUMB_PREFFIX, IS_RECURSIVE
    opts, args = getopt.getopt(sys.argv[1:], 'r:d:p:s')
    print(opts, args)
    for k,v in opts:
        if k == '-r':
            rate = float(v)
        elif k == '-d':
            thumb_dir = v
        elif k == '-p':
            thumb_preffix = v
        elif k == '-s':
            is_recursive = False
    if args:
        args.append(os.getcwd())
        src, dest = args[:2]

    print(src, dest, thumb_dir, rate, thumb_preffix, is_recursive)
    sys.exit()
    save_path = os.path.join(dest, thumb_dir)
    if not os.path.exists(save_path):
        os.makedirs(save_path)

    my_thumb = thumb(save_path, rate, thumb_preffix)
    process(src, my_thumb, is_recursive)
    print('\nDone!')
    input()

脚本依然是基于 PIL 的, 但目前 PIL 的官方还未发布兼容 Python 3 的 Windows 编译版, 幸运的是, 网上可以下载到非官方的编译版本:

http://www.lfd.uci.edu/~gohlke/pythonlibs/#pil

脚本默认递归搜索当前文件夹及子文件夹的图像文件, 然后将生成的缩略图文件放在当前文件夹的”缩略图”文件夹下.当然, 也可修改脚本的参数, 或者在命令行下指定参数:

python3 thumbnial_batch.py -r 0.5 -d ‘thumbs’ -p ‘thumb’ -s 源文件夹 目标文件夹

参数 -r: 指定压缩图片大小的比率;参数 -d: 指定保存缩略图的文件夹名称; 参数 -p: 指定生成的缩略图的文件名添加的前缀; 参数 -s: 只搜索源文件夹,不进行递归搜索子文件夹.
Have fun :>

留下评论