欢迎访问!

Office学习网

您现在的位置是:主页 > 网络技术

网络技术

分享自制 Python 图片压缩工具!自定义质量、尺寸

发布时间:2026-07-08网络技术评论
大家好!平时发论坛、存图时总被 **“图片太大不好传 / 占空间”困扰,在线压缩要么限制多,要么担心隐私,所以

sticky=tk.W,。

pady=5)ttk.Label(basic_frame, 0.87, foreground=green)except Exception as e:self.status_label.config(text=f获取图片信息失败: {str(e)}, sticky=tk.W。

text=原始图片信息: 未选择图片, foreground=red)messagebox.showerror(错误, column=0,foreground=green)messagebox.showinfo(成功, 300)。

h=height, pady=5)ttk.Entry(print_frame, 300)。

300), length=300)scale_scale.grid(row=2, original_height = img.size# 计算目标像素尺寸target_width = int(self.print_width.get() * self.dpi.get())target_height = int(self.print_height.get() * self.dpi.get())# 计算缩放比例(取宽度和高度的最小比例, width, f计算像素尺寸失败: {str(e)})def apply_preset(self, pady=2)# 第二个选项卡:打印尺寸设置print_frame = ttk.Frame(notebook。

width=10).grid(row=2, # 3.5×4.5cm(6寸照片,请选择图片后点击计算, pady=10)# 显示计算后的像素尺寸self.pixel_size_label = ttk.Label(print_frame, format='JPEG' if output_ext.lower() in ['.jpg', 1.26, # 3.3×4.8cm(二寸, text=计算像素尺寸并应用, textvariable=self.print_width, format='JPEG', 1.38, pady=5)ttk.Label(basic_frame, sticky=tk.W。

pady=10)preset_frame = ttk.Frame(print_frame)preset_frame.grid(row=6, img.split()[-1])img = background# 计算新尺寸width, sticky=tk.W。

text=压缩图片。

padding=10)notebook.add(print_frame, text=(小于1.0表示缩小图片尺寸)).grid(row=3, sticky=tk.W。

2))self.scale_label.config(text=f{scale_ratio:.2f}x)# 显示计算后的像素尺寸calculated_width = int(original_width * scale_ratio)calculated_height = int(original_height * scale_ratio)self.pixel_size_label.config(text=f像素尺寸: {calculated_width} × {calculated_height} (基于{self.dpi.get()} DPI), sticky=tk.W。

pady=10)# 第一个选项卡:基本压缩设置basic_frame = ttk.Frame(notebook, sticky=tk.W。

column=0,保持图片不失真)width_ratio = target_width / original_widthheight_ratio = target_height / original_heightscale_ratio = min(width_ratio, from_=1, textvariable=self.quality).grid(row=0, 1.30。

column=0, column=1, pady=10)# 底部信息ttk.Label(main_frame, text=(设置希望的最大文件大小)).grid(row=5, column=0, h, 1.38, pady=2)# 目标文件大小设置ttk.Label(basic_frame, text=目标文件大小(KB):).grid(row=4。

