先把那个结果看一遍。一共是 28 张截图, 它们的大小之前是 5.3MB, 现在跑完一段代码之后, 大小变成了 3.0MB, 总体节省的空间达到了 43%, 其中单张图片里最狠的一张照片, 它的大小从之前的 326KB 减小到了 104KB, 这一个别项上节省了 68。压缩对比这一些图全部都是各种界面的截图, 把图片压缩之后, 我是一张一张地进行对比的, 用肉眼看过去, 基本上是完全发现不了什么差别的, 在微信群里进行发送, 或者是在传输文档的过程之中, 又或者是贴到聊天记录里面去的情况下, 这么一样的画质是绝对地完全够用了。图片这种文件, 其实是硬盘还有网盘里面最隐蔽的那种占用空间的大户。下面我把这一整套情况给你讲得明明白白的, 到底为什么呢, 为什么图片是可以压制的, 代码具体是怎么运行的, 哪些我已经替你踩过的那些坑我都给你说清楚了。这些代码呢你都是可以直接复制过来使用的。你所提交的那些图片, 很有可能在存储资源方面, 白白地占用了差不多一半的容量份额。首先提出这样一个疑问, 针对将截图文件格式设置为PNG这一情况, 你是否曾经思考过导致其文件体积非常大的原因在何方。PNG格式是无损伤存储类型。它将像素颜色数据进行完全留存, 不会遗漏任何一个细节。这种特性针对设计文件呈现是非常友好的处理方式。然而对于屏幕截图场景而言, 却会造成存储空间上的浪费现象。具体表现为界面中存在大面积单调色彩背景区域、大量重复使用相同的按钮组件元素、以及一致文本内容情况发生之时。采用无损伤归档方式会对所有上述信息进行逐一备份记录操作。JPEG 是有损格式, 在质量值设定为80的档位之下, 人眼难以分辨出差异, 可是文件大小却缩减到了原始文件体量的几分之一。存图的这个速度, 是能够超出你的想象中的。就是截取一张就保存一张, 在微信里面存的图片、另行保存的网页上面的图片、各种软件里导出来的图片, 一年下来累计到几千张是一个非常正常的现象。按照每一张图片的大小是 200KB 来进行计算的话, 2000 张图片的总大小就是达到 400MB了。如果要给他人传送这些资料的话, 由于微信有规定的不能发送大于 25MB 的文件这样一个限制条件, 所以说通常一批图片传过去的时候是经常会直接超过了限制的规模的。为什么不选择使用手动压缩的方式呢? 如果借助图片处理软件来一个个地打开并单独保存, 那么面对一百张这样规模的图片, 你很可能需要耗费整整一晚上的时间来反复点击操作。虽然市面上确实存在一些图片查看软件支持批量压缩的功能, 但这些工具往往要求用户额外进行安装, 可能需要开通会员权限, 并且还会在你使用的过程中添加水印, 这显然是不可取的。自己写十几行的事。第一步就是要把那个东西安装好。这个脚本用 处理图片命令行里敲pip install pillow当安装完成后, 会出现一个带有空格的提示信息。如果软件已经安装过了, 系统会给出相应的提示, 接着直接进行下一步操作。第二步是将这个脚本进行存档。去新建出一个文本文件来, 然后把它的名字修改成为压图片.py接着呢, 把那个文章末尾地方所展示的全部代码全部都粘贴复制到文件里面去。进入程序运行的这一步骤。python 压图片.py D:\你的图片文件夹敲回车键等着程序跑完就行。只要完成一张图的压缩, 系统就会打印一行输出内容, 这一行内容包括三个指标: 分别是原始的大小是多少、变成后的体积是多大、还有最终节省下来的百分比具体是多少。运行结果以上就是那28张图构成的完整清单, 在这里对全部的结果做一个最后的总结性的陈述。至于那些经过压缩运算处理之后的图片文件, 系统将它们统一输出存放到了原始文件夹内部所包含的那个, 标签名称叫做压缩后的子文件夹当中去。而在此之前所存在的那部分原始文件资料, 在操作过程中一个都没有发生任何性质的移动或修改举动。原文件不动这一点, 对于现在的大家来说, 确实是挺重要的一个事情, 所以你要先去仔细看看压缩之后的那张图片是不是让你觉得满意, 如果你觉得这个新做的图片看起来还可以, 那你就可以使用这个新的文件, 要是你觉得不好, 那原来的原始文件还好好地放在那边呢, 所以说你根本没有任何一点的损失。核心就一行核心代码实际在进行具体操作和劳动, 真正出力气的也就是这么一行。im.convert(RGB).save(dst, JPEG, quality80, optimizeTrue)(“RGB”)这一步是把图片里用的多的那个带透明度的四维模式换回那种要三个通道的模式, 这样以前透明的地方就会用白色去填上。后面的等号等于八十代表的是压缩文件大小的一个等级设置, 八十五这个数字经常被人用来在文件大小和画面干净程度之间找个平衡点, 如果把这一项往下调到六十, 那么生成的文件确实会小很多, 但是一旦把它放大看就会发现表面有点糊成一团的感觉, 相反要是把这个值提到九十五的话, 那么大小的变化也就几乎没有了。后面的 if 是我踩坑之后加的保护下一节说。我踩过的三个坑第一个坑, 有的图会越压越大。我在跑第一批的时候, 有一张大小是 46.9KB 的小图, 压完之后变成了 57.5KB , 还有一张大小是 11.1KB 的图, 压完之后变成了 13.2KB。因为 JPEG 这种格式它是有固定的开销的, 图的体积越小、内容越是简单, 这个开销占的比例就越高, 所以小图在压缩之后反而变大, 这其实是一个正常现象。所以在脚本里增加了判断逻辑, 如果遇到压缩之后比原来的文件还大的情况, 就会放弃继续压缩, 直接进行原样复制, 并且把这个文件放入结果文件夹里面。你拿到的结果文件夹是已经处理过的, 其中保证里面的每一张图片的体积都比原来小, 不会比原来的大。第二个坑是动图还有带透明通道的图, 容易翻车。把GIF动图强行压成JPG格式, 最后得到的结果只剩下画面第一帧的内容, 动画效果就这样没了。如果是一个带透明背景的PNG图片, 把它压缩成JPG格式以后, 原本透明的区域就会变成白色。假设你拿这张图是要叠加到其他图片上的当作素材使用, 经过这么一压缩, 它就彻底废掉了。所以在进行压缩操作之前一定要想清楚具体的用途是什么。如果是那些打算发到聊天软件里、传送到文档中或者是用来发帖子的图片, 尽管放心去压缩。而设计素材以及动态图片这些类型, 坚决不要压缩。如果想要去保留那个透明的通道, 把图像的格式换成是 WebP, 这其实是另外一回事儿, 这篇文章就不把它展开来讲了。第三个需要留意的陷阱是, 在操作的时候不要一次性放进太多不同类别的文件夹里面去。目前的脚本工具它只会根据文件的扩展名来做识别, 所以没有办法区分出哪些图片是重要的资料。如果你把像「素材库」或者是「家庭相册原片」这种包含大量内容的文件夹直接放进去运行程序, 那么最终生成的将会是整个文件夹对应的压缩版本, 到时候你需要花费不少时间和精力来分辨出哪些文件才是真正用得上的。因此建议大家按照具体的用途来把这些文件夹分开进行处理: 比如针对用于记录聊天信息的截图文件夹, 完全可以放心地使用压缩功能而专门存放各种设计或创作资料的素材库, 则需要把它单独发送到另一个指定的输出目录下进行压缩, 这样就能确保两个方面的内容不会出现混合在一起的情况。去和那些在线的压缩网站做一个比较, 对比一番。有的人就会发起询问: 通过搜索名为「图片压缩」的关键词, 能够直接获得数量众多的网站, 只需要将这些文件拖拽进入相应的页面即可完成操作, 那么为什么还要去做编写代码的工作呢。我拿出三个实实在在的不同点来列出。第一个问题是关于隐私安全的。所谓在线压缩, 其实质操作就是要把图像数据上传到别人的服务器设备上去进行处理。当你把聊天内容的截图、身份证件的照片或者是工作需要的资料传上去的那一个瞬间, 这些资料的管控权就不再归你所有了, 你无法再控制它们后续的命运。与之相对的是在本地运行那些脚本程序的模式, 在这种模式下, 图像文件从开始处理到最后完成, 整个过程都没有离开过你自己电脑的硬盘存储区域。第二点是存在限制的情况。市面上那些免费的在线工具, 通常会规定单张图片的最大文件大小是多少, 还会限制每天能够使用的总次数, 更常见的是会给处理后的图片加上水印。假设有二百张需要处理的图片, 这类平台可能允许一次性上传十张图片, 那么用户就得分二十个批次去轮流上传。对于自动化脚本而言, 它们并不理解这些人为设定的规则概念, 无论是图片尺寸多大、数量一共有多少张, 都可以直接执行程序进行处理, 而无需遵循那些繁琐的限制条件。第三点是处于可控状态。那个等于80的档位完全是由你自己设定的, 如果你想要施加更严厉的压制, 只需要更换一个数字, 然后重新运行一遍程序即可。而那些在线工具则只给你提供高清、标准以及极致这三个按钮, 对于它们背后具体对应多少数值的问题, 你是无从知晓的, 同时你也没有任何办法去进行修改。对于那种一年之内只会用到两三次甚至更多的偶尔性需求, 在线工具是比较适合的去做的选择。但是只要是你这里边有着几百张图片都处在等着被去处理的那种情况的话, 本地脚本就是更为省事的一种途径所在。请问设置为80这一数值的话, 会不会存在画面不清晰的情况。这是一个被问得最多的问题, 直接把结论说出来: 在对于把东西发出去给别人看的这种场景里面, 这个是足够的。我这批一共 28 张, 全都是界面截图。文字边缘、按钮圆角以及小图标都还在里面。我压缩完成之后, 把放大以后的图片挨个看过, 对比了一下结果。在正常查看的尺寸下, 完全分不出哪一张是被压缩过的照片。等到把它放大到百分之四百去看文字边缘的时候, 能够看出有一点点发软的现象。但是现实中没有人会把聊天里的图片放大到百分之一百零四去仔细看。这个分布情况也挺有意思的。省最多的一张, 文件从 326KB 压到了 104KB, 节省了百分之六十八。大多数的压缩率, 都落在百分之二十到百分之五十五之间。还有几张小的文件, 几乎没节省空间。这是因为原文件越小, 能压缩出的空间就越小, 这是由格式开销所决定的下限。所以, 别指望每个文件夹都能节省一半的空间。图片越大, 内容越复杂, 压缩率才会越可观。真正不能够进行压缩处理的场景, 那就是印刷以及设计输出。如果你要拿图片去做海报的打印工作或者是当作设计稿里面的原始素材, 请务必使用无损格式来保存这些文件的原件, 千万不要去对这些文件进行修改或者压缩操作。这里有一个建议的用法, 就是把原件留在原地充当底稿, 然后把压缩版拿出来进行日常使用。因为这个脚本的输出方式是特意按照这个思路来设计的, 所以压缩后的结果会放在单独的一个文件夹里面, 两者之间彼此互不干扰。两个高频疑问大家是不是觉得, 微信这个东西不就自动带有压缩格式的功能嘛? 其实它是有的, 但是它的运作方向并不对我们所需求的那种方向。具体来讲, 就是在你把图片发送出去的那个时候, 它会对图片进行一次压缩处理, 而你设备本地存储的那些原始大小的文件依然保持着原来的庞大体积, 你的硬盘可用空间完全没有得到节省, 唯一的结果就是你发给对方的那些图片变得模糊不清了。而这个脚本所做的事情完全不同, 这个脚本主要针对的是你硬盘里面已经存下来的那些文件进行尺寸和容量的缩减, 它所节省下来的是属于你自己个人硬盘的空间, 这和之前说的那种情况完全是两回事。如果你在处理完所有图片之后, 突然想要把它们重新切换回原来的状态, 结果就是根本没法换回去。因为 JPEG 是一种有损压缩的文件格式, 那些在压缩过程中丢失掉的细节信息, 再也无法找回来了。所以咱们这个工具脚本才特别设计成了这样一种模式, 也就是会把处理好的文件输出到一个新开辟的文件夹里面, 而原来存放的文件一个都不会动。那个原原本本的原始文件, 其实就是你可以随时后悔并恢复的依据。在进行大批量的批量操作之前, 先留好原始的底稿。养成这样的习惯, 其实就等价于请朋友吃一顿饭的花费成本。手机里的相册功能能够正常使用吗? 处理思路是一致的, 但是在手机端进行操作会显得非常折腾。解决相册问题的通用办法是把图片文件迁移至计算机终端进行压缩处理, 然后再传输回手机设备之中。或者也可以直接使用手机系统自带的应用程序里提供的云存储优化选项, 这种方式下云端保存的是原始画质照片而本地设备中仅保留压缩后的低版本副本, 两者的底层逻辑相同, 但通常需要用户购买会员服务才能解锁该功能。完整代码存成 压图片.pyimport osimport shutilimport sysfrom PIL import ImageEXTS {.png, .jpg, .jpeg, .bmp, .webp}OUT_NAME 压缩后def human(n):for unit in [B, KB, MB, GB]:if n 1024:return f{n:.1f}{unit}n / 1024return f{n:.1f}TBdef main():root sys.argv[1] if len(sys.argv) 1 else .out_dir os.path.join(root, OUT_NAME)os.makedirs(out_dir, exist_okTrue)before_total after_total 0n 0for name in sorted(os.listdir(root)):p os.path.join(root, name)if not os.path.isfile(p) or os.path.splitext(name)[1].lower() not in EXTS:continuetry:im Image.open(p)im.load()except OSError:continuestem os.path.splitext(name)[0]dst os.path.join(out_dir, stem .jpg)im.convert(RGB).save(dst, JPEG, quality80, optimizeTrue)b, a os.path.getsize(p), os.path.getsize(dst)if a b: # 压完反而更大放弃原样带走os.remove(dst)shutil.copy2(p, os.path.join(out_dir, name))a bbefore_total bafter_total an 1print(f{name} {human(b)} - {human(a)} 省{(1 - a / b) * 100:.0f}%)if n:saved 1 - after_total / before_totalprint(- * 50)print(f共 {n} 张{human(before_total)} - {human(after_total)}f整体省 {saved * 100:.0f}%输出在 {OUT_NAME} 文件夹)if __name__ __main__:main()######请注意, 此脚本仅限于处理位于顶层文件夹中的图像文件, 它不会向下钻取到子文件夹里去执行操作, 这一做法的主要目的在于防止发生意外损坏或者误伤了不该动到的东西。如果你想要压缩某一个特定的文件夹, 那么就让该脚本来对这个指定的文件夹运行即可。请你使用自己那个文件夹, 这个文件夹里面被塞满了各种各样的截图, 你要对它进行一轮运行操作, 然后在评论区里面报告一下, 你自己总共节省了多少时间或者精力。
阅读完成 · 觉得有帮助?