用 Python 批量处理图片大小
Python 批量处理图片大小
写博客,文档的时候常常要附上很多图片,但是图片的尺寸往往不符合我们的要求,手动一个一个修改尺寸再保存,太浪费时间了,既然学了 Python,当然就要物尽其用。本文实现了批量修改同级目录下的 image\src 文件夹下的所有图片,并输出到 image\output 文件夹下,可以设定具体像素,也可以只设定水平像素或者垂直像素, 另一边按原图比例进行缩放。使用 Python 处理图片大小需要使用 PIL 库,PIL:Python Imaging Library,是一个图片处理库,需要自行安装。
PIL 读取图片大小
下面是修改单张图片尺寸的函数。
from PIL import Image
set_img_type = ""
def resize_image(filein, fileout, set_horizontal_length, set_vertical_length):
if set_vertical_length == 0 and set_horizontal_length == 0:
return
img = Image.open(filein)
img_size = img.size
img_horizontal_length = img_size[0]
img_vertical_length = img_size[1]
if set_vertical_length == 0:
set_vertical_length = set_horizontal_length * img_vertical_length / img_horizontal_length
if set_horizontal_length == 0:
set_horizontal_length = set_vertical_length * img_horizontal_length / img_vertical_length
print img_horizontal_length, img_vertical_length
print set_horizontal_length, set_vertical_length
# resize image with high-quality
out = img.resize((set_horizontal_length, set_vertical_length), Image.ANTIALIAS)
if set_img_type == "":
out.save(fileout)
else:
out.save(fileout, set_img_type)
代码简介
- filein 图片输入文件名(带路径)。
- fileout 图片输出文件名(带路径)。
- set_horizontal_length 希望修改成的水平长度,如果为 0,自动使用原图比例和设定的竖直长度计算该值。
- set_vertical_length 希望修改成的竖直长度,如果为 0,自动使用原图比例和设定的水平长度计算该值。
- img.size 包含了两个值,比如(1080, 1920),第一个值是宽度(水平长度),第二值是高度(竖直长度)。
- set_img_type 如果为空,保持原图片类型,如果非空则保存成对应图片类型,比如
set_img_type = "png"
,会把图片以 png 数据格式进行保存。
PIL 批量处理图片
上面已经介绍了处理单张图片的方法,想要处理文件夹下的所有图片就要能遍历文件夹里所有的文件。这里使用递归遍历出所有的文件,再分别进行处理。
使用递归遍历文件夹
def check_image(root_dir):
if not os.path.isdir(root_dir):
return
for lists in os.listdir(root_dir):
path = os.path.join(root_dir, lists)
if os.path.isfile(path):
# TODO: resize image.
if os.path.isdir(path):
check_image(path)
代码简介:
判断当前文件夹中的每个元素,如果是文件夹则进入该文件夹递归调用,并重复读取判断操作。如果是文件,则在代码中的 TODO 标签处进行相应处理。注:这里默认 image\src 文件夹下不会出现非图片文件。
准备输出工作
目标是把修改后的图片输出到 image\output 文件夹下,这里需要做三件事,在 output 目录下创建对应 src 目录下的子文件夹,生成图片保存的文件名(带路径),修改生成图片的后缀名。将递归代码修改如下,增加了 find_last_point 函数用于找到后缀名前的小数点来修改后缀名。
import os
import os.path
def check_image(root_dir):
if not os.path.isdir(root_dir):
return
for lists in os.listdir(root_dir):
path = os.path.join(root_dir, lists)
# handle output path of dir and file
out_path = image_output_dir + path[9:]
print path
if os.path.isfile(path):
# handle output file name
point_position = find_last_point(out_path)
if not set_img_type == "":
out_path = out_path[0:point_position + 1] + set_img_type
print out_path
# resize image.
resize_image(path, out_path, horizontal_length, vertical_length)
if os.path.isdir(path):
# make dir in image\output
if not os.path.exists(out_path):
os.mkdir(out_path)
print out_path
check_image(path)
def find_last_point(file_path):
position = 0
temp = 0
while temp != -1:
temp = file_path.find(".")
if temp != -1:
position = temp
file_path = file_path[ temp + 1:]
return position
清理 output 文件夹
如果只生成不清理,output 文件夹会越来越臃肿,想要找到转换的图片还需要花额外的时间,所以这里选择程序刚开始就删除整个 output 文件夹,并新建一个空的 output 文件夹。
import os
import os.path
import shutil
def clear():
if os.path.exists(image_output_dir):
shutil.rmtree(image_output_dir)
if not os.path.exists(image_output_dir):
os.mkdir(image_output_dir)
完整代码
PIL 不支持修改为 jpg 后缀,所以如果设置生成 jpg 文件,程序会自动修改成 jpeg 文件。
import os
import os.path
import shutil
from PIL import Image
horizontal_length = 260
vertical_length = 0
image_src_dir = r"image\src"
image_output_dir = r"image\output"
set_img_type = ""
# set_img_type = "bmp"
# set_img_type = "jpeg"
# set_img_type = "png"
def test_run():
if os.path.exists(image_output_dir):
shutil.rmtree(image_output_dir)
if not os.path.exists(image_output_dir):
os.mkdir(image_output_dir)
global set_img_type
if set_img_type == "jpg":
set_img_type = "jpeg"
check_image(image_src_dir)
print "finish."
def resize_image(filein, fileout, set_horizontal_length, set_vertical_length):
if set_vertical_length == 0 and set_horizontal_length == 0:
return
img = Image.open(filein)
img_size = img.size
img_horizontal_length = img_size[0]
img_vertical_length = img_size[1]
if set_vertical_length == 0:
set_vertical_length = set_horizontal_length * img_vertical_length / img_horizontal_length
if set_horizontal_length == 0:
set_horizontal_length = set_vertical_length * img_horizontal_length / img_vertical_length
print img_horizontal_length, img_vertical_length
print set_horizontal_length, set_vertical_length
# resize image with high-quality
out = img.resize((set_horizontal_length, set_vertical_length), Image.ANTIALIAS)
if set_img_type == "":
out.save(fileout)
else:
out.save(fileout, set_img_type)
def check_image(root_dir):
if not os.path.isdir(root_dir):
return
for lists in os.listdir(root_dir):
path = os.path.join(root_dir, lists)
# handle output path of dir and file
out_path = image_output_dir + path[9:]
print path
if os.path.isfile(path):
# handle output file name
point_position = find_last_point(out_path)
if not set_img_type == "":
out_path = out_path[0:point_position + 1] + set_img_type
print out_path
# resize image.
resize_image(path, out_path, horizontal_length, vertical_length)
if os.path.isdir(path):
# make dir in image\output
if not os.path.exists(out_path):
os.mkdir(out_path)
print out_path
check_image(path)
def find_last_point(file_path):
position = 0
temp = 0
i = 0
while temp != -1:
temp = file_path.find(".")
if temp != -1:
if i == 0:
position = position + temp
else:
position = position + temp + 1
file_path = file_path[temp+1:]
i = 1
return position
if __name__ == "__main__":
test_run()