Python調(diào)用PIL庫實現(xiàn)圖片格式轉(zhuǎn)換工具
要運行該程序,需要使用第三方庫PIL(pillow),詳情可見Python的圖像處理庫Pillow安裝與使用教程
格式支持:
支持常見圖片格式轉(zhuǎn)換(JPEG, PNG, BMP, GIF, TIFF, WEBP)
轉(zhuǎn)換設(shè)置:
- 可調(diào)整輸出圖片質(zhì)量(1-100)
- 支持尺寸調(diào)整(可保持寬高比,保持寬高比時,只需輸入寬度或高度中的一個即可自動計算另一個維度)
- 可選是否保留元數(shù)據(jù)(EXIF信息)
輸出選項:
- 自定義輸出路徑
- 自動生成新文件名(保留原文件名)
使用方法:
(1)通過"添加文件"或"添加文件夾"按鈕選擇圖片
(2)設(shè)置輸出格式和保存路徑(若不指定輸出路徑默認(rèn)原文件路徑)
(3)根據(jù)需要調(diào)整圖片質(zhì)量和尺寸
(4)點擊"開始轉(zhuǎn)換"按鈕進行轉(zhuǎn)換
若輸出路徑有同名文件提示提供三個選項:
是:覆蓋當(dāng)前文件
否:跳過當(dāng)前文件
取消:中止整個轉(zhuǎn)換過程
注意事項:
- 轉(zhuǎn)換透明背景圖片到不支持透明的格式(如JPEG)時,背景會被自動填充為白色
- 質(zhì)量設(shè)置對不同的格式效果不同(JPEG使用標(biāo)準(zhǔn)質(zhì)量參數(shù),PNG使用壓縮級別)
- 保持寬高比時,只需輸入寬度或高度中的一個即可自動計算另一個維度
運行界面如下:

