zoukankan      html  css  js  c++  java
  • 【python】图片批量压缩(多线程)

    效果演示

    在这里插入图片描述

    项目场景

    从某网站爬了很多图片,图片有jpgpng等格式。有些图片很大,出于某种需求,我们需要把图片批量压缩一下。

    核心代码

    from PIL import Image
    im = Image.open('test.png')
    im = im.convert('RGB')
    im.save('test.jpg', quality=75)
    

    这里的图片压缩我们用到的是pillow库,所有图片都先转换到RGB三个通道,然后全部保存为jpg格式。

    quality参数是设置图片保存质量的参数,默认值是75,其取值范围为1~95,你可以根据自己的具体需求设置。

    完整代码

    import concurrent.futures as cf
    from PIL import Image
    import time
    import os
    import re
    
    
    class ImageConvert(object):
        def __init__(self):
            self.root = input('请输入图片文件夹的绝对路径: ')
            self.count = 0
            self.pret()
    
        def pret(self):
            self.names = os.listdir(self.root)
            for i in self.names:
                pattern = re.compile('(.png|.jpg)$')
                if not re.search(pattern, i):
                    self.names.remove(i)
            self.sum = len(self.names)
            self.size = sum([
                os.path.getsize(os.path.join(self.root, name)) for name in self.names
            ])
            self.size /= (1024*1024)
    
        def cont(self, name):
            path = os.path.join(self.root, name)
            im = Image.open(path)
            im = im.convert('RGB')
            im.save(os.path.join(self.root, name[:-4]+'.jpg'), quality=95)
            im.close()
            if '.png' in name:
                os.remove(path)
            else:
                pass
    
        def show(self, num, _sum,  runTime):
            barLen = 20  # 进度条的长度
            perFin = num/_sum
            numFin = round(barLen*perFin)
            numNon = barLen-numFin
            leftTime = (1-perFin)*(runTime/perFin)
            print(
                f"{num:0>{len(str(_sum))}}/{_sum}",
                f"|{'█'*numFin}{' '*numNon}|",
                f"任务进度: {perFin*100:.2f}%",
                f"已用时间: {runTime:.2f}S",
                f"剩余时间: {leftTime:.2f}S",
                end='
    ')
            if num == _sum:
                print()
                sizeBefore = self.size
                self.pret()
                sizeAfter = self.size
                rate = sizeAfter/sizeBefore
                print(
                    f"压缩前大小: {sizeBefore:.2f}MB",
                    f"压缩后大小: {sizeAfter:.2f}MB",
                    f"整体压缩率: {rate*100:.2f}%" # 压缩率越小越好
                )
    
        def main(self):
            tp = cf.ThreadPoolExecutor(32) # 设置线程数32
            futures = []
            startTime = time.time()
            for name in self.names:
                future = tp.submit(self.cont, name)
                futures.append(future)
            for future in cf.as_completed(futures):
                self.count += 1
                endTime = time.time()
                runTime = endTime-startTime
                self.show(self.count, self.sum, runTime)
            tp.shutdown()
            os.system('pause')
    
    
    if __name__ == "__main__":
        ImageConvert().main()
    

    温馨提示

    为什么我们这里用多线程而不是多进程?

    多进程适合处理CPU密集型任务(比如纯计算问题),而多线程适合解决IO密集型任务(比如文件读写操作)。

    我们这里主要是读取图片,压缩图片,然后保存图片,显然CPU的占用率不高,而主要是硬盘/内存的读写操作。

    引用参考

    https://blog.csdn.net/youanyyou/article/details/78990156
    https://blog.csdn.net/qq_42951560/article/details/109349309
    
  • 相关阅读:
    使用C语言生成任意指定长度的一串随机数
    拷贝ssh公钥到 authorized_keys 后仍然无法免密登录的原因记录
    vs2013 远程调试---笔记
    C++ 根据进程名找到对应Pid
    使用C语言判断一个IP 地址是否为私有地址
    WEB后台传数据给前台
    邮箱跳转
    Cookie记住密码
    Linux服务器攻击防御(转)
    APACHE两种域名跳转法简单完成重定向
  • 原文地址:https://www.cnblogs.com/ghgxj/p/14219109.html
Copyright © 2011-2022 走看看