本文目录导读:

我来帮您设计一个可以控制输出文件大小的图片压缩工具,以下是几种实现方案:
基于质量的迭代压缩(最常用)
from PIL import Image
import os
def compress_to_target_size(image_path, target_size_kb, output_path=None):
"""
将图片压缩到目标大小(KB)
Args:
image_path: 原图路径
target_size_kb: 目标大小(KB)
output_path: 输出路径(可选)
"""
if output_path is None:
name, ext = os.path.splitext(image_path)
output_path = f"{name}_compressed{ext}"
img = Image.open(image_path)
# 保存原格式,如果不是JPEG则转换为JPEG
if img.format != 'JPEG':
img = img.convert('RGB')
output_path = output_path.replace('.png', '.jpg').replace('.webp', '.jpg')
# 二分法查找合适的质量参数
target_size_bytes = target_size_kb * 1024
min_quality = 1
max_quality = 95
while min_quality <= max_quality:
mid_quality = (min_quality + max_quality) // 2
# 临时保存以检查大小
import io
buffer = io.BytesIO()
img.save(buffer, format='JPEG', quality=mid_quality, optimize=True)
current_size = buffer.tell()
if current_size < target_size_bytes:
min_quality = mid_quality + 1
elif current_size > target_size_bytes:
max_quality = mid_quality - 1
else:
break
# 保存最终结果
img.save(output_path, format='JPEG', quality=mid_quality, optimize=True)
actual_size = os.path.getsize(output_path) / 1024
print(f"压缩完成!质量: {mid_quality}%, 大小: {actual_size:.2f}KB")
return output_path
# 使用示例
compress_to_target_size("input.jpg", 500) # 压缩到500KB
支持多种格式的全功能压缩
from PIL import Image
import os
import io
class ImageCompressor:
"""全能图片压缩器"""
def __init__(self, max_iterations=20, tolerance=0.1):
self.max_iterations = max_iterations
self.tolerance = tolerance # 允许的误差范围(10%)
def compress_to_target(self, input_path, target_size_kb, output_path=None):
"""压缩图片到目标大小"""
if output_path is None:
name, ext = os.path.splitext(input_path)
output_path = f"{name}_compressed_{target_size_kb}kb{ext}"
img = Image.open(input_path)
img_format = img.format or 'JPEG'
# 转换为RGB(处理RGBA图片)
if img.mode in ('RGBA', 'LA', 'P'):
rgb_img = Image.new('RGB', img.size, (255, 255, 255))
rgb_img.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
img = rgb_img
target_bytes = target_size_kb * 1024
self.original_size = os.path.getsize(input_path) / 1024
print(f"原图大小: {self.original_size:.2f}KB")
# 策略1:调整质量(JPEG)
if img_format in ('JPEG', 'JPG'):
result_path = self._compress_jpeg(img, output_path, target_bytes)
else:
# 策略2:调整尺寸+质量
result_path = self._compress_other_formats(img, output_path, target_bytes)
actual_size = os.path.getsize(result_path) / 1024
print(f"压缩完成: {actual_size:.2f}KB (目标: {target_size_kb}KB)")
return result_path
def _compress_jpeg(self, img, output_path, target_bytes):
"""JPEG图片压缩"""
quality = 95
best_quality = quality
for _ in range(self.max_iterations):
buffer = io.BytesIO()
img.save(buffer, format='JPEG', quality=quality, optimize=True)
size = buffer.tell()
if abs(size - target_bytes) / target_bytes <= self.tolerance:
break
elif size > target_bytes:
quality = max(1, quality - 5)
best_quality = quality
else:
quality = min(95, quality + 5)
img.save(output_path, format='JPEG', quality=best_quality, optimize=True)
return output_path
def _compress_other_formats(self, img, output_path, target_bytes):
"""其他格式图片压缩(先调整尺寸)"""
width, height = img.size
scale = 1.0
for _ in range(self.max_iterations):
new_width = int(width * scale)
new_height = int(height * scale)
resized_img = img.resize((new_width, new_height), Image.LANCZOS)
buffer = io.BytesIO()
resized_img.save(buffer, format='JPEG', quality=85, optimize=True)
size = buffer.tell()
if abs(size - target_bytes) / target_bytes <= self.tolerance:
break
elif size > target_bytes:
scale *= 0.8
else:
break
output_path = output_path.rsplit('.', 1)[0] + '.jpg'
resized_img.save(output_path, format='JPEG', quality=85, optimize=True)
return output_path
# 使用示例
compressor = ImageCompressor()
compressor.compress_to_target("input.png", 300) # 压缩到300KB
WebP格式(更高效的压缩)
from PIL import Image
import os
def compress_to_webp(image_path, target_size_kb, output_path=None):
"""转换为WebP格式并控制大小"""
if output_path is None:
name = os.path.splitext(image_path)[0]
output_path = f"{name}.webp"
img = Image.open(image_path)
target_bytes = target_size_kb * 1024
# WebP支持很好的压缩率
quality = 80
for _ in range(20):
import io
buffer = io.BytesIO()
img.save(buffer, format='WEBP', quality=quality, method=6)
size = buffer.tell()
if abs(size - target_bytes) / target_bytes < 0.05:
break
elif size > target_bytes:
quality -= 5
else:
quality += 5
quality = max(1, min(100, quality))
img.save(output_path, format='WEBP', quality=quality, method=6)
print(f"WebP压缩完成: {os.path.getsize(output_path)/1024:.2f}KB")
return output_path
GUI工具(简易版)
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image
import os
class ImageCompressorGUI:
def __init__(self):
self.root = tk.Tk()
self.root.title("图片压缩工具")
self.root.geometry("400x300")
# 文件选择
tk.Label(self.root, text="选择图片:").pack(pady=10)
self.file_path = tk.StringVar()
tk.Entry(self.root, textvariable=self.file_path, width=50).pack()
tk.Button(self.root, text="浏览", command=self.select_file).pack()
# 目标大小
tk.Label(self.root, text="目标大小 (KB):").pack(pady=10)
self.target_size = tk.IntVar(value=200)
tk.Scale(self.root, from_=10, to=1000, orient="horizontal",
variable=self.target_size).pack()
# 压缩按钮
tk.Button(self.root, text="开始压缩", command=self.compress,
bg="blue", fg="white", font=("Arial", 12)).pack(pady=20)
# 状态显示
self.status_label = tk.Label(self.root, text="")
self.status_label.pack()
self.root.mainloop()
def select_file(self):
filename = filedialog.askopenfilename(
filetypes=[("图片文件", "*.jpg *.jpeg *.png *.webp")]
)
if filename:
self.file_path.set(filename)
def compress(self):
if not self.file_path.get():
messagebox.showerror("错误", "请选择图片文件")
return
try:
target_kb = self.target_size.get()
# 调用上面的压缩函数
output_path = compress_to_target_size(self.file_path.get(), target_kb)
self.status_label.config(text=f"压缩完成!保存为: {output_path}")
except Exception as e:
messagebox.showerror("错误", str(e))
# 运行GUI
# ImageCompressorGUI()
使用建议
-
选择合适的格式:
- JPEG:适合照片,控制质量参数
- WebP:比JPEG压缩率高30%
- PNG:适合带透明度的图像
-
平衡质量与大小:
- 一般图片质量设置在80-85%即可
- 如果需要精确控制,使用二分法迭代
-
性能优化:
# 多线程批量处理 from concurrent.futures import ThreadPoolExecutor def batch_compress(image_list, target_size_kb): with ThreadPoolExecutor(max_workers=4) as executor: futures = [] for img_path in image_list: future = executor.submit(compress_to_target_size, img_path, target_size_kb) futures.append(future) for future in futures: future.result()
这个工具可以根据需要灵活调整,既能精确控制文件大小,又能保持良好的图像质量。
标签: 指定大小
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播