本脚本可用于对指定文件夹中的所有图片进行批量裁剪和缩放,并按照指定的尺寸和比例保存为新的图片。
问题描述
该脚本主要解决了以下问题:
- 对文件夹内的所有图片进行居中裁剪,以达到指定的高宽比。
- 将裁剪后的图片缩放到指定的大小。
- 支持不同的保存模式,可以选择将处理后的图片保存到新文件夹中(保留或不保留子目录结构),或直接在原文件夹中生成。
使用方法
- 确保您已经安装了Python和Pillow库。如果尚未安装,可以使用以下命令安装:
pip install pillow
- 将脚本保存为image_resizer.py(或其他您喜欢的文件名)。
- 通过命令行(或终端)运行脚本:
python image_resizer.py
- 程序会提示您输入图片文件夹位置,请输入待处理的图片文件夹位置并按回车键,例如:
请输入图片文件夹位置(输入Q或q退出): sample_images/
- 如果您想要退出程序,请在提示输入图片文件夹位置的界面输入“Q”或“q”并按回车键。
- 程序会根据您输入的图片文件夹位置进行批量处理,并将处理后的图片保存到指定的目录中。
参数设置
以下参数可以根据需要进行修改:
dst_w
和dst_h
:目标尺寸,分别表示图片的目标宽度和高度。默认值分别为580和300。-
save_type
:保存模式。有以下几种选项:- 1:将处理后的图片存储到新文件夹中,并保留子目录结构。
- 2:将处理后的图片存储到一个新的文件夹,但不复制子文件夹,而是全部放到一起。
- 3:直接在原文件夹中生成处理后的图片。
默认值为1。
函数说明
is_img(ext)
: 判断给定的文件扩展名是否为图片格式。remove_ds_store(path)
: 删除指定路径下的.DS_Store
文件(仅适用于macOS)。resize_dir_images(src_path)
: 遍历指定文件夹内的所有图片,并调用crop_and_resize
函数进行处理。crop_and_resize(fp)
: 对给定的图片进行裁剪和缩放。get_src_path()
: 获取用户输入的文件夹路径。main()
: 主函数,负责获取源文件夹路径,创建目标文件夹,调用resize_dir_images
函数进行图片处理,最后输出处理结果。
不同参数和模式下的效果
保存模式 1
默认参数(dst_w=580,dst_h=300,save_type=1)
- 输入文件夹结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
sample_images ├── folder1 │ ├── image1.jpg │ ├── image2.jpg │ └── image3.jpg ├── folder2 │ ├── image4.jpg │ ├── image5.jpg │ └── image6.jpg └── folder3 ├── image7.jpg ├── image8.jpg └── image9.jpg |
- 运行脚本后,输出文件夹结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
sample_images_580x300 ├── folder1 │ ├── image1.jpg │ ├── image2.jpg │ └── image3.jpg ├── folder2 │ ├── image4.jpg │ ├── image5.jpg │ └── image6.jpg └── folder3 ├── image7.jpg ├── image8.jpg └── image9.jpg |
- 裁剪结果:将原图按照目标比例居中剪裁,以宽度为580,高度为300进行缩放。原图比例大于目标比例时,裁剪掉原图上下部分;原图比例小于目标比例时,裁剪掉原图左右部分。
保存模式 2
自定义参数(dst_w
=1000,dst_h
=600,save_type
=2)
将所有处理后的图片放入一个新的文件夹中。
- 输入文件夹结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
sample_images ├── folder1 │ ├── image1.jpg │ ├── image2.jpg │ └── image3.jpg ├── folder2 │ ├── image4.jpg │ ├── image5.jpg │ └── image6.jpg └── folder3 ├── image7.jpg ├── image8.jpg └── image9.jpg |
- 运行脚本后,输出文件夹结构:
1 2 3 4 5 6 7 8 9 10 11 |
sample_images_1000x600 ├── image1.jpg ├── image2.jpg ├── image3.jpg ├── image4.jpg ├── image5.jpg ├── image6.jpg ├── image7.jpg ├── image8.jpg └── image9.jpg |
- 裁剪结果:将原图按照目标比例居中剪裁,以宽度为1000,高度为600进行缩放。所有图片均存储到一个新的文件夹中,保留原始文件名。
保存模式 3
将处理后的图片保存在原文件夹中。自定义参数(dst_w
=400,dst_h
=400,save_type
=3)
- 输入文件夹结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
sample_images ├── folder1 │ ├── image1.jpg │ ├── image2.jpg │ └── image3.jpg ├── folder2 │ ├── image4.jpg │ ├── image5.jpg │ └── image6.jpg └── folder3 ├── image7.jpg ├── image8.jpg └── image9.jpg |
- 输出文件夹结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
sample_images ├── folder1 │ ├── image1.jpg │ ├── image2.jpg │ ├── image3.jpg │ ├── image1_400x400.jpg │ ├── image2_400x400.jpg │ └── image3_400x400.jpg ├── folder2 │ ├── image4.jpg │ ├── image5.jpg │ ├── image6.jpg │ ├── image4_400x400.jpg │ ├── image5_400x400.jpg │ └── image6_400x400.jpg └── folder3 ├── image7.jpg ├── image8.jpg ├── image9.jpg ├── image7_400x400.jpg ├── image8_400x400.jpg └── image9_400x400.jpg |
- 裁剪结果:将原图按照目标比例居中剪裁,以宽度为400,高度为400进行缩放。所有图片均存储到一个原来的文件夹中,新文件后缀会加上新的像素值。
输入文件夹结构
脚本默认会处理指定文件夹下所有的子文件夹中的图片,处理后将会按照指定的存储模式进行保存。如果您的文件夹中包含了多个子文件夹,并且希望仅处理其中的某个子文件夹,可以将子文件夹的名称添加到路径中。例如,如果要仅处理名为 my_photos 的子文件夹中的图片,可以将命令修改为:
1 2 |
python image_resizer.py my_photos |
注意事项
在使用脚本进行图片处理时,有一些需要注意的事项:
- 脚本只能处理常见的图片格式,包括 .jpg、.jpeg、.png、.bmp等格式。其他格式的文件会被忽略。
- 处理图片时会将图片进行裁剪和缩放,如果图片的比例和目标比例差别很大,可能会导致图片变形或者出现黑边。因此,建议将目标比例设置为和原始图片比例相近的值。
- 在脚本处理图片时,会按照默认的宽度和高度进行缩放。如果您需要将图片缩放到其他的尺寸,可以修改
dst_w
和dst_h
参数。 - 在脚本处理图片时,会按照指定的存储模式保存处理后的图片。如果您需要将处理后的图片保存到其他的文件夹中,可以修改 save_type 参数。
- 在脚本处理图片时,会先检查是否存在 .DS_Store 文件,并自动删除。这是因为在 Mac OS 系统中,该文件会记录文件夹中的图标布局等信息,可能会对处理图片产生影响。
总结
通过本脚本,您可以方便地对图片进行批量裁剪和缩放,实现快速处理大量图片的目的。根据实际需求,您可以调整参数来满足不同的图片处理要求。同时,我们还提供了多种保存模式,可以根据实际需求选择适合的模式。希望这个脚本能够帮助您更高效地进行图片处理。
附录代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
#!/usr/bin/env python # -*- coding:utf-8 -*- # 将文件夹下的图片居中剪裁为指定比例并缩放到指定大小 ### from PIL import Image from pathlib import Path import sys # 目标尺寸 dst_w = 580 dst_h = 300 # 存储模式,为1时存储到新文件夹中,保留子目录结构,为2时存储到一个新的文件夹,但不复制子文件夹,而是全部放到一起,为3时直接在原来的文件夹中生成 save_type = 1 def is_img(ext): # 检测文件后缀名是否为图片 ext = ext.lower() if ext == '.jpg': return True elif ext == '.png': return True elif ext == '.jpeg': return True elif ext == '.bmp': return True else: return False def remove_ds_store(path): # print('检查 %s 内是否存在 .DS_Store 文件'%str(path)) target = path / '.DS_Store' if (target.exists()): Path.unlink(target) print(f'{target} 文件已自动删除。') else: # print(f'.DS_Store 文件不存在,继续操作。') pass def resize_dir_images(src_path): global filecount remove_ds_store(src_path) for f in src_path.glob('**/*'): # 也可以用src_path.rglob('*') if f.is_file(): filecount += 1 print('正在转换第 %d 个文件:%s \r' % (filecount, f.name), end='') crop_and_resize(f) def crop_and_resize(fp): ''' 图片按照目标比例裁剪并缩放 ''' global dst_w, dst_h, dst_path, option if(is_img(fp.suffix)): im = Image.open(str(fp)) src_w, src_h = im.size dst_scale = float(dst_h / dst_w) # 目标高宽比 src_scale = float(src_h / src_w) # 原高宽比 if src_scale >= dst_scale: # 过高 # print("原图过高") width = src_w height = int(width * dst_scale) x = 0 y = (src_h - height) / 2 else: # 过宽 # print("原图过宽\n") height = src_h width = int(height / dst_scale) x = (src_w - width) / 2 y = 0 # 裁剪 box = (x, y, width + x, height + y) # 这里的参数可以这么认为:从某图的(x,y)坐标开始截,截到(width+x,height+y)坐标 newIm = im.crop(box) im = None # 压缩 ratio = float(dst_w) / width newWidth = int(width * ratio) newHeight = int(height * ratio) # dst_file = dst_path/fp.name # 保持原文件名 # dst_file = dst_path / f'{fp.stem}_{dst_w}x{dst_h}{fp.suffix}' # 文件名添加新尺寸 if save_type == 1: # print(str(fp.parent).replace(str(src_path), str(dst_path))) # 在新文件夹中新建子目录 dst_file_name = str(fp.parent).replace(str(src_path), str(dst_path)) dst_file_path = Path(dst_file_name) if dst_file_path.exists(): pass else: dst_file_path.mkdir(parents=True) #在子目录中新建同名图片 dst_file = dst_file_path / fp.name elif save_type == 2: dst_file = dst_path / fp.name # 保持原文件名 else: dst_file = fp.parent / f'{fp.stem}_{dst_w}x{dst_h}{fp.suffix}' #保存到原来的文件夹 newIm.resize((newWidth, newHeight), Image.Resampling.LANCZOS).save(dst_file, quality=100) def get_src_path(): src_dir = input('请输入图片文件夹位置(输入Q或q退出):') if src_dir == "Q" or src_dir == 'q': sys.exit() src_path = Path(src_dir) src_path = src_path.expanduser() print("输入的文件夹:", src_path) return src_path def main(): global src_path, dst_path, filecount src_path = get_src_path() while (not src_path.exists()): print(f'文件夹{src_path}不存在,请检查输入的文件夹名称是否正确。') src_path = get_src_path() dst_dir = f'{src_path}_{dst_w}x{dst_h}' dst_path = Path(dst_dir) filecount = 0 # 此参数规定了最后文件列表每行显示的文件名数量。 display_each_line = 10 cnt = 0 # print('原始图片文件夹:',src_path) print('目标文件夹:', dst_path) if dst_path.exists(): print(f'目标文件夹 {dst_path} 已经存在...') pass else: # print(f'创建目标文件夹: {dst_path} ') dst_path.mkdir(parents=True) print(f'目标分辨率:{dst_w}x{dst_h}') resize_dir_images(src_path) remove_ds_store(dst_path) # dst_file_list = dst_path.iterdir() # # 直接遍历目标文件夹下的jpg/jpeg文件(使用*.jp*g来匹配两种后缀名)。 dst_file_list = dst_path.glob('*.jp*g') print(f'\n一共转换了{filecount}个文件\n已转换的文件列表:', end='') line_count = 0 for f in sorted(dst_file_list, key=lambda f: f.stem): cnt += 1 if cnt % display_each_line == 1: line_count += 1 print('\n%d | %10s' % (line_count, f.name), end='') else: print('%10s' % f.name, end='') if __name__ == '__main__': main() |
总结
chatGPT牛逼,如果要他生成markdown源文件的,则对应的AI引导词为:
1 2 |
如果您需要生成类似的Markdown源文件内容,您可以使用类似于“请提供用Markdown语法写的源文件内容”或“请提供Markdown格式的源文件内容”的引导词,这样我就能更好地理解您的需求,并为您提供满意的答案。 |