用shell脚本批量压缩图片

现在我们网站对用户上传的图片生成了三种规格大小的图片:

一种宽最大590,高按比例适应,如 ./2012/20121107/4668/201211071252339737_middle.jpg
一种宽最大250,高按比例适应,如 ./2012/20121107/4668/201211071252339737_small.jpg
还有就是原图,如 ./2012/20121107/4668/201211071252339737.jpg。

现在因为做了手机端的APP,要求再生成两种比较小规格的图片给手机APP显示用。两种如下规格:

宽x高 = 200×300,也就是宽最大不超过200,且高最大不超过300,在此条件下按比例缩放。
宽x高 = 150×150。

在用php压缩的时候,需要计算高宽比,也就是需要看到底按宽还是高来等比。

这里需要解决的问题就是,如何对以前用户上传的图片进行处理,生成这两种规格的图片。

我先是尝试用php,写php页面,然后curl调用。这样写代码很快,但是当我跑了一台机器后,发现一些问题。

1、有的图片很大,压缩耗时,甚至超过了php脚本执行的最大时间,当然可以设置加长php脚本最大执行时间,但改那么多服务器的配置不是很合适。以前我就是减少一次php执行时,处理的数据量,如一次只处理10张图片。但是这样几十W图片,一次处理10张,那么调用多少次页面啊!感觉不爽。

2、有时候,图片后缀是JPG,但是实际上却是PNG格式(之前上传图片逻辑那出BUG造成的,之前直接用上传文件的后缀做后缀保存文件,汗)。还有GIF图片不作压缩,还得判断。

还有php本身的特点,不适合做这样大型、非常耗时的处理,所以后来我放弃用php继续处理。转向其它实现思路,我首先想到了用python,python实现起来也快,但我们的服务器上没装python运行环境,还得装PIL库,我自己去装也就还好,不废什么事,但权限问题,还得叫我们的运维装,估计运维也烦,我也不想麻烦别人,所以最后用shell脚本实现了,而且代码量更少。

下面是实现的shell代码resize_for_mobile.sh:

#!/bin/bash
#encoding=utf-8

#convert 命令
CONVERT_PATH='convert'

# convert 命令的geometry,按200x300比例,其中宽高最大都不超过200和300
# http://www.imagemagick.org/script/command-line-processing.php#geometry
SIZE_S1='200x300>'
SIZE_S2='150x150>'

LOG=''
LOGFILE='resize_for_mobile.log'
#find 匹配文件名,you need to specify .*/ in the beginning because find matches the whole path
#过滤掉_small.jpg  _middle.jpg _s1.jpg _s2.jpg等,只取全数字+后缀的文件
for imgfile in `find . -regextype sed -regex ".*/.*[^s][0-9]\..*"`; do
    LOG="${LOG} ${imgfile}"
    dir=`echo ${imgfile} | awk -F '.' '{print $2}'`
    name=`echo ${imgfile} | awk -F '.' '{print $3}'`
    s1name=.${dir}_s1.${name}
    s2name=.${dir}_s2.${name}
    if file ${imgfile} | grep "GIF"; then
        LOG="${LOG} 不处理GIF文件"
    else
        if [ -f ${s1name} ]; then
            LOG="${LOG} ${s1name} 已存在 "
        else
            ${CONVERT_PATH} ${imgfile} -quality 70 -resize ${SIZE_S1} ${s1name}
        fi
        if [ -f ${s2name} ]; then
            LOG="${LOG} ${s2name} 已存在 "
        else
            ${CONVERT_PATH} ${imgfile} -quality 70 -resize ${SIZE_S2} ${s2name}
        fi
    fi
    echo -e "${LOG}\n" >> ${LOGFILE}
done

压缩图片部分主要用到了 imagemagick 的 convert 命令,看其文档找到了满足我需要的用法。
还有就是查看文件的mime类型

file -ib 20121124094332257.gif