【Python】PIL 压缩图片刚好 200KB

编程入门 行业动态 更新时间:2024-10-28 06:26:33

【Python】PIL 压缩<a href=https://www.elefans.com/category/jswz/34/1770705.html style=图片刚好 200KB"/>

【Python】PIL 压缩图片刚好 200KB

问题来源

今天遇到一个特别奇葩的需求,甲方要求我把图片制作成刚好 200KB,天啦撸。这这这怎么可能,理论上只能压缩到接近于目标大小。但,干了兄弟萌。

解决思路

压缩图片至低于目标大小,再把差的部分全部填充 “0”。

核心内容

核心内容是如何补齐,以下提供两种思路:

  1. 第一种(save):
    ① 打开图片文件并转换为 BytesIO
    ② 计算 (目标大小 - 压缩后大小) 的差值, 并用 “\x00” 补足
    ③ 保存
  2. 第二种(save2):
    ① cmd 生成一个指定大小的文件
    ② 将压缩后的二进制流写入生成的文件

代码

文件结构
main.py
| - - new
| - - old
| - - | - - test.jpg

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# main.pyfrom PIL import Image
from io import BytesIO
from os import system
from os import listdir
from os import remove
from os.path import getsize
from os.path import exists__author__ = 'one-ccs'"""
功能: 把 ".\old" 目录下的所有图片压缩并填充至 200KB 后存放在 ".\new" 目录下.
"""settings = {'loadPath': r'.\old',  # 待压缩图片路径'savePath': r'.\new',  # 保存路径'size': 200,'quality': 90
}class ImageFixCompressor():def __init__(self) -> None:self.imgBytes = Noneself.imgPath = Noneself.name = Noneself.oldSize = 0self.newSize = 0self.saveSize = 0self.format = 'JPEG'self.targetSize = 200 # 目标大小 (KB)self.quality = 90     # 压缩比率 若压缩后图片大于目标大小应减小该值def split_path(self, path:str='') -> tuple:"""提取 path 中的路径与文件名."""if not isinstance(path, str):raise ValueError(f'参数 "path" 的数据类型应该为 "str", 但是传入了 "{type(path)}" 类型.')# 判断是否是以 '/' '\' 作为目录分隔符flag = path[::-1].find('/')if flag == -1:flag = path[::-1].find('\\')if flag == -1:raise ValueError(f'参数 "path" 的数据类型应该为 "str", 但是传入了 "{type(path)}" 类型.')name = path[-flag:]path = path[:-flag]return (path, name)def full_path(self, path) -> str:return fr'{path}\{self.name}'def open(self, imgPath:str) -> None:"""打开图像文件:参数 imgPath: 图片文件路径."""try:_, self.name = self.split_path(imgPath)self.oldSize = getsize(imgPath)self.image = Image.open(imgPath)print(f'打开: "{imgPath}" 成功; 大小: {self.oldSize / 1024:.2f} KB.')except Exception as e:print(f'错误: 文件 "{imgPath}" 打开失败; 原因: "{e}".')def show(self) -> None:self.image.show()def compress(self, format='JPEG', quality=None) -> None:if format == 'PNG' or format == 'png':self.format = 'PNG'if quality:self.quality = qualityself.image.tobytes()self.imageBuffer = BytesIO()self.image.save(self.imageBuffer, format=self.format, quality=self.quality)def save(self, savePath:str, cover:bool=False, name=None) -> None:if cover:mode = 'wb+'else:mode = 'rb+'try:self.newSize = self.imageBuffer.tell() / 1024# ~ 补齐大小for i in range(0, self.targetSize * 1024 - self.imageBuffer.tell()):self.imageBuffer.write(b'\x00')with open(self.full_path(savePath), mode) as fb:fb.write(self.imageBuffer.getvalue())self.saveSize = getsize(self.full_path(savePath)) / 1024print(fr'保存: "{self.full_path(savePath)}" 成功; 压缩大小: {self.newSize:.2f} KB; 保存大小: {self.saveSize:.2f} KB.')except Exception as e:print(f'错误: "{self.name}" 保存失败; 原因: "{e}".')def save2(self, savePath:str, cover:bool=False, name=None) -> None:if cover:if exists(self.full_path(savePath)):remove(self.full_path(savePath))else:print(f'异常: 文件 "{savePath}" 已存在, 已放弃保存.')returnsystem('@echo off')system(f'fsutil file createnew {self.full_path(savePath)} {self.targetSize * 1024}')try:with open(self.full_path(savePath), 'rb+') as fb:fb.write(self.imageBuffer.getvalue())self.newSize = self.imageBuffer.tell() / 1024self.saveSize = getsize(self.full_path(savePath)) / 1024print(fr'保存: "{self.full_path(savePath)}" 成功; 压缩大小: {self.newSize:.2f} KB; 保存大小: {self.saveSize:.2f} KB.')except Exception as e:print(f'错误: "{self.name}" 保存失败; 原因: "{e}".')def main(args):compressor = ImageFixCompressor()oldImgPaths = listdir(settings['loadPath'])for oldImgPath in oldImgPaths:fullPath = f"{settings['loadPath']}\{oldImgPath}"compressor.open(fullPath)compressor.compress()compressor.save(settings['savePath'], cover=True)# ~ returnreturn 0if __name__ == '__main__':import syssys.exit(main(sys.argv))

【如果觉得本文不错 “点赞、收藏、关注”,是对作者最大的鼓励。】

更多推荐

【Python】PIL 压缩图片刚好 200KB

本文发布于:2023-07-28 18:44:48,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1278163.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:图片   PIL   Python   KB

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!