1. 首页
  2. python
  3. Python程序实现Logo图片尺寸转换

Python程序实现Logo图片尺寸转换

  • 发布于 2025-10-09
  • 2 次阅读

功能特点

  • 两种尺寸输出:自动生成28×28和108×108像素的PNG图片
  • 保持透明度:自动转换为RGBA模式支持透明背景
  • 高质量重采样:使用LANCZOS算法保持图片质量
  • 批量处理:支持处理整个目录的图片
  • 错误处理:完善的异常处理机制
  • 运行程序后,选择你的logo图片,程序会在同目录下的resized_logos文件夹中生成两个尺寸的新图片。

源码运行

方法1:处理单个文件
运行程序后,输入单个图片文件的路径,程序会生成两个尺寸的PNG文件。

方法2:批量处理
输入包含多个图片的目录路径,程序会处理目录中的所有图片文件。

from PIL import Image
import os

def resize_logo(input_path, output_dir="resized_logos"):
    """
    将logo图片转换为28x28像素和108x108像素的PNG格式图片
    
    参数:
    input_path: 输入图片路径
    output_dir: 输出目录
    """
    try:
        # 创建输出目录
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        
        # 打开原始图片
        with Image.open(input_path) as img:
            # 确保图片是RGBA模式(支持透明度)
            if img.mode != 'RGBA':
                img = img.convert('RGBA')
            
            # 获取文件名(不含扩展名)
            filename = os.path.splitext(os.path.basename(input_path))[0]
            
            # 尺寸列表
            sizes = [(28, 28), (108, 108)]
            
            # 转换并保存不同尺寸的图片
            for width, height in sizes:
                # 调整尺寸,使用LANCZOS重采样算法保持质量
                resized_img = img.resize((width, height), Image.Resampling.LANCZOS)
                
                # 生成输出文件名
                output_filename = f"{filename}_{width}x{height}.png"
                output_path = os.path.join(output_dir, output_filename)
                
                # 保存为PNG格式
                resized_img.save(output_path, 'PNG')
                print(f"已生成: {output_path}")
            
            print("所有尺寸转换完成!")
            
    except FileNotFoundError:
        print(f"错误:找不到文件 '{input_path}'")
    except Exception as e:
        print(f"处理图片时出错: {e}")

def batch_resize_logos(input_dir, output_dir="resized_logos"):
    """
    批量处理目录中的所有图片
    
    参数:
    input_dir: 输入图片目录
    output_dir: 输出目录
    """
    # 支持的图片格式
    supported_formats = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff', '.webp'}
    
    try:
        # 获取目录中的所有文件
        for filename in os.listdir(input_dir):
            file_path = os.path.join(input_dir, filename)
            
            # 检查是否是文件且为支持的图片格式
            if (os.path.isfile(file_path) and 
                os.path.splitext(filename)[1].lower() in supported_formats):
                
                print(f"\n处理文件: {filename}")
                resize_logo(file_path, output_dir)
                
    except FileNotFoundError:
        print(f"错误:找不到目录 '{input_dir}'")

if __name__ == "__main__":
    # 使用方法1:处理单个文件
    logo_path = input("请输入logo图片路径(直接回车跳过): ").strip()
    
    if logo_path:
        if os.path.exists(logo_path):
            resize_logo(logo_path)
        else:
            print("文件不存在,请检查路径")
    
    # 使用方法2:批量处理目录中的图片
    else:
        dir_path = input("请输入包含logo图片的目录路径: ").strip()
        if dir_path and os.path.exists(dir_path):
            batch_resize_logos(dir_path)
        else:
            print("目录不存在,程序结束")

tkinter

from PIL import Image
import os
import tkinter as tk
from tkinter import filedialog, messagebox, ttk

class LogoResizerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Logo尺寸转换器")
        self.root.geometry("500x300")
        
        # 创建界面
        self.create_widgets()
    
    def create_widgets(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="20")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 标题
        title_label = ttk.Label(main_frame, text="Logo图片尺寸转换器", 
                               font=("Arial", 16, "bold"))
        title_label.grid(row=0, column=0, columnspan=3, pady=(0, 20))
        
        # 选择文件按钮
        self.file_button = ttk.Button(main_frame, text="选择单个文件", 
                                     command=self.select_file)
        self.file_button.grid(row=1, column=0, padx=5, pady=10, sticky=tk.W+tk.E)
        
        # 选择目录按钮
        self.dir_button = ttk.Button(main_frame, text="选择目录批量处理", 
                                    command=self.select_directory)
        self.dir_button.grid(row=1, column=1, padx=5, pady=10, sticky=tk.W+tk.E)
        
        # 输出目录选择
        self.output_button = ttk.Button(main_frame, text="选择输出目录", 
                                       command=self.select_output_dir)
        self.output_button.grid(row=1, column=2, padx=5, pady=10, sticky=tk.W+tk.E)
        
        # 文件路径显示
        self.path_label = ttk.Label(main_frame, text="未选择文件或目录", 
                                   wraplength=400)
        self.path_label.grid(row=2, column=0, columnspan=3, pady=10)
        
        # 输出目录显示
        self.output_label = ttk.Label(main_frame, text="输出目录: resized_logos")
        self.output_label.grid(row=3, column=0, columnspan=3, pady=5)
        
        # 进度条
        self.progress = ttk.Progressbar(main_frame, mode='indeterminate')
        self.progress.grid(row=4, column=0, columnspan=3, sticky=tk.W+tk.E, pady=10)
        
        # 开始转换按钮
        self.convert_button = ttk.Button(main_frame, text="开始转换", 
                                        command=self.start_conversion)
        self.convert_button.grid(row=5, column=0, columnspan=3, pady=20, sticky=tk.W+tk.E)
        
        # 状态标签
        self.status_label = ttk.Label(main_frame, text="就绪")
        self.status_label.grid(row=6, column=0, columnspan=3)
        
        # 初始化变量
        self.input_path = ""
        self.output_path = "resized_logos"
        self.is_batch = False
    
    def select_file(self):
        file_path = filedialog.askopenfilename(
            title="选择Logo图片",
            filetypes=[("图片文件", "*.jpg *.jpeg *.png *.bmp *.gif *.tiff *.webp")]
        )
        if file_path:
            self.input_path = file_path
            self.path_label.config(text=f"选择文件: {file_path}")
            self.is_batch = False
    
    def select_directory(self):
        dir_path = filedialog.askdirectory(title="选择包含Logo图片的目录")
        if dir_path:
            self.input_path = dir_path
            self.path_label.config(text=f"选择目录: {dir_path}")
            self.is_batch = True
    
    def select_output_dir(self):
        dir_path = filedialog.askdirectory(title="选择输出目录")
        if dir_path:
            self.output_path = dir_path
            self.output_label.config(text=f"输出目录: {dir_path}")
    
    def resize_logo(self, input_path):
        """调整单个logo尺寸"""
        try:
            with Image.open(input_path) as img:
                if img.mode != 'RGBA':
                    img = img.convert('RGBA')
                
                filename = os.path.splitext(os.path.basename(input_path))[0]
                sizes = [(28, 28), (108, 108)]
                
                for width, height in sizes:
                    resized_img = img.resize((width, height), Image.Resampling.LANCZOS)
                    output_filename = f"{filename}_{width}x{height}.png"
                    output_filepath = os.path.join(self.output_path, output_filename)
                    resized_img.save(output_filepath, 'PNG')
            
            return True
        except Exception as e:
            print(f"处理 {input_path} 时出错: {e}")
            return False
    
    def start_conversion(self):
        if not self.input_path:
            messagebox.showerror("错误", "请先选择文件或目录")
            return
        
        # 创建输出目录
        if not os.path.exists(self.output_path):
            os.makedirs(self.output_path)
        
        # 开始进度条
        self.progress.start()
        self.convert_button.config(state='disabled')
        
        try:
            if self.is_batch:
                # 批量处理
                supported_formats = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff', '.webp'}
                success_count = 0
                total_count = 0
                
                for filename in os.listdir(self.input_path):
                    file_path = os.path.join(self.input_path, filename)
                    if (os.path.isfile(file_path) and 
                        os.path.splitext(filename)[1].lower() in supported_formats):
                        total_count += 1
                        if self.resize_logo(file_path):
                            success_count += 1
                
                self.status_label.config(text=f"批量处理完成: {success_count}/{total_count} 个文件成功")
                messagebox.showinfo("完成", f"批量处理完成!\n成功: {success_count}/{total_count} 个文件")
            
            else:
                # 单个文件处理
                if self.resize_logo(self.input_path):
                    self.status_label.config(text="转换完成")
                    messagebox.showinfo("完成", "图片转换完成!")
                else:
                    self.status_label.config(text="转换失败")
                    messagebox.showerror("错误", "图片转换失败")
        
        except Exception as e:
            messagebox.showerror("错误", f"处理过程中出错: {e}")
        
        finally:
            # 停止进度条
            self.progress.stop()
            self.convert_button.config(state='normal')

