python 使用pngquant和ImageMagick批处理压缩png/jpg

最近闲着没事,大佬便分配个压缩图片的任务给我。于是,我就上网找寻相对需求而言最优的解决方案。

 初步实践后,得出结论:pngquant与ImageMagick各方面都符合需求。

各方法比对​​​​​​

 

ImageMagick下载地址 :http://www.imagemagick.org/script/download.php/
pngquant下载地址: http://pngquant.org/
我的是windows系统,所以选择下载windows版的。

pngquant下载

 

pngquant_window.zip解压后用到的是pngquant.exe。你可以把它添加进系统变量,也可直接放在.py文件的目录下调用。

ImageMagick则运行exe安装。一路next之后,安装完成。如果你是使用PyCharm编辑,且安装之前打开的话,需重启PyCharm才能调用'magick'命令。

准备工作都做好了,上代码。

#!/usr/bin/python
# coding=utf-8

import os
import time
import shutil
import math

# PYTHON 2.7

srcPath = r"./tsimg"
savePath = r"./pngquantImg1"

# 运行命令行
def runSystem(ossys):
    result = os.system(ossys)
    if result == 0:
        print(str(ossys) + ' success')
        return True
    else:
        print(str(ossys) + ' fail')
        return False


# 删除空文件夹
def delete_null_dir(dirr):
    if os.path.isdir(dirr):
        for p in os.listdir(dirr):
            d = os.path.join(dirr, p)
            if (os.path.isdir(d) == True):
                delete_null_dir(d)
    if not os.listdir(dirr):
        os.rmdir(dirr)

# pngqyant 参数:
# --ext new.png 新名字(不传就默认后缀加'-or8.png' 或 '-fs8.png') 好像不行 用 -o new.png 可以
# --quality min-max 指示pngquant使用满足或超过最大质量所需的最少颜色量
# --speed 速度/质量权衡从1(蛮力)到10(最快)。默认值为3。速度10的质量降低5%,但比默认速度快8倍。
# --iebug E6的解决方案,它只显示完全不透明的像素。pngquant将使几乎不透明的像素完全不透明,并避免创建新的透明颜色
# --version 将版本信息打印到stdout
# - 从stdin读取图像并将结果发送到stdout
# -- 停止处理参数。这允许使用以-开头的文件名。如果在脚本中使用pngquant,建议将其放在文件名之前:pngquant $OPTIONS -- "$FILE"
# 网上说的
# --force 参数无效,只要输出文件存在,就会报错,无视这个本用来指定覆写的参数
# --skip-if-larger 参数不正常,有时候生成文件明明比较小,也会被skip掉……

def usePngQuantAndImageMagickAPI(max_size):
    if os.path.exists(savePath):
        shutil.rmtree(savePath, True)
    print(savePath)

    os.mkdir(savePath)

    for n, f, file in os.walk(srcPath):
        if len(file) != 0:
            for i in file:
                filetotledir = os.path.join(n, i)
                temp_savePath = n.replace(srcPath, savePath)
                if not os.path.exists(temp_savePath):
                    os.makedirs(temp_savePath)
                filetotledir1 = os.path.join(temp_savePath, i)

                CompressImage(filetotledir, max_size, filetotledir1)  # 75
        else:
            continue

    delete_null_dir(savePath)

def CompressImage(image_name, max_size, replace_name=''):
    image_stat = os.stat(image_name)
    image_size = image_stat.st_size / 1024.0  # 计算KB
    print 'st_size:{0} image_size:{1}'.format(image_stat.st_size, image_size)

    global g_total
    global g_compress_size
    global png_array
    global jpg_array
    global g_pic_num
    global g_compress_pic_num

    if image_size > max_size and not '.meta' in image_name:
        compress_factor = max_size / image_size * 500  # 100

        base_name = os.path.basename(image_name)
        print("compressing :{0} compress_factor:{1} basename:{2}".format(image_name, compress_factor, base_name))

        for ext_name in png_array:
            if ext_name in image_name:
                compress_factor = math.trunc(round(compress_factor))
                if compress_factor > 90:
                    compress_factor = 85
                # if compress_factor < 75:
                #     compress_factor = 75
                iscompress = runSystem('pngquant.exe --force --verbose --speed=1 --quality={2}-100 {0} -o {1}'
                                       .format(image_name, replace_name, compress_factor))

                if iscompress:
                    g_compress_size = g_compress_size + math.ceil(os.stat(replace_name).st_size / 1024.0)
                    g_compress_pic_num = g_compress_pic_num + 1

                g_total = g_total + math.ceil(image_size)
                g_pic_num = g_pic_num + 1
                break

        for ext_name in jpg_array:
            if ext_name in image_name:
                iscompress = runSystem('magick convert {0} -quality {1} {2}'
                                       .format(image_name, compress_factor, replace_name))
                if iscompress:
                    g_compress_size = g_compress_size + math.ceil(os.stat(replace_name).st_size / 1024.0)
                    g_compress_pic_num = g_compress_pic_num + 1

                g_total = g_total + math.ceil(image_size)
                g_pic_num = g_pic_num + 1
                break
    elif not '.meta' in image_name:  # 不复制原图,只记大小
        for ext_name in png_array:
            if ext_name in image_name:
                # shutil.copy(image_name, replace_name)

                g_total = g_total + math.ceil(image_size)
                g_pic_num = g_pic_num + 1

                break

        for ext_name in jpg_array:
            if ext_name in image_name:
                # shutil.copy(image_name, replace_name)

                g_total = g_total + math.ceil(image_size)
                g_pic_num = g_pic_num + 1

                break


if __name__ == "__main__":
    # 给个默认值
    time1 = time.time()
    # 图片总大小
    global g_total
    g_total = 0
    # 图片压缩大小
    global g_compress_size
    g_compress_size = 0
    # png
    global png_array
    png_array = ['.png', '.PNG']
    # jpg
    global jpg_array
    jpg_array = ['.JPG', '.jpg', '.jepg', '.JPEG']

    # 图片总数
    global g_pic_num
    g_pic_num = 0

    # 压缩图片数量
    global g_compress_pic_num
    g_compress_pic_num = 0

    max_size = 50

    usePngQuantAndImageMagickAPI(max_size)


    print (u'总共图片大小:{0}KB 压缩了:{1}KB 压缩后大小:{2}KB'
           .format(g_total, g_compress_size, (g_total - g_compress_size)))
    print (u'图片总数:{0}张 压缩图片数:{1}张'.format(g_pic_num, g_compress_pic_num))

    time2 = time.time()

    print u'总共耗时:' + str(time2 - time1) + 's'

我的项目运行后:
总共图片大小:29232.0KB 压缩了:14152.0KB 压缩后大小:15080.0KB
图片总数:759张 压缩图片数:94张
总共耗时:42.7580001354s

参数还可再调整下,现在还凑合。

总结:网上的轮子很多,仔细找找,总有一款合适你的需求。但要成为大牛,还是自己实现一遍比较diao。

再分享个技巧:找不到合适的方法时,可以下载类似软件,看下它们的库文件。就像ImageMagick,我是下载搜索排行第一的压缩宝,才找到的。/手动斜眼笑

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值