最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Python自制一個圖片批量處理工具實現(xiàn)格式統(tǒng)一和大小壓縮

 更新時間:2025年11月03日 08:30:43   作者:Jack電子實驗室  
在日常工作和生活中,我們經(jīng)常需要處理大量圖片,今天就給大家分享一款自制的Python圖片批量處理工具,無需復雜操作,圖形化界面一鍵搞定所有需求

在日常工作和生活中,我們經(jīng)常需要處理大量圖片——比如電商商品圖需要統(tǒng)一正方形尺寸、公眾號配圖要控制在3MB以內(nèi)、多格式圖片需轉為JPG統(tǒng)一管理。手動處理幾十上百張圖效率極低,今天就給大家分享一款自制的Python圖片批量處理工具,無需復雜操作,圖形化界面一鍵搞定所有需求!

工具核心功能

這款工具專為批量圖片處理設計,整合了4個高頻需求,徹底解放雙手:

  • 正方形轉換:自動將任意尺寸圖片轉為正方形,短邊兩側填充白色背景,避免拉伸變形
  • 格式統(tǒng)一:支持PNG、JPG、BMP、GIF、WebP等多種格式,統(tǒng)一輸出為JPG格式
  • 大小壓縮:智能控制圖片大小在3MB以內(nèi),自動平衡質(zhì)量與體積,避免失真
  • 安全處理:原圖保持不變,處理后的圖片自動保存到新文件夾,杜絕誤操作

環(huán)境準備

1. 基礎環(huán)境

  • Python 3.6 及以上版本(推薦3.8+,兼容性更好)
  • tkinter 庫(Python標準庫,默認已預裝,無需額外安裝)

2. 依賴安裝

核心依賴僅需Pillow庫(Python圖像處理神器),打開命令行執(zhí)行以下命令:

pip install pillow

如果需要批量安裝,也可以創(chuàng)建requirements.txt文件,寫入以下內(nèi)容后執(zhí)行pip install -r requirements.txt

pillow>=9.0.0

完整代碼(可直接復制運行)

import os
import sys
from PIL import Image
import time
from io import BytesIO
import tkinter as tk
from tkinter import filedialog, ttk, messagebox
import threading
import queue