def main():
    root = tk.Tk()
    app = LogoResizerApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()

命令行版本(自定义尺寸)

from PIL import Image
import os

def resize_logo(input_path, sizes, output_dir="resized_logos"):
    """
    将logo图片转换为指定尺寸的PNG格式图片
    
    参数:
    input_path: 输入图片路径
    sizes: 尺寸列表,例如 [(28, 28), (108, 108), (200, 100)]
    output_dir: 输出目录
    """
    try:
        # 创建输出目录
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        
        # 打开原始图片
        with Image.open(input_path) as img:
            # 确保图片是RGBA模式(支持透明度)
            if img.mode != 'RGBA':
                img = img.convert('RGBA')
            
            # 获取文件名(不含扩展名)
            filename = os.path.splitext(os.path.basename(input_path))[0]
            
            # 转换并保存不同尺寸的图片
            for width, height in sizes:
                # 调整尺寸,使用LANCZOS重采样算法保持质量
                resized_img = img.resize((width, height), Image.Resampling.LANCZOS)
                
                # 生成输出文件名
                output_filename = f"{filename}_{width}x{height}.png"
                output_path = os.path.join(output_dir, output_filename)
                
                # 保存为PNG格式
                resized_img.save(output_path, 'PNG')
                print(f"已生成: {output_path}")
            
            print(f"所有尺寸转换完成!共生成 {len(sizes)} 个文件")
            
    except FileNotFoundError:
        print(f"错误:找不到文件 '{input_path}'")
    except Exception as e:
        print(f"处理图片时出错: {e}")

def batch_resize_logos(input_dir, sizes, output_dir="resized_logos"):
    """
    批量处理目录中的所有图片
    
    参数:
    input_dir: 输入图片目录
    sizes: 尺寸列表
    output_dir: 输出目录
    """
    # 支持的图片格式
    supported_formats = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff', '.webp'}
    
    try:
        # 获取目录中的所有文件
        files = [f for f in os.listdir(input_dir) 
                if os.path.isfile(os.path.join(input_dir, f)) and 
                os.path.splitext(f)[1].lower() in supported_formats]
        
        if not files:
            print("目录中没有找到支持的图片文件")
            return
        
        print(f"找到 {len(files)} 个图片文件")
        
        for filename in files:
            file_path = os.path.join(input_dir, filename)
            print(f"\n处理文件: {filename}")
            resize_logo(file_path, sizes, output_dir)
                
    except FileNotFoundError:
        print(f"错误:找不到目录 '{input_dir}'")

