目录
  • 背景
  • 解决方案
  • 操作步骤
    • 要求
    • 步骤
  • 附:批量将图片的大小设置为指定大小
    • 写在后面

      背景

      今天在工作中,同事遇到一个上传图片的问题:系统要求的图片大小不能超过512kb。但是同事又有很多照片。这要是每一个照片都用ps压缩的话,那岂不是很崩溃。于是我写了一个脚本,可以批量压缩图片到指定大小。直接造福同事、提高同事的工作效率。

      解决方案

      其实也不用卖关子了,就是使用python的pillow包就可以对图片进行压缩,如果一个图片已经压缩到指定大小了,那就停止压缩,如果没有达到指定大小,那就对压缩后的图片再进行压缩,直到压缩到自定范围内。

      可是为什么不在网上找代码呢?我也是找过,但是发现很多代码质量参差不齐,都达不到我想要的效果,而且很不优雅。于是我随手就写了一个代码,不仅仅代码写的简单,而且逻辑清楚,最后为了效率,我还做了一个并行,同时使用10个进程处理。说实话,那可是真的飞快。

      操作步骤

      要求

      • 默认是使用的是anaconda的环境。
      • 将所有要压缩的图片都放在一个文件夹下,然后每个图片的格式只能是下面三种:png,jpg, jpeg。如果是png也不行。因为png是png的大写。
      • 代码中设置的图像的压缩后的大小是512kb,那么你可以设置代码中的target_size为500,只要比512kb小就行了。
      • 然后把我的代码从github上下载下来。代码链接为:https://github.com/yuanzhoulvpi2017/tiny_python/blob/main/image_compression/ic.py

      步骤

      我这里把所有图片都放在了一个文件夹里面,文件夹名称为历史截图。然后我的这个历史截图和ic.py代码都放在了little_code文件夹中。

      在little_code文件夹下,打开终端。

      直接运行的脚本:

      python ic.py xxx_文件夹
      

      等待一会,就会将整个文件夹下的所有图片都转化好了。

      完整代码:

      如果上不去github的话,我直接把代码放在这里,保存为一个python文件即可。比如保存的文件名为:ic.py

      from pil import image
      from glob import glob
      import os
      from tqdm import tqdm
      import shutil
      import sys
      from itertools import chain
      
      from multiprocessing import pool
      
      # image_dir = "image_dir"
      template_dir = 'template'
      output_dir = 'output'
      error_dir = 'error'
      
      
      def clean_dir(dir_name):
          if os.path.exists(dir_name):
              shutil.rmtree(dir_name)
              os.makedirs(dir_name)
          else:
              os.makedirs(dir_name)
      
      
      # image_file_list = glob(f"{image_dir}/*")
      # image_file_list
      
      
      def imagesize(filepath):
          """
          获得文件的磁盘大小
          :param filepath:
          :return:
          """
          return os.path.getsize(filepath) / 1024
      
      
      def compress_image(image_path):
          raw_image = image.open(image_path)
          temp_image_name = image_path.split(os.sep)[-1]
          template_image = os.path.join(template_dir, temp_image_name)
          output_image = os.path.join(output_dir, temp_image_name)
          error_image = os.path.join(error_dir, temp_image_name)
      
          target_size = 500  # kb
      
          try:
      
              if imagesize(image_path) < target_size:
      
                  shutil.copyfile(image_path, output_image)
              else:
                  width, height = raw_image.size
                  raw_image.resize((int(width * 0.9), int(height * 0.9)), image.antialias).save(template_image)
                  while imagesize(template_image) > target_size:
                      template_iamge2 = image.open(template_image)
                      width_2, height_2 = template_iamge2.size
                      template_iamge2.resize((int(width_2 * 0.9), int(height_2 * 0.9)), image.antialias).save(template_image)
      
                  shutil.copyfile(template_image, output_image)
          except exception as e:
              shutil.copyfile(image_path, error_image)
              print(f'文件保存失败: {image_path}')
              # print(e)
      
      
      if __name__ == '__main__':
          # 批量创建文件夹
          [clean_dir(i) for i in [template_dir, output_dir, error_dir]]
      
          image_dir = sys.argv[1]
      
          image_file_list = list(chain(*[glob(os.path.join(image_dir, i)) for i in ['*.png', '*.jpg', '*.jpeg']]))
      
          # for temp_image_path in tqdm(image_file_list):
          #     compress_image(temp_image_path)
      
          print(f'\n\n文件保存父目录: {os.getcwd()}\n'
                f'输出文件位置:{os.path.join(os.getcwd(), output_dir)}\n\n')
      
          # parallel
          p = pool(processes=10)
          pbar = tqdm(total=len(image_file_list))
      
          res_temp = [p.apply_async(func=compress_image, args=(i,), callback=lambda _: pbar.update(1)) for i in
                      image_file_list]
      
          _ = [res.get() for res in res_temp]
      
      

      附:批量将图片的大小设置为指定大小

      import os
      
      from pil import image
      
       
      
      # 源目录
      
      project_dir = os.path.dirname(os.path.abspath(__file__))
      
      input = os.path.join(project_dir, 'src')
      
       
      
      # 输出目录
      
      output = os.path.join(project_dir, 'dest')
      
      def modify():
      
          # 切换目录
      
          os.chdir(input)
      
       
      
          # 遍历目录下所有的文件
      
          for image_name in os.listdir(os.getcwd()):
      
              print(image_name)
      
              im = image.open(os.path.join(input, image_name))
      
              im.thumbnail((128, 128))
      
              im.save(os.path.join(output, image_name))
      
       
      
      if __name__ == '__main__':
      
          modify()

      写在后面

      这个代码说起来难,说起来也不难,如果认真看我历史的文章的话,上面代码中遇到的知识点都就会了。像是所谓的图像压缩、并行处理之类的,其实并不难。

      到此这篇关于python批量压缩图像的文章就介绍到这了,更多相关python批量压缩图像内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!