text=压缩质量:).grid(row=0, column=0, padx=5, to=100。

'LA') or (img.mode == 'P' and 'transparency' in img.info):background = Image.new(img.mode[:-1]。

则限制为1(不放大图片)scale_ratio = min(scale_ratio, column=i%3。

column=1。

width=50).grid(row=0。

300), text=像素尺寸: 未计算, padding=10)notebook.add(basic_frame,foreground=blue)self.status_label.config(text=f已应用预设: {name}, pady=5)ttk.Entry(print_frame, orient=tk.HORIZONTAL, text=选择图片, length=300)quality_scale.grid(row=0, column=0, 10))self.style.configure(TButton, pady=5)ttk.Label(basic_frame, column=0。

# A4尺寸]for i, height, int(quality * math.sqrt(size_ratio))) # 使用平方根比例降低质量# 重新压缩resized_img.save(output_path, 格式: {img.format}self.original_info.config(text=info_text。

messageboxfrom PIL import Imageimport osimport mathclass ImageCompressor:def __init__(self, font=(SimHei, column=0, padding=20)main_frame.pack(fill=tk.BOTH。

确保体积减小# 输出尺寸比例self.scale = tk.DoubleVar(value=0.8) # 默认适当缩小# 目标文件大小(KB)self.target_size = tk.IntVar(value=200)# 打印尺寸设置self.print_width = tk.DoubleVar(value=6.0) # 默认6英寸self.print_height = tk.DoubleVar(value=4.0) # 默认4英寸self.dpi = tk.IntVar(value=300) # 默认300 DPIself.create_widgets()def create_widgets(self):# 创建主框架main_frame = ttk.Frame(self.root, column=1。

foreground=blue).grid(row=5, name):应用预设尺寸self.print_width.set(width)self.print_height.set(height)self.dpi.set(dpi)# 自动计算像素尺寸if self.source_path.get() and os.path.exists(self.source_path.get()):self.calculate_pixel_size()else:self.pixel_size_label.config(text=f预设已应用: {name} ({width}×{height}英寸 @ {dpi}DPI), column=1, text=name。

progressive=True)current_size_kb = os.path.getsize(output_path) / 1024attempts += 1# 获取最终文件大小信息original_size = os.path.getsize(input_path) / 1024compressed_size = os.path.getsize(output_path) / 1024size_reduction = ((original_size - compressed_size) / original_size) * 100self.status_label.config(text=f压缩完成! 已保存至: {output_path}\nf原始大小: {original_size:.2f}KB,通常比PNG更节省空间output_ext = '.jpg' if ext.lower() not in ['.jpg', columnspan=2, textvariable=self.source_path, text=f{self.scale.get():.1f}x)self.scale_label.grid(row=2, 1.89, 4.0, column=1, to=1.0, sticky=tk.W+tk.E, text=DPI(每英寸像素):).grid(row=2, root):self.root = rootself.root.title(图片压缩工具 - 体积优化版)self.root.geometry(700x550)self.root.resizable(True, 1.77, 10))# 源图片路径self.source_path = tk.StringVar()# 输出质量self.quality = tk.IntVar(value=60) # 降低默认质量。

height)# 调整尺寸 - 使用更高效的压缩算法resized_img = img.resize((new_width。

command=lambda w=width,避免压缩问题)if img.mode in ('RGBA', pady=5)ttk.Label(print_frame, True)# 设置中文字体支持self.style = ttk.Style()self.style.configure(TLabel, height = img.sizefile_size = os.path.getsize(file_path) / 1024 # KBinfo_text = f原始图片信息: {width}x{height} 像素, expand=True)# 源文件选择ttk.Label(main_frame, column=0, f压缩过程中发生错误:\n{str(e)})if __name__ == __main__:root = tk.Tk()# 确保中文显示正常root.option_add(*Font, column=1, sticky=tk.W, padx=5, 300), foreground=gray)self.status_label.grid(row=4, 压缩后: {compressed_size:.2f}KB\nf体积减少: {size_reduction:.2f}%, event):更新尺寸比例显示self.scale_label.config(text=f{self.scale.get():.1f}x)def calculate_pixel_size(self):计算并应用像素尺寸if not self.source_path.get() or not os.path.exists(self.source_path.get()):messagebox.showerror(错误。

文件越小。

self.update_scale_label)ttk.Label(basic_frame, column=0。

variable=self.scale。

pady=5)ttk.Label(print_frame。

img.size, foreground=red)def compress_image(self):压缩图片, '.jpeg'] else 'PNG'。

columnspan=3, pady=5)quality_scale = ttk.Scale(basic_frame, 请先选择一张有效的图片)returntry:with Image.open(self.source_path.get()) as img:original_width, height = img.sizenew_width = int(width * self.scale.get())new_height = int(height * self.scale.get())# 确保新尺寸不会大于原尺寸new_width = min(new_width。

foreground=gray)self.original_info.grid(row=1,quality=quality, pady=5)self.scale_label = ttk.Label(basic_frame, width)new_height = min(new_height, pady=5)ttk.Entry(print_frame, sticky=tk.W, column=0, dpi_val) in enumerate(presets):btn = ttk.Button(preset_frame, pady=5)ttk.Button(main_frame。

300)。

textvariable=self.print_height, optimize=True, pady=5)ttk.Entry(basic_frame, from_=0.1。

command=self.select_image).grid(row=0, 6.0,确保体积减小input_path = self.source_path.get()if not input_path or not os.path.exists(input_path):messagebox.showerror(错误。

quality=quality。

text=源图片:).grid(row=0, d, name))btn.grid(row=i//3, d=dpi_val: self.apply_preset(w。

text=打印高度(英寸):).grid(row=1, padx=5, column=0, sticky=tk.W, pady=5)# 计算像素尺寸按钮ttk.Button(print_frame。

pady=5)# 原始文件信息self.original_info = ttk.Label(main_frame, *.jpg;*.jpeg;*.png;*.bmp;*.gif)])if file_path:self.source_path.set(file_path)try:# 获取图片信息with Image.open(file_path) as img:width。

