项目地址

项目需求

项目思路

实现解析命令行参数

遍历文件,并且只处理图片

调整图片大小

总结

用Python批量调整图片大小

本文发表于入职啦(公众号: ruzhila) 大家可以访问入职啦学习更多的编程实战。

项目地址

代码已经开源, resize_images_py 👏 Star

项目需求

做一个图片批量调整大小的工具,可以指定输入目录和输出目录,然后将输入目录下的所有图片调整大小后保存到输出目录,还能支持指定转换的格式:

# 将当前目录下的所有图片调整为小于100KB,保存到new_dirs目录下,格式为jpg
python resize_images.py -i . -o new_dirs -s 100k -f jpg

# 将当前目录下的所有图片调整为原先的80%,保存到new_dirs目录下,格式为png
python resize_images.py -i . -o new_dirs -s 80% --format png

项目思路

这个需求由3个部分组成:

  1. 解析命令行参数: 特别是-s参数,支持100k80%这样的格式,这样我们就需要对参数进行解析,失败出是固定大小还是比例,执行的时候根据不同的参数执行不同的逻辑
  2. 遍历文件: 通过os.walk可以实现,遍历文件夹下的所有文件,只对.jpeg/.jpeg/.png这样的图片进行处理
  3. 调整图片大小: 通过Pillow库可以实现,调整图片大小,如果-f/--format不指定格式,那么就保持原来的格式

所以根据这三个部分,我们就可以实现这个需求。

先上代码: resize_images_py

实现解析命令行参数

我们利用内置的optparse库,可以很方便的解析命令行参数,这里我们主要解析-i-o-s-f这几个参数

其中-s参数支持100k80%这样的格式,这样我们就需要对参数进行解析是固定大小还是比例

我们识别最后一个字符,如果是%,那么就是比例,如果是kmg,那么就是固定大小 可以看出来Python处理字符串非常方便

def main():
  parser = OptionParser()
  parser.add_option("-i", "--input", dest="input",
                    default=".", help="Input image file", metavar="INPUT")
  parser.add_option("-o", "--output", dest="output",
                    default=".", help="Output image file", metavar="OUTPUT")
  parser.add_option("-s", "--size", dest="size", default="80%",
                    help="Output image size", metavar="SIZE")
  parser.add_option("-f", "--format", dest="format",
                    default="jpeg", help="Output image format", metavar="FORMAT")

  (options, _) = parser.parse_args()
  max_size = options.size.lower()
  percent = False

  if max_size.endswith('%'):
      max_size = int(max_size[:-1])
      if max_size < 1 or max_size > 100:
          parser.error('Invalid percentage')
      max_size = max_size / 100.0
      percent = True
  else:
      unit = max_size[-1]
      units = {'k': 1024, 'm': 1024**2, 'g': 1024**3}
      if unit in units:
          max_size = int(max_size[:-1])
          max_size *= units[unit]
      else:
          parser.error('Invalid size format')

遍历文件,并且只处理图片

我们可以使用os.walk来遍历文件夹下的所有文件,然后只处理.jpeg/.jpeg/.png这样的图片

遍历出的文件,我们可以通过os.path.splitext来获取文件的扩展名,然后判断是否是图片

并且我们可以通过os.path.join来拼接文件的路径

def walk_dir(input_dir, output_dir, max_size, percent, format):
    """walk through input_dir and convert images to output_dir
    """
    for root, _, files in os.walk(input_dir):
        for file in files:
            ext = os.path.splitext[file](1).lower()
            if ext not in ('.jpg', '.jpeg', '.png'):
                continue
            input_file = os.path.join(root, file)
            output_file = input_file.replace(input_dir, output_dir)
            convert_file(input_file, output_file,
                         max_size, percent, format)

调整图片大小

我们的算法是通过修改图片的大小来改变文件的大小,这个算法有个明显缺陷会改变图片的尺寸,如果不修改图片的尺寸,那么就需要改变图片的质量

  • 调用Pillow库的Image.open来打开图片,然后获取图片的大小,然后根据图片的大小和文件的大小来计算新的大小
  • 如果是百分比,那么就直接调整图片的大小
  • 如果是固定大小,那么就计算新的大小,然后调整图片的大小
  • 最后保存图片到输出文件,通过img.save来保存图片
with Image.open(input_file) as img:
    img_size = os.path.getsize(input_file)
    if percent:
        width, height = img.size
        max_width = int(width * max_size)
        max_height = int(height * max_size)
        img = img.resize((max_width, max_height), Image.LANCZOS)
    else:
        # check file size
        if img_size < max_size:
            print(f'{input_file} ({img_size}) -> {output_file} (skip)')
            return

        # calculate new size
        width, height = img.size
        scale_factor = (max_size / img_size) ** 0.59
        new_width = int(width * scale_factor)
        new_height = int(height * scale_factor)
        img = img.resize((new_width, new_height), Image.LANCZOS)
    try:
        img.save(output_file, format=format)
        new_size = os.path.getsize(output_file)
        print(f'{input_file} ({img_size}) -> {output_file} ({new_size})')
    except OSError as e:
        print(f'{input_file} failed: ({e})')

总结

Python特别适合做文件处理,并且支持跨平台,日常工作中可以用Python做文件处理,比如批量处理图片,批量处理文本等。

写一个批量处理的工具可以大幅度的提升效率,这也是python作为自动化工具首选的原因

批量处理工具还需要考虑很多因素,比如目录的创建,是否要保留源文件等等,这些都是非常细节的事情,也是决定工具好坏的关键。

推荐大家学习一门静态语言,比如Java、C++,这样可以更好的理解编程语言的底层原理,同时也要掌握一门动态语言,比如Python、JavaScript,这样可以更好的提高工作效率。

所有的后端面试常见的问题,我们每天都会在我们的编程群里面讨论和Code review, 欢迎大家加入我们的编程群,一起学习和进步。

编程交流群

欢迎大家关注 入职啦 (公众号: ruzhila) ,获取更多有趣的编程挑战题和技术干货!

友情链接:

Copyright© 2024 杭州园中葵科技有限公司 版权所有