2025年2月7日
- 将大于5mb的jpg格式的照片压缩到5mb以下
- 代码为
import os from PIL import Image def compress_image_if_needed(image_path, max_size_mb=5): # 获取图片的原始大小 original_size_mb = os.path.getsize(image_path) / (1024 * 1024) # 如果图片超过最大限制,则进行压缩 if original_size_mb > max_size_mb: # 打开图片 img = Image.open(image_path) # 计算新的质量 quality = 95 while quality > 20 and os.path.getsize(image_path) / (1024 * 1024) > max_size_mb: # 保存图片到临时文件 temp_path = image_path + '.temp' img.save(temp_path, 'JPEG', quality=quality) # 如果临时文件小于或等于最大大小,则替换原文件 if os.path.getsize(temp_path) / (1024 * 1024) <= max_size_mb: # 删除掉源文件 os.remove(image_path) # 将临时文件的名称修改成源文件 os.rename(temp_path, image_path) else: # 否则,删除临时文件 os.remove(temp_path) quality -= 5 print( f"图片 {image_path} 已压缩至 {quality + 5}% 质量,大小为 {os.path.getsize(image_path) / (1024 * 1024):.2f} MB") else: print(f"图片 {image_path} 大小为 {original_size_mb:.2f} MB,无需压缩")
- 函数定义:
def compress_image_if_needed(image_path, max_size_mb=5):
:定义了一个名为compress_image_if_needed的函数,接受两个参数:image_path(图片文件的路径)和max_size_mb(允许的最大文件大小,单位为MB,默认值为5MB)。
- 获取图片原始大小:
original_size_mb = os.path.getsize(image_path) / (1024 * 1024)
:使用os.path.getsize函数获取图片的原始文件大小(以字节为单位),然后将其转换为MB以便于比较。
- 判断是否需要压缩:
if original_size_mb > max_size_mb:
:判断图片的原始大小是否超过了允许的最大文件大小。如果超过了,则需要压缩图片。
- 打开图片文件:
img = Image.open(image_path):
使用PIL库中的Image.open方法打开图片文件,以便后续进行压缩处理。
- 压缩图片过程:
quality = 95
:初始化图片的质量为95%。while quality > 20 and os.path.getsize(image_path) / (1024 * 1024) > max_size_mb:
:使用一个while循环来不断尝试压缩图片,直到图片大小不超过最大文件大小或质量降低到20%为止。img.save(temp_path, 'JPEG', quality=quality)
:使用PIL库中的save方法将图片以JPEG格式保存,质量设置为当前的quality值。os.remove(image_path)
:如果压缩后的图片大小满足要求,则删除原始图片文件。os.remove(temp_path)
:无论是否满足要求,都会删除临时文件,因为在这个代码片段中,临时文件和原始文件的路径是相同的。quality -= 5
:每次循环中将质量降低5%,以尝试进一步减小图片大小。
- 输出压缩结果:
print(f"图片 {image_path} 已压缩至 {quality + 5}% 质量,大小为 {os.path.getsize(image_path) / (1024 * 1024):.2f} MB")
:如果图片经过压缩后满足大小要求,则打印压缩后的图片质量和文件大小。print(f"图片 {image_path} 大小为 {original_size_mb:.2f} MB,无需压缩")
:如果图片的原始大小已经满足要求,则直接打印图片的原始大小,并提示无需压缩。
- 如何批量压缩图片
- 批量调用代码为
def find_files(directory, extension): for root, dirs, files in os.walk(directory): for file in files: if file.endswith(extension): # print(os.path.join(root, file)) compress_image_if_needed(os.path.join(root, file))
- 函数定义:
def find_files(directory, extension):
- find_files 是函数的名称。
- directory 是参数,表示要搜索的目录路径。
- extension 是参数,表示要查找的文件扩展名,例如 .jpg 或 .png。
- 遍历目录树:
for root, dirs, files in os.walk(directory):
- os.walk(directory) 是一个生成器,它会生成目录树中的所有目录和文件。
- root 表示当前正在遍历的目录路径。
- dirs 是一个列表,包含当前目录下的所有子目录名。
- files 是一个列表,包含当前目录下的所有文件名。
- 如何根据图片大小动态的调整压缩的步长
- 代码为
from PIL import Image import os def compress_image_if_needed(image_path,max_size_mb=5): # 获取图片的原始大小 original_size_mb = os.path.getsize(image_path) / (1024 * 1024) current_size_mb = original_size_mb # 如果图片超过最大限制,则进行压缩 if current_size_mb > max_size_mb: # 打开图片 img = Image.open(image_path) # 初始化质量 quality = 95 while quality > 20 and current_size_mb > max_size_mb: # 计算差距 size_diff = current_size_mb - max_size_mb # 根据差距动态调整步长 step = max(1,int(10*(size_diff/max_size_mb))) # 保存图片到临时文件 temp_path = image_path + '.temp' img.save(temp_path,'JPEG',quality=quality) # 检查临时文件的大小 current_size_mb = os.path.getsize(temp_path) / (1024 * 1024) # 如果临时文件小于或等于最大大小,则替换原文件 if current_size_mb <= max_size_mb: os.remove(image_path) os.rename(temp_path,image_path) else: os.remove(temp_path) quality -= step
- 上述代码中,自动调整步长的数学公式是:
step = max(1, int(10 * (size_diff / max_size_mb)))
size_diff
: 这是当前图片大小与最大允许大小之间的差距。step
: 这是每次压缩时减少的质量值。10 * (size_diff / max_size_mb)
: 这部分计算的是一个比例值,表示当前大小超出最大允许大小的比例。乘以10是为了将这个比例值放大到一个更合理的步长范围。int(...)
: 将比例值转换为整数,以便作为步长使用。max(1, ...)
: 确保步长至少为1。如果计算出的步长小于1,则直接使用1作为步长。
- 例如:
- 如果当前图片大小为10 MB,最大允许大小为5 MB,则 size_diff 为 5 MB。
- 计算步长时,10 * (5 / 5) 等于 10,所以 step 为 10。
- 如果当前图片大小为5.5 MB,最大允许大小为5 MB,则 size_diff 为 0.5 MB。
- 计算步长时,10 * (0.5 / 5) 等于 1,所以 step 为 1。