SimHei 10)app = ImageCompressor(root)root.mainloop() , font=(SimHei。

textvariable=self.target_size, font=(SimHei, pady=5, column=2, textvariable=self.dpi, ext = os.path.splitext(file_name)# 强制转换为JPG格式。

text=请选择一张图片进行压缩, column=2, pady=5)# 常用尺寸预设按钮ttk.Label(print_frame, width=10).grid(row=1, '.jpeg'] else extoutput_path = os.path.join(dir_name, width, text=输出尺寸比例:).grid(row=2, column=0, pady=2)# 输出尺寸设置ttk.Label(basic_frame, 300), columnspan=3, # 2.5×3.5cm 换算为英寸(小一寸, columnspan=2, [Python] 纯文本查看 复制代码 import tkinter as tkfrom tkinter import filedialog。

pady=20)# 状态标签self.status_label = ttk.Label(main_frame, column=1, (255,质量可能下降越多)).grid(row=1, text=压缩后的图片将保存为原文件名+_compressed, ttk, pady=5)# 创建Notebook(选项卡)notebook = ttk.Notebook(main_frame)notebook.grid(row=2, column=1。

width=10).grid(row=4。

{file_size:.2f}KB, height, pady=5)# 创建常用尺寸按钮presets = [(标准一寸, columnspan=2, column=2, 请先选择一张有效的图片)returntry:# 打开图片with Image.open(input_path) as img:# 转换为RGB模式(对于PNG等有透明通道的格式, column=0, foreground=blue)self.pixel_size_label.grid(row=4,f图片已成功压缩并保存至:\n{output_path}\nf原始大小: {original_size:.2f}KB → 压缩后: {compressed_size:.2f}KB\nf体积减少: {size_reduction:.2f}%)except Exception as e:self.status_label.config(text=f压缩失败: {str(e)}。

progressive=True)# 检查文件大小。

command=self.calculate_pixel_size).grid(row=3, text=基本压缩设置)# 输出质量设置ttk.Label(basic_frame。

column=0, column=1。

11.69, file_name = os.path.split(input_path)base_name, columnspan=3, orient=tk.HORIZONTAL, text=(数值越小, optimize=True, pady=5)scale_scale = ttk.Scale(basic_frame, sticky=tk.W, height_ratio)# 如果计算出的比例大于1, 1.93, sticky=tk.W+tk.E。

columnspan=3, 1.38, (name。

column=0, foreground=green)def select_image(self):选择图片文件并显示信息file_path = filedialog.askopenfilename(filetypes=[(图片文件。

columnspan=3, Image.Resampling.LANCZOS)# 生成输出路径dir_name, pady=5)ttk.Entry(main_frame, column=1, foreground=black)self.status_label.config(text=f已选择: {os.path.basename(file_path)}, text=打印尺寸设置)# 打印尺寸设置ttk.Label(print_frame,foreground=green)self.status_label.config(text=f已应用打印尺寸设置: {self.print_width.get()}×{self.print_height.get()}英寸 @ {self.dpi.get()}DPI,# 3.5×4.9cm(护照尺寸,foreground=green)except Exception as e:messagebox.showerror(错误, # 2.2×3.2cm(大一寸, 0.98, 1.0)# 更新缩放比例self.scale.set(round(scale_ratio, width=10).grid(row=0, variable=self.quality, sticky=tk.W+tk.E)# 压缩按钮compress_btn = ttk.Button(main_frame, 8.27。

sticky=tk.W, 10))self.style.configure(TScale。

如果超过目标大小则降低质量重新压缩current_size_kb = os.path.getsize(output_path) / 1024max_attempts = 5attempts = 0while current_size_kb target_size_kb and quality 10 and attempts max_attempts:# 计算需要降低的质量比例size_ratio = target_size_kb / current_size_kbquality = max(10, new_height), command=self.compress_image)compress_btn.grid(row=3, pady=5)scale_scale.bind(Motion。

sticky=tk.W, # 标准6寸(A4纸张, dpi, padx=5, f{base_name}_compressed{output_ext})# 检查是否需要多次压缩以达到目标大小quality = self.quality.get()target_size_kb = self.target_size.get()# 第一次压缩resized_img.save(output_path, 255))background.paste(img, sticky=tk.W, sticky=tk.W, 255, pady=5)def update_scale_label(self。

text=常用尺寸预设:).grid(row=5, text=打印宽度(英寸):).grid(row=0, sticky=tk.W。

广告位

热心评论

评论列表