现在我们网站对用户上传的图片生成了三种规格大小的图片:
一种宽最大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