源碼如下:
import os
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from PIL import Image
from pathlib import Path
SUPPORTED_FORMATS = ["JPEG", "PNG", "BMP", "GIF", "TIFF", "WEBP"]
class ImageConverterApp:
def __init__(self, root):
self.root = root
self.root.title("圖片格式轉(zhuǎn)換工具")
self.root.geometry("800x600")
# 初始化變量
self.selected_files = []
self.output_format = tk.StringVar(value="JPEG")
self.output_path = tk.StringVar()
self.quality = tk.IntVar(value=85)
self.resize_enabled = tk.BooleanVar(value=False)
self.new_width = tk.IntVar(value=0)
self.new_height = tk.IntVar(value=0)
self.keep_ratio = tk.BooleanVar(value=True)
self.keep_metadata = tk.BooleanVar(value=False)
self.create_widgets()
def create_widgets(self):
# 文件選擇區(qū)域
file_frame = ttk.LabelFrame(self.root, text="選擇圖片")
file_frame.pack(padx=10, pady=5, fill="x")
ttk.Button(file_frame, text="添加文件", command=self.add_files).pack(side="left", padx=5)
ttk.Button(file_frame, text="添加文件夾", command=self.add_folder).pack(side="left", padx=5)
ttk.Button(file_frame, text="清空列表", command=self.clear_files).pack(side="right", padx=5)
# 文件列表
self.file_list = tk.Listbox(self.root, selectmode=tk.EXTENDED)
self.file_list.pack(padx=10, pady=5, fill="both", expand=True)
# 設(shè)置區(qū)域
settings_frame = ttk.LabelFrame(self.root, text="轉(zhuǎn)換設(shè)置")
settings_frame.pack(padx=10, pady=5, fill="x")
# 輸出格式
ttk.Label(settings_frame, text="輸出格式:").grid(row=0, column=0, sticky="w")
format_combo = ttk.Combobox(settings_frame, textvariable=self.output_format,
values=SUPPORTED_FORMATS, state="readonly")
format_combo.grid(row=0, column=1, padx=5, sticky="ew")
# 輸出路徑
ttk.Label(settings_frame, text="輸出路徑:").grid(row=1, column=0, sticky="w")
ttk.Entry(settings_frame, textvariable=self.output_path).grid(row=1, column=1, columnspan=2, padx=5, sticky="ew")
ttk.Button(settings_frame, text="瀏覽...", command=self.select_output_path).grid(row=1, column=3, padx=5)
# 質(zhì)量設(shè)置
ttk.Label(settings_frame, text="圖片質(zhì)量 (1-100):").grid(row=2, column=0, sticky="w")
ttk.Scale(settings_frame, from_=1, to=100, variable=self.quality,
command=lambda v: self.quality.set(int(float(v)))).grid(row=2, column=1, padx=5, sticky="ew")
ttk.Label(settings_frame, textvariable=self.quality).grid(row=2, column=2, padx=5)
# 尺寸調(diào)整
resize_frame = ttk.Frame(settings_frame)
resize_frame.grid(row=3, column=0, columnspan=3, sticky="ew", pady=5)
ttk.Checkbutton(resize_frame, text="調(diào)整尺寸", variable=self.resize_enabled).pack(side="left", padx=5)
ttk.Entry(resize_frame, textvariable=self.new_width, width=5).pack(side="left", padx=5)
ttk.Label(resize_frame, text="x").pack(side="left")
ttk.Entry(resize_frame, textvariable=self.new_height, width=5).pack(side="left", padx=5)
ttk.Checkbutton(resize_frame, text="保持比例", variable=self.keep_ratio).pack(side="left", padx=5)
# 其他選項
ttk.Checkbutton(settings_frame, text="保留元數(shù)據(jù)", variable=self.keep_metadata).grid(row=4, column=0, columnspan=3, sticky="w")
# 操作按鈕
button_frame = ttk.Frame(self.root)
button_frame.pack(padx=10, pady=10, fill="x")
ttk.Button(button_frame, text="開始轉(zhuǎn)換", command=self.start_conversion).pack(side="right", padx=5)
ttk.Button(button_frame, text="退出", command=self.root.destroy).pack(side="right", padx=5)
def add_files(self):
files = filedialog.askopenfilenames(
filetypes=[("圖片文件", "*.jpg *.jpeg *.png *.bmp *.gif *.tiff *.webp")]
)
if files:
self.selected_files.extend(files)
self.update_file_list()
def add_folder(self):
folder = filedialog.askdirectory()
if folder:
for ext in ("*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.tiff", "*.webp"):
self.selected_files.extend(Path(folder).glob(ext))
self.update_file_list()
def clear_files(self):
self.selected_files = []
self.file_list.delete(0, tk.END)
def update_file_list(self):
self.file_list.delete(0, tk.END)
for f in self.selected_files:
self.file_list.insert(tk.END, str(f))
def select_output_path(self):
path = filedialog.askdirectory()
if path:
self.output_path.set(path)
def start_conversion(self):
if not self.selected_files:
messagebox.showwarning("警告", "請先選擇要轉(zhuǎn)換的圖片文件!")
return
output_path = self.output_path.get() or os.path.dirname(self.selected_files[0])
output_format = self.output_format.get()
# 創(chuàng)建輸出目錄(如果不存在)
os.makedirs(output_path, exist_ok=True)
for file_path in self.selected_files:
try:
img = Image.open(file_path)
# 處理尺寸調(diào)整
if self.resize_enabled.get():
width = self.new_width.get()
height = self.new_height.get()
original_width, original_height = img.size
if self.keep_ratio.get():
if width > 0 and height == 0:
ratio = width / original_width
height = int(original_height * ratio)
elif height > 0 and width == 0:
ratio = height / original_height
width = int(original_width * ratio)
else:
ratio = min(width/original_width, height/original_height)
width = int(original_width * ratio)
height = int(original_height * ratio)
if width > 0 and height > 0:
img = img.resize((width, height), Image.Resampling.LANCZOS)
# 構(gòu)建輸出路徑
filename = os.path.splitext(os.path.basename(file_path))[0]
output_file = os.path.join(output_path, f"{filename}.{output_format.lower()}")
# 檢查文件是否存在并提示
if os.path.exists(output_file):
response = messagebox.askyesnocancel(
"文件已存在",
f"目標(biāo)文件已存在:\n{output_file}\n\n"
"請選擇操作:\n"
"? 是:覆蓋當(dāng)前文件\n"
"? 否:跳過當(dāng)前文件\n"
"? 取消:中止全部轉(zhuǎn)換",
parent=self.root
)
if response is None: # 取消
return
if not response: # 跳過
continue
# 構(gòu)建輸出路徑
filename = os.path.splitext(os.path.basename(file_path))[0]
output_file = os.path.join(output_path, f"{filename}.{output_format.lower()}")
# 保存參數(shù)
save_args = {'format': output_format}
if output_format == 'JPEG':
save_args['quality'] = self.quality.get()
save_args['optimize'] = True
elif output_format == 'PNG':
save_args['compress_level'] = 9 - int(self.quality.get() / 11.1)
# 保存圖片
if not self.keep_metadata.get():
img.info.pop('exif', None)
img.save(output_file, **save_args)
except Exception as e:
messagebox.showerror("錯誤", f"處理文件 {file_path} 時出錯:\n{str(e)}")
continue
messagebox.showinfo("完成", "圖片轉(zhuǎn)換完成!")
if __name__ == "__main__":
root = tk.Tk()
app = ImageConverterApp(root)
root.mainloop()到此這篇關(guān)于Python調(diào)用PIL庫實現(xiàn)圖片格式轉(zhuǎn)換工具的文章就介紹到這了,更多相關(guān)Python PIL圖片格式轉(zhuǎn)換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實現(xiàn)將多個文件的名稱或后綴名由大寫改為小寫
這篇文章主要介紹了如何基于Python語言實現(xiàn)將多個文件的名稱或后綴名由大寫字母修改為小寫,文中的示例代碼講解詳細(xì),感興趣的可以了解下2023-09-09
python腳本調(diào)用iftop 統(tǒng)計業(yè)務(wù)應(yīng)用流量的思路詳解
這篇文章主要介紹了python腳本調(diào)用iftop 統(tǒng)計業(yè)務(wù)應(yīng)用流量的思路詳解,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10
Python中如何使用sqlite3操作SQLite數(shù)據(jù)庫詳解
這篇文章主要介紹了Python中SQLite數(shù)據(jù)庫的使用,包括連接數(shù)據(jù)庫、創(chuàng)建表、數(shù)據(jù)增刪改查、事務(wù)管理和參數(shù)化查詢等,并提供了操作示例,需要的朋友可以參考下2025-03-03
python 利用已有Ner模型進行數(shù)據(jù)清洗合并代碼
今天小編就為大家分享一篇python 利用已有Ner模型進行數(shù)據(jù)清洗合并代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12