# 打包命令:pyinstaller --noconsole --onefile --icon=icon.ico --name="圖片批量處理工具" image_processor.py
class ImageProcessor:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("圖片批量處理工具")
        # 設置窗口大小和位置(居中顯示)
        window_width = 800
        window_height = 600
        screen_width = self.window.winfo_screenwidth()
        screen_height = self.window.winfo_screenheight()
        x = (screen_width - window_width) // 2
        y = (screen_height - window_height) // 2
        self.window.geometry(f"{window_width}x{window_height}+{x}+{y}")
        self.window.resizable(False, False)
        
        # 界面樣式配置(現(xiàn)代簡潔風格)
        self.style = ttk.Style()
        self.style.theme_use('clam')
        self.style.configure("TButton", padding=10, font=('微軟雅黑', 10))
        self.style.configure("TLabel", font=('微軟雅黑', 10))
        self.style.configure("Header.TLabel", font=('微軟雅黑', 16, 'bold'))
        self.style.configure("Info.TLabel", font=('微軟雅黑', 9))
        self.style.configure("Custom.TButton", padding=10, font=('微軟雅黑', 10, 'bold'))
        
        # 線程通信隊列(避免界面卡頓)
        self.message_queue = queue.Queue()
        
        self.create_widgets()
        self.update_messages()
    
    def create_widgets(self):
        # 主框架(統(tǒng)一內(nèi)邊距,布局更整潔)
        main_frame = ttk.Frame(self.window, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 標題區(qū)域
        title_frame = ttk.Frame(main_frame)
        title_frame.pack(fill=tk.X, pady=(0, 20))
        title_label = ttk.Label(title_frame, text="圖片批量處理工具", style="Header.TLabel")
        title_label.pack(side=tk.LEFT)
        
        # 功能說明區(qū)域
        features_frame = ttk.LabelFrame(main_frame, text="功能說明", padding="10")
        features_frame.pack(fill=tk.X, pady=(0, 20))
        features_text = """本工具提供以下功能:
? 將圖片轉換為正方形(短邊兩側填充白色)
? 統(tǒng)一轉換為JPG格式,保證最佳圖片質(zhì)量
? 智能控制圖片大小在3MB以下
? 自動創(chuàng)建輸出文件夾,原圖保持不變"""
        features_label = ttk.Label(features_frame, text=features_text, justify=tk.LEFT)
        features_label.pack(pady=5)
        
        # 文件夾選擇區(qū)域
        folder_frame = ttk.LabelFrame(main_frame, text="選擇文件夾", padding="10")
        folder_frame.pack(fill=tk.X, pady=(0, 20))
        self.folder_path = tk.StringVar()
        folder_entry = ttk.Entry(folder_frame, textvariable=self.folder_path, width=70)
        folder_entry.pack(side=tk.LEFT, padx=(0, 10), fill=tk.X, expand=True)
        folder_button = ttk.Button(folder_frame, text="瀏覽...", command=self.select_folder, style="Custom.TButton")
        folder_button.pack(side=tk.LEFT)
        
        # 操作按鈕區(qū)域
        control_frame = ttk.Frame(main_frame)
        control_frame.pack(fill=tk.X, pady=(0, 10))
        self.process_button = ttk.Button(control_frame, text="開始處理", 
                                       command=self.start_processing, 
                                       style="Custom.TButton")
        self.process_button.pack(pady=10)
        
        # 進度顯示區(qū)域
        progress_frame = ttk.LabelFrame(main_frame, text="處理進度", padding="10")
        progress_frame.pack(fill=tk.X, pady=(0, 20))
        self.progress_var = tk.DoubleVar()
        self.progress_bar = ttk.Progressbar(progress_frame, 
                                          variable=self.progress_var, 
                                          maximum=100,
                                          length=300)
        self.progress_bar.pack(fill=tk.X, pady=(5, 10))
        self.progress_label = ttk.Label(progress_frame, text="等待開始...", style="Info.TLabel")
        self.progress_label.pack()
        
        # 處理詳情日志區(qū)域
        log_frame = ttk.LabelFrame(main_frame, text="處理詳情", padding="10")
        log_frame.pack(fill=tk.BOTH, expand=True)
        text_frame = ttk.Frame(log_frame)
        text_frame.pack(fill=tk.BOTH, expand=True)
        self.log_text = tk.Text(text_frame, height=10, width=70, 
                               font=('微軟雅黑', 9),
                               wrap=tk.WORD)
        self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar = ttk.Scrollbar(text_frame, orient=tk.VERTICAL, 
                                command=self.log_text.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.log_text.configure(yscrollcommand=scrollbar.set)
        
        # 狀態(tài)欄
        self.status_label = ttk.Label(main_frame, text="就緒", style="Info.TLabel")
        self.status_label.pack(pady=(10, 0))
    
    def select_folder(self):
        # 選擇文件夾并更新路徑
        folder_path = filedialog.askdirectory(title="選擇包含圖片的文件夾")
        if folder_path:
            self.folder_path.set(folder_path)
            self.log_message(f"已選擇文件夾: {folder_path}")
            self.status_label.config(text="已選擇文件夾,可以開始處理")
    
    def log_message(self, message):
        # 日志信息入隊(線程安全)
        self.message_queue.put(message)
    
    def update_messages(self):
        # 實時更新日志顯示
        try:
            while True:
                message = self.message_queue.get_nowait()
                self.log_text.insert(tk.END, message + "\n")
                self.log_text.see(tk.END)
                self.log_text.update()
        except queue.Empty:
            pass
        self.window.after(100, self.update_messages)
    
    def start_processing(self):
        # 預處理校驗(避免無效操作)
        folder_path = self.folder_path.get()
        if not folder_path:
            messagebox.showerror("錯誤", "請先選擇要處理的文件夾!")
            return
        if not os.path.exists(folder_path):
            messagebox.showerror("錯誤", "選擇的文件夾不存在!")
            return
        
        # 禁用按鈕防止重復點擊
        self.process_button.state(['disabled'])
        self.status_label.config(text="正在處理中...")
        self.progress_label.config(text="正在準備處理...")
        
        # 開啟子線程處理圖片(避免界面凍結)
        thread = threading.Thread(target=self.process_images_thread, args=(folder_path,))
        thread.daemon = True
        thread.start()
    
    def process_images_thread(self, input_folder):
        try:
            # 支持的圖片格式(覆蓋主流格式)
            supported_formats = ['.png', '.jpeg', '.jpg', '.bmp', '.gif', '.webp']
            
            # 創(chuàng)建輸出文件夾(原文件夾名+“調(diào)整”)
            dir_name = os.path.basename(input_folder)
            output_dir_name = dir_name + "調(diào)整"
            parent_dir = os.path.dirname(input_folder)
            output_dir = os.path.join(parent_dir, output_dir_name)
            try:
                os.makedirs(output_dir, exist_ok=True)
            except Exception as e:
                self.log_message(f"創(chuàng)建輸出文件夾失?。簕str(e)}")
                messagebox.showerror("錯誤", f"創(chuàng)建輸出文件夾失?。簕str(e)}")
                return
            
            # 篩選圖片文件
            image_files = [f for f in os.listdir(input_folder) 
                         if any(f.lower().endswith(fmt) for fmt in supported_formats)]
            if not image_files:
                self.log_message("沒有找到支持的圖片文件!")
                messagebox.showinfo("提示", "文件夾中沒有找到支持的圖片文件!")
                return
            
            # 初始化統(tǒng)計參數(shù)
            total_files = len(image_files)
            processed_files = 0
            success_count = 0
            error_count = 0
            size_reduced_count = 0
            total_size_saved = 0
            
            # 日志初始化
            self.log_message(f"\n開始處理圖片...")
            self.log_message(f"輸入目錄: {input_folder}")
            self.log_message(f"輸出目錄: {output_dir}\n")
            self.log_message(f"共發(fā)現(xiàn) {total_files} 個圖片文件\n")
            
            # 批量處理圖片
            for filename in image_files:
                file_path = os.path.join(input_folder, filename)
                try:
                    # 更新進度
                    processed_files += 1
                    progress = (processed_files / total_files) * 100
                    self.progress_var.set(progress)
                    self.progress_label.config(
                        text=f"正在處理: {filename} ({processed_files}/{total_files})"
                    )
                    
                    # 打開圖片并處理
                    with Image.open(file_path) as img:
                        # 保留EXIF信息(避免圖片方向異常)
                        exif = img.info.get('exif')
                        
                        # 處理透明背景(PNG轉JPG時填充白色)
                        if img.mode in ('RGBA', 'P'):
                            background = Image.new('RGB', img.size, 'white')
                            if img.mode == 'P':
                                img = img.convert('RGBA')
                            background.paste(img, mask=img.split()[3] if img.mode == 'RGBA' else None)
                            img = background
                        
                        # 轉為正方形
                        square_img = self.convert_to_square(img)
                        if square_img is None:
                            continue
                        
                        # 生成輸出路徑
                        new_filename = os.path.splitext(filename)[0] + '.jpg'
                        new_path = os.path.join(output_dir, new_filename)
                        
                        # 計算大小變化
                        original_size = os.path.getsize(file_path) / (1024 * 1024)
                        
                        # 優(yōu)化圖片大?。刂圃?MB內(nèi))
                        quality = self.optimize_image_size(square_img)
                        
                        # 保存圖片
                        save_args = {'format': 'JPEG', 'quality': quality}
                        if exif:
                            save_args['exif'] = exif
                        square_img.save(new_path, **save_args)
                        
                        # 更新統(tǒng)計信息
                        new_size = os.path.getsize(new_path) / (1024 * 1024)
                        success_count += 1
                        if new_size < original_size:
                            size_reduced_count += 1
                            size_reduction = original_size - new_size
                            total_size_saved += size_reduction
                            self.log_message(f"? 已處理: {filename} -> {new_filename}")
                            self.log_message(
                                f"  大小: {original_size:.1f}MB → {new_size:.1f}MB "
                                f"(節(jié)省 {size_reduction:.1f}MB)"
                            )
                        else:
                            self.log_message(f"? 已處理: {filename} -> {new_filename}")
                            self.log_message(f"  大小: {new_size:.1f}MB")
                
                except Exception as e:
                    error_count += 1
                    self.log_message(f"? 處理 {filename} 時出錯: {str(e)}")
            
            # 輸出處理總結
            summary = f"""\n處理完成!
----------------------------------------
成功處理:{success_count} 個文件
處理失?。簕error_count} 個文件
文件大小優(yōu)化:{size_reduced_count} 個文件
總共節(jié)省空間:{total_size_saved:.1f}MB
輸出文件夾:{output_dir}
----------------------------------------"""
            self.log_message(summary)
            
            # 彈窗提示結果
            if success_count > 0:
                messagebox.showinfo("完成", 
                    f"圖片處理完成!\n成功:{success_count} 個\n失?。簕error_count} 個")
            else:
                messagebox.showwarning("警告", "沒有成功處理任何文件!")
        
        except Exception as e:
            self.log_message(f"處理過程出錯:{str(e)}")
            messagebox.showerror("錯誤", f"處理過程出錯:{str(e)}")
        
        finally:
            # 恢復界面狀態(tài)
            self.process_button.state(['!disabled'])
            self.progress_var.set(0)
            self.progress_label.config(text="處理完成")
            self.status_label.config(text="就緒")
    
    def convert_to_square(self, image):
        """將圖片轉為正方形,最大尺寸限制800x800(避免過大)"""
        try:
            width, height = image.size
            max_size = max(width, height)
            
            # 縮放過大圖片
            if max_size > 800:
                scale = 800 / max_size
                new_width = int(width * scale)
                new_height = int(height * scale)
                image = image.resize((new_width, new_height), Image.LANCZOS)  # 高質(zhì)量縮放
                width, height = image.size
                max_size = max(width, height)
            
            # 創(chuàng)建白色正方形背景
            square_img = Image.new('RGB', (max_size, max_size), 'white')
            
            # 居中粘貼原圖
            paste_x = (max_size - width) // 2 if height > width else 0
            paste_y = (max_size - height) // 2 if width > height else 0
            square_img.paste(image, (paste_x, paste_y))
            return square_img
        except Exception as e:
            self.log_message(f"轉換圖片時出錯:{str(e)}")
            return None
    
    def get_file_size(self, img, quality):
        """計算指定質(zhì)量下的圖片大?。ㄗ止?jié))"""
        buffer = BytesIO()
        img.save(buffer, format='JPEG', quality=quality)
        size = buffer.tell()
        buffer.close()
        return size
    
    def optimize_image_size(self, img, max_size_mb=2.9):
        """二分查找最優(yōu)質(zhì)量,確保圖片<3MB(留0.1MB冗余)"""
        max_size_bytes = int(max_size_mb * 1024 * 1024)
        quality = 95
        current_size = self.get_file_size(img, quality)
        
        # 原圖已達標,直接返回高質(zhì)量
        if current_size <= max_size_bytes:
            return quality
        
        # 二分查找最優(yōu)質(zhì)量
        min_quality = 5
        max_quality = 95
        best_quality = max_quality
        while min_quality <= max_quality:
            quality = (min_quality + max_quality) // 2
            current_size = self.get_file_size(img, quality)
            if current_size > max_size_bytes:
                max_quality = quality - 1
            else:
                best_quality = quality
                min_quality = quality + 1
        
        # 最終校驗(確保不超標)
        final_size = self.get_file_size(img, best_quality)
        while final_size > max_size_bytes and best_quality > 5:
            best_quality -= 1
            final_size = self.get_file_size(img, best_quality)
        
        return best_quality
    
    def run(self):
        # 啟動GUI
        self.window.mainloop()

def main():
    app = ImageProcessor()
    app.run()

if __name__ == '__main__':
    main()

使用教程(超簡單!)

運行程序

將上述代碼保存為`image_processor.py

到此這篇關于基于Python自制一個圖片批量處理工具實現(xiàn)格式統(tǒng)一和大小壓縮的文章就介紹到這了,更多相關Python圖片批量處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 理解深度學習之深度學習簡介

    理解深度學習之深度學習簡介

    這篇文章主要是關于深度學習的簡介,對大家學習了解機器深度學習有一定的幫助,以后會持續(xù)更新本系列,希望能為大家?guī)硪恍┦肇?,讓我們一起來看看下面的文章?/div> 2021-04-04
  • Python入門指南之代碼注釋的三種寫法詳解

    Python入門指南之代碼注釋的三種寫法詳解

    本文詳細介紹了Python中的三種代碼注釋方式及其最佳實踐,主要內(nèi)容包括單行注釋(#),多行注釋('''或""")和文檔字符串(docstring),感興趣的小伙伴可以跟隨小編一起學習一下
    2026-06-06
  • Python?Ruby?等語言棄用自增運算符原因剖析

    Python?Ruby?等語言棄用自增運算符原因剖析

    這篇文章主要為大家介紹了Python?Ruby?等語言棄用自增運算符原因剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • 使用Django和Ansible實現(xiàn)自動化部署方式

    使用Django和Ansible實現(xiàn)自動化部署方式

    這篇文章主要介紹了使用Django和Ansible實現(xiàn)自動化部署方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • Centos 升級到python3后pip 無法使用的解決方法

    Centos 升級到python3后pip 無法使用的解決方法

    今天小編就為大家分享一篇Centos 升級到python3后pip 無法使用的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • Python?sklearn庫三種常用編碼格式實例

    Python?sklearn庫三種常用編碼格式實例

    這篇文章主要為大家介紹了Python?sklearn庫三種常用編碼格式實例展示,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 從基礎到高級詳解Python文本對齊完全指南

    從基礎到高級詳解Python文本對齊完全指南

    在數(shù)據(jù)處理和展示領域,文本對齊是提升可讀性和專業(yè)性的關鍵技術,本文將深入解析Python文本對齊技術體系,從基礎方法到高級應用,需要的可以了解下
    2025-08-08
  • 開始著手第一個Django項目

    開始著手第一個Django項目

    這篇文章主要介紹了開始著手第一個Django項目的過程,Django是豐富多彩的Python框架中人氣最高的一個,功能多而全,需要的朋友可以參考下
    2015-07-07
  • Pandas 如何篩選包含特定字符的列

    Pandas 如何篩選包含特定字符的列

    這篇文章主要介紹了Pandas 如何篩選包含特定字符的列,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Python lambda匿名函數(shù)深入講解

    Python lambda匿名函數(shù)深入講解

    lambda所表示的匿名函數(shù)的內(nèi)容應該是很簡單的,如果復雜的話,干脆就重新定義一個函數(shù)了,使用lambda就有點過于執(zhí)拗了。lambda就是用來定義一個匿名函數(shù)的,如果還要給他綁定一個名字的話,就會顯得有點畫蛇添足,通常是直接使用lambda函數(shù)
    2023-01-01

最新評論

阳曲县| 乃东县| 乌恰县| 石泉县| 江津市| 滨海县| 章丘市| 临夏县| 资兴市| 临沂市| 萨嘎县| 合江县| 客服| 化德县| 新竹县| 金阳县| 柳州市| 延吉市| 乌审旗| 阳江市| 板桥市| 睢宁县| 绥宁县| 武清区| 万全县| 天门市| 黔江区| 泽普县| 会宁县| 龙江县| 桦南县| 连城县| 微山县| 广宁县| 泰宁县| 淄博市| 金华市| 浦城县| 瑞金市| 灌云县| 九寨沟县|