def parse_size_input(size_input):
    """
    解析用户输入的尺寸字符串
    支持格式: "28x28 108x108 200x100" 或 "28,28 108,108 200,100"
    """
    sizes = []
    try:
        # 按空格分割多个尺寸
        size_parts = size_input.strip().split()
        for part in size_parts:
            # 支持 x 或 , 作为分隔符
            if 'x' in part:
                w, h = part.split('x')
            elif ',' in part:
                w, h = part.split(',')
            else:
                print(f"忽略无效尺寸格式: {part}")
                continue
            
            width = int(w.strip())
            height = int(h.strip())
            
            if width <= 0 or height <= 0:
                print(f"忽略无效尺寸: {width}x{height}")
                continue
                
            sizes.append((width, height))
        
        return sizes
    except ValueError as e:
        print(f"尺寸解析错误: {e}")
        return []

def get_custom_sizes():
    """
    获取用户自定义尺寸
    """
    print("\n请输入您想要的图片尺寸(可以输入多个尺寸)")
    print("格式示例:")
    print("  - 28x28 108x108 200x100")
    print("  - 28,28 108,108 200,100")
    print("  - 50x50 100x100 200x200 300x300")
    
    while True:
        size_input = input("\n请输入尺寸(直接回车使用默认尺寸 28x28 和 108x108): ").strip()
        
        if not size_input:
            # 使用默认尺寸
            return [(28, 28), (108, 108)]
        
        sizes = parse_size_input(size_input)
        if sizes:
            return sizes
        else:
            print("输入格式有误,请重新输入")

if __name__ == "__main__":
    # 获取自定义尺寸
    custom_sizes = get_custom_sizes()
    
    print(f"\n将生成以下尺寸的图片:")
    for w, h in custom_sizes:
        print(f"  - {w}x{h}像素")
    
    # 选择处理模式
    print("\n请选择处理模式:")
    print("1. 处理单个文件")
    print("2. 批量处理目录")
    
    choice = input("请输入选择 (1 或 2): ").strip()
    
    if choice == "1":
        logo_path = input("请输入logo图片路径: ").strip()
        if logo_path and os.path.exists(logo_path):
            resize_logo(logo_path, custom_sizes)
        else:
            print("文件不存在,程序结束")
    elif choice == "2":
        dir_path = input("请输入包含logo图片的目录路径: ").strip()
        if dir_path and os.path.exists(dir_path):
            batch_resize_logos(dir_path, custom_sizes)
        else:
            print("目录不存在,程序结束")
    else:
        print("无效选择,程序结束")

图形界面版本(支持自定义尺寸)

from PIL import Image
import os
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import re

class LogoResizerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Logo尺寸转换器 - 自定义尺寸")
        self.root.geometry("600x450")
        
        # 初始化变量
        self.input_path = ""
        self.output_path = "resized_logos"
        self.is_batch = False
        self.sizes = [(28, 28), (108, 108)]  # 默认尺寸
        
        # 创建界面
        self.create_widgets()
    
    def create_widgets(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="20")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 标题
        title_label = ttk.Label(main_frame, text="Logo图片尺寸转换器 - 自定义尺寸", 
                               font=("Arial", 16, "bold"))
        title_label.grid(row=0, column=0, columnspan=3, pady=(0, 20))
        
        # 尺寸设置区域
        size_frame = ttk.LabelFrame(main_frame, text="自定义尺寸设置", padding="10")
        size_frame.grid(row=1, column=0, columnspan=3, sticky=tk.W+tk.E, pady=(0, 10))
        
        # 尺寸输入说明
        size_help = ttk.Label(size_frame, 
                             text="输入格式: 宽x高,多个尺寸用空格分隔\n示例: 28x28 108x108 200x100 300x150",
                             foreground="blue")
        size_help.grid(row=0, column=0, columnspan=2, sticky=tk.W, pady=(0, 10))
        
        # 尺寸输入框
        ttk.Label(size_frame, text="尺寸列表:").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.size_entry = ttk.Entry(size_frame, width=40)
        self.size_entry.insert(0, "28x28 108x108")
        self.size_entry.grid(row=1, column=1, sticky=tk.W+tk.E, padx=(10, 0), pady=5)
        
        # 更新尺寸按钮
        self.update_size_button = ttk.Button(size_frame, text="更新尺寸", 
                                            command=self.update_sizes)
        self.update_size_button.grid(row=1, column=2, padx=(10, 0), pady=5)
        
        # 当前尺寸显示
        self.size_display = ttk.Label(size_frame, text="当前尺寸: 28x28, 108x108")
        self.size_display.grid(row=2, column=0, columnspan=3, sticky=tk.W, pady=5)
        
        # 文件选择区域
        file_frame = ttk.LabelFrame(main_frame, text="文件选择", padding="10")
        file_frame.grid(row=2, column=0, columnspan=3, sticky=tk.W+tk.E, pady=10)
        
        # 选择文件按钮
        self.file_button = ttk.Button(file_frame, text="选择单个文件", 
                                     command=self.select_file)
        self.file_button.grid(row=0, column=0, padx=5, pady=5, sticky=tk.W+tk.E)
        
        # 选择目录按钮
        self.dir_button = ttk.Button(file_frame, text="选择目录批量处理", 
                                    command=self.select_directory)
        self.dir_button.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W+tk.E)
        
        # 输出目录选择
        self.output_button = ttk.Button(file_frame, text="选择输出目录", 
                                       command=self.select_output_dir)
        self.output_button.grid(row=0, column=2, padx=5, pady=5, sticky=tk.W+tk.E)
        
        # 文件路径显示
        self.path_label = ttk.Label(file_frame, text="未选择文件或目录", 
                                   wraplength=500)
        self.path_label.grid(row=1, column=0, columnspan=3, pady=5, sticky=tk.W)
        
        # 输出目录显示
        self.output_label = ttk.Label(file_frame, text="输出目录: resized_logos")
        self.output_label.grid(row=2, column=0, columnspan=3, pady=5, sticky=tk.W)
        
        # 进度条
        self.progress = ttk.Progressbar(main_frame, mode='indeterminate')
        self.progress.grid(row=3, column=0, columnspan=3, sticky=tk.W+tk.E, pady=10)
        
        # 开始转换按钮
        self.convert_button = ttk.Button(main_frame, text="开始转换", 
                                        command=self.start_conversion)
        self.convert_button.grid(row=4, column=0, columnspan=3, pady=10, sticky=tk.W+tk.E)
        
        # 状态标签
        self.status_label = ttk.Label(main_frame, text="就绪")
        self.status_label.grid(row=5, column=0, columnspan=3)
        
        # 配置列权重
        main_frame.columnconfigure(1, weight=1)
        size_frame.columnconfigure(1, weight=1)
        file_frame.columnconfigure(0, weight=1)
        file_frame.columnconfigure(1, weight=1)
        file_frame.columnconfigure(2, weight=1)
    
    def parse_size_input(self, size_input):
        """解析尺寸输入"""
        sizes = []
        try:
            if not size_input.strip():
                return [(28, 28), (108, 108)]
            
            # 按空格分割多个尺寸
            size_parts = size_input.strip().split()
            for part in size_parts:
                # 使用正则表达式匹配尺寸格式
                match = re.match(r'^(\d+)[x,X](\d+)$', part)
                if match:
                    width = int(match.group(1))
                    height = int(match.group(2))
                    
                    if width <= 0 or height <= 0:
                        continue
                        
                    sizes.append((width, height))
            
            return sizes
        except Exception as e:
            print(f"尺寸解析错误: {e}")
            return []
    
    def update_sizes(self):
        """更新尺寸列表"""
        size_input = self.size_entry.get()
        new_sizes = self.parse_size_input(size_input)
        
        if new_sizes:
            self.sizes = new_sizes
            size_text = ", ".join([f"{w}x{h}" for w, h in self.sizes])
            self.size_display.config(text=f"当前尺寸: {size_text}")
            messagebox.showinfo("成功", f"已更新尺寸: {size_text}")
        else:
            messagebox.showerror("错误", "尺寸格式有误,请使用格式: 宽x高,如 28x28 108x108")
    
    def select_file(self):
        file_path = filedialog.askopenfilename(
            title="选择Logo图片",
            filetypes=[("图片文件", "*.jpg *.jpeg *.png *.bmp *.gif *.tiff *.webp")]
        )
        if file_path:
            self.input_path = file_path
            self.path_label.config(text=f"选择文件: {file_path}")
            self.is_batch = False
    
    def select_directory(self):
        dir_path = filedialog.askdirectory(title="选择包含Logo图片的目录")
        if dir_path:
            self.input_path = dir_path
            self.path_label.config(text=f"选择目录: {dir_path}")
            self.is_batch = True
    
    def select_output_dir(self):
        dir_path = filedialog.askdirectory(title="选择输出目录")
        if dir_path:
            self.output_path = dir_path
            self.output_label.config(text=f"输出目录: {dir_path}")
    
    def resize_logo(self, input_path):
        """调整单个logo尺寸"""
        try:
            with Image.open(input_path) as img:
                if img.mode != 'RGBA':
                    img = img.convert('RGBA')
                
                filename = os.path.splitext(os.path.basename(input_path))[0]
                
                output_files = []
                for width, height in self.sizes:
                    resized_img = img.resize((width, height), Image.Resampling.LANCZOS)
                    output_filename = f"{filename}_{width}x{height}.png"
                    output_filepath = os.path.join(self.output_path, output_filename)
                    resized_img.save(output_filepath, 'PNG')
                    output_files.append(output_filepath)
            
            return True, output_files
        except Exception as e:
            print(f"处理 {input_path} 时出错: {e}")
            return False, []
    
    def start_conversion(self):
        if not self.input_path:
            messagebox.showerror("错误", "请先选择文件或目录")
            return
        
        # 更新尺寸(确保使用最新的输入)
        self.update_sizes()
        
        if not self.sizes:
            messagebox.showerror("错误", "没有有效的尺寸设置")
            return
        
        # 创建输出目录
        if not os.path.exists(self.output_path):
            os.makedirs(self.output_path)
        
        # 开始进度条
        self.progress.start()
        self.convert_button.config(state='disabled')
        
        try:
            if self.is_batch:
                # 批量处理
                supported_formats = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff', '.webp'}
                success_count = 0
                total_count = 0
                
                for filename in os.listdir(self.input_path):
                    file_path = os.path.join(self.input_path, filename)
                    if (os.path.isfile(file_path) and 
                        os.path.splitext(filename)[1].lower() in supported_formats):
                        total_count += 1
                        success, _ = self.resize_logo(file_path)
                        if success:
                            success_count += 1
                
                self.status_label.config(text=f"批量处理完成: {success_count}/{total_count} 个文件成功")
                messagebox.showinfo("完成", 
                                  f"批量处理完成!\n"
                                  f"成功: {success_count}/{total_count} 个文件\n"
                                  f"生成尺寸: {', '.join([f'{w}x{h}' for w, h in self.sizes])}")
            
            else:
                # 单个文件处理
                success, output_files = self.resize_logo(self.input_path)
                if success:
                    self.status_label.config(text="转换完成")
                    file_list = "\n".join([os.path.basename(f) for f in output_files])
                    messagebox.showinfo("完成", 
                                      f"图片转换完成!\n\n生成的文件:\n{file_list}")
                else:
                    self.status_label.config(text="转换失败")
                    messagebox.showerror("错误", "图片转换失败")
        
        except Exception as e:
            messagebox.showerror("错误", f"处理过程中出错: {e}")
        
        finally:
            # 停止进度条
            self.progress.stop()
            self.convert_button.config(state='normal')

def main():
    root = tk.Tk()
    app = LogoResizerApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()