单个图片转化工具分享(源码+工具)

目录

工具界面

工具使用及下载

[📥 工具下载](#📥 工具下载)

[🚀 操作步骤(5 步搞定)](#🚀 操作步骤(5 步搞定))

[📋 查看转换结果](#📋 查看转换结果)

[💡 核心特性说明](#💡 核心特性说明)

工具源码

核心思路

[📥 前期准备](#📥 前期准备)

[🚀 核心操作步骤(5 步完成转换)](#🚀 核心操作步骤(5 步完成转换))

[💡 关键特性与注意事项](#💡 关键特性与注意事项)

[📂 查看结果](#📂 查看结果)


工具界面

转化结果

工具使用及下载

📥 工具下载

https://pan.baidu.com/s/1WwGJTKRHUMUkW1GavzpgLA?pwd=e1n2

解压密码:xi.ji

🚀 操作步骤(5 步搞定)

  1. 选择输入图片在「输入选择」区域,点击「选择文件」按钮,从电脑中挑选你想要转换的图片(支持 PNG、JPG、BMP、GIF、TIFF 等格式)。

  2. 选择输出文件夹在「输出设置」区域,点击「选择」按钮,指定生成的 ICO 文件要保存到哪个文件夹。

  3. 选择目标格式为 ICO 在「目标格式」下拉菜单中,选择 ICO 选项。此时下方会展开「ICO 尺寸选择」区域。

  4. 选择 ICO 尺寸

    • 常用尺寸:直接勾选你需要的尺寸(如 16x16、32x32、48x48)。
    • 自定义尺寸 :如果需要特殊尺寸,在输入框中按格式填写(如 50,50;64,64),多个尺寸用分号分隔。
  5. 开始转换 点击「开始转换」按钮,工具会自动处理图片,并为每个勾选的尺寸生成独立的 ICO 文件(命名规则:原文件名_宽x高.ico,例如 图标_16x16.ico)。


📋 查看转换结果

  • 转换日志:窗口下方的「转换日志」区域会实时显示每个尺寸的生成状态(成功 / 失败),并带时间戳,方便你追踪过程。
  • 生成的文件:前往你选择的输出文件夹,就能看到所有生成的 ICO 文件,每个文件对应一个尺寸,且都能被 Windows 正常打开。

💡 核心特性说明

  • 智能处理非标准图片:如果你的原图是长方形等非正方形,工具会自动先按比例缩放,再从中心裁剪出正方形区域,保证生成的 ICO 不变形、内容居中。
  • 格式兼容:生成的 ICO 文件完全符合 Windows 规范,不会出现「无法打开」的问题。
  • 容错机制:如果忘记选择尺寸,工具会自动使用 16x16、32x32、48x48 这三个常用尺寸作为默认值;如果自定义尺寸输入错误,会弹出提示并继续使用勾选的尺寸。

工具源码

python 复制代码
import os
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from PIL import Image
from PIL.Image import UnidentifiedImageError


# ====================== 核心转换函数 ======================
def convert_image(input_path, output_path, target_format):

    try:
        with Image.open(input_path) as img:

            if target_format == 'JPEG' and img.mode in ('RGBA', 'P'):
                background = Image.new('RGB', img.size, (255, 255, 255))
                if img.mode == 'RGBA':
                    background.paste(img, mask=img.split()[3])
                else:
                    background.paste(img)
                img = background

            img.save(output_path, format=target_format)
        return True, f"转换成功:{os.path.basename(input_path)}"
    except Exception as e:
        return False, f"转换失败 {os.path.basename(input_path)}:{str(e)}"


def create_single_size_ico(input_path, output_path, size):

    target_w, target_h = size
    try:
        with Image.open(input_path) as img:

            if img.mode != 'RGBA':
                img = img.convert('RGBA')



            scale_factor = max(target_w / img.width, target_h / img.height)
            new_width = int(img.width * scale_factor)
            new_height = int(img.height * scale_factor)


            img_resized = img.resize((new_width, new_height), Image.Resampling.LANCZOS)


            crop_left = max(0, (new_width - target_w) // 2)
            crop_top = max(0, (new_height - target_h) // 2)
            crop_right = min(new_width, crop_left + target_w)
            crop_bottom = min(new_height, crop_top + target_h)


            img_cropped = img_resized.crop((crop_left, crop_top, crop_right, crop_bottom))


            if img_cropped.size != (target_w, target_h):
                img_cropped = img_cropped.resize((target_w, target_h), Image.Resampling.LANCZOS)
            # ==================================================


            img_cropped.save(output_path, format='ICO', sizes=[(target_w, target_h)])

        return True, f"生成成功:{os.path.basename(output_path)}"
    except Exception as e:
        return False, f"生成失败 {os.path.basename(output_path)}:{str(e)}"


# ====================== GUI界面逻辑 ======================
class ImageConverterGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("图片转化小工具(CSDN程序蓄)")
        self.root.geometry("800x600")
        self.root.resizable(False, False)

        # 初始化变量
        self.input_path = tk.StringVar()
        self.output_dir = tk.StringVar()
        self.target_format = tk.StringVar(value="PNG")
        # 强制单个文件模式,禁用批量转换
        self.is_folder = tk.BooleanVar(value=False)

        # ICO尺寸选择变量(常用尺寸复选框)
        self.ico_size_vars = {
            (16, 16): tk.BooleanVar(value=True),
            (32, 32): tk.BooleanVar(value=True),
            (48, 48): tk.BooleanVar(value=True),
            (64, 64): tk.BooleanVar(value=False),
            (128, 128): tk.BooleanVar(value=False),
            (256, 256): tk.BooleanVar(value=False)
        }
        self.custom_ico_sizes = tk.StringVar(value="")


        self._create_widgets()

    def _create_widgets(self):

        frame_input = ttk.LabelFrame(self.root, text="输入选择")
        frame_input.pack(padx=10, pady=8, fill=tk.X)


        ttk.Radiobutton(frame_input, text="单个文件", variable=self.is_folder, value=False,
                        state="disabled").grid(row=0, column=0, padx=5, pady=5)


        self.entry_input = ttk.Entry(frame_input, textvariable=self.input_path, state="readonly")
        self.entry_input.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky=tk.EW)


        self.btn_select_input = ttk.Button(frame_input, text="选择文件", command=self._select_input)
        self.btn_select_input.grid(row=1, column=2, padx=5, pady=5)


        frame_output = ttk.LabelFrame(self.root, text="输出设置")
        frame_output.pack(padx=10, pady=8, fill=tk.X)


        ttk.Label(frame_output, text="输出文件夹:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        ttk.Entry(frame_output, textvariable=self.output_dir, state="readonly").grid(row=0, column=1, padx=5, pady=5,
                                                                                     sticky=tk.EW)
        ttk.Button(frame_output, text="选择", command=self._select_output_dir).grid(row=0, column=2, padx=5, pady=5)


        ttk.Label(frame_output, text="目标格式:").grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
        format_options = ["PNG", "JPEG", "BMP", "ICO", "GIF"]
        ttk.Combobox(frame_output, textvariable=self.target_format, values=format_options, state="readonly").grid(
            row=1, column=1, padx=5, pady=5, sticky=tk.EW)


        self.frame_ico = ttk.LabelFrame(frame_output, text="ICO尺寸选择(仅支持正方形,最大256x256)")
        self.frame_ico.columnconfigure(1, weight=1)


        common_sizes_frame = ttk.Frame(self.frame_ico)
        common_sizes_frame.grid(row=0, column=0, columnspan=3, padx=5, pady=5, sticky=tk.W)


        size_options = [(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
        for i, size in enumerate(size_options):
            ttk.Checkbutton(
                common_sizes_frame,
                text=f"{size[0]}x{size[1]}",
                variable=self.ico_size_vars[size]
            ).grid(row=0, column=i, padx=8, pady=3)


        ttk.Label(self.frame_ico, text="自定义尺寸(分号分隔,如:32,32;64,64):").grid(
            row=1, column=0, padx=5, pady=5, sticky=tk.W)
        ttk.Entry(self.frame_ico, textvariable=self.custom_ico_sizes).grid(
            row=1, column=1, padx=5, pady=5, sticky=tk.EW)
        ttk.Label(self.frame_ico, text="示例:16,16;32,32;48,48", font=("Arial", 8)).grid(
            row=1, column=2, padx=5, pady=5)


        btn_convert = ttk.Button(self.root, text="开始转换", command=self._start_convert)
        btn_convert.pack(padx=10, pady=10, ipady=5)


        frame_log = ttk.LabelFrame(self.root, text="转换日志")
        frame_log.pack(padx=10, pady=8, fill=tk.BOTH, expand=True)


        scrollbar = ttk.Scrollbar(frame_log)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.text_log = tk.Text(frame_log, yscrollcommand=scrollbar.set, wrap=tk.WORD, state="disabled",
                                font=("Consolas", 9))
        self.text_log.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        scrollbar.config(command=self.text_log.yview)

        self.target_format.trace_add("write", self._toggle_ico_settings)
        self._toggle_ico_settings()

    def _toggle_input_type(self):

        pass

    def _toggle_ico_settings(self, *args):

        if self.target_format.get() == "ICO":
            self.frame_ico.grid(row=2, column=0, columnspan=3, padx=5, pady=5, sticky=tk.EW)
        else:
            self.frame_ico.grid_forget()

    def _select_input(self):

        path = filedialog.askopenfilename(
            title="选择待转换的图片",
            filetypes=[("图片文件", "*.png;*.jpg;*.jpeg;*.bmp;*.gif;*.tiff"), ("所有文件", "*.*")]
        )
        if path:
            self.input_path.set(path)
            self._log(f"✅ 已选择输入文件:{path}")

    def _select_output_dir(self):

        path = filedialog.askdirectory(title="选择输出文件夹")
        if path:
            self.output_dir.set(path)
            self._log(f"✅ 已选择输出文件夹:{path}")

    def _log(self, msg):

        from datetime import datetime
        timestamp = datetime.now().strftime("[%H:%M:%S]")
        self.text_log.config(state="normal")
        self.text_log.insert(tk.END, f"{timestamp} {msg}\n")
        self.text_log.see(tk.END)  # 自动滚动到最后一行
        self.text_log.config(state="disabled")

    def _parse_ico_sizes(self):
        """解析勾选的ICO尺寸 + 自定义尺寸"""
        # 1. 获取勾选的常用尺寸
        selected_sizes = [size for size, var in self.ico_size_vars.items() if var.get()]
        self._log(f"📌 勾选的常用尺寸:{[f'{w}x{h}' for w, h in selected_sizes]}")


        try:
            custom_sizes_str = self.custom_ico_sizes.get().strip()
            self._log(f"📌 自定义尺寸输入:{custom_sizes_str if custom_sizes_str else '无'}")

            if custom_sizes_str:
                custom_sizes = []
                for part in custom_sizes_str.split(";"):
                    part = part.strip()
                    if part:
                        w, h = part.split(",")
                        custom_size = (int(w.strip()), int(h.strip()))
                        custom_sizes.append(custom_size)


                for custom_size in custom_sizes:
                    if custom_size not in selected_sizes:
                        selected_sizes.append(custom_size)
                        self._log(f"➕ 添加自定义尺寸:{custom_size[0]}x{custom_size[1]}")
        except Exception as e:
            self._log(f"⚠️ 自定义尺寸解析失败:{str(e)}")
            messagebox.warning("警告", f"自定义尺寸格式错误:{str(e)}\n将仅使用勾选的尺寸")


        if not selected_sizes:
            selected_sizes = [(16, 16), (32, 32), (48, 48)]
            self._log("⚠️ 未选择任何ICO尺寸,使用默认尺寸:16x16, 32x32, 48x48")

        self._log(f"📋 最终待生成的尺寸列表:{[f'{w}x{h}' for w, h in selected_sizes]}")
        return selected_sizes

    def _start_convert(self):

        input_path = self.input_path.get().strip()
        output_dir = self.output_dir.get().strip()
        target_format = self.target_format.get()

        if not input_path:
            messagebox.showerror("错误", "请先选择输入文件!")
            return
        if not output_dir:
            messagebox.showerror("错误", "请先选择输出文件夹!")
            return

        self._log("=" * 70)
        self._log(f"🚀 开始转换,目标格式:{target_format}")

        # 执行单个文件转换
        self._single_convert(input_path, output_dir, target_format)

        self._log("✅ 转换任务完成!")
        messagebox.showinfo("完成", "转换任务已执行完毕,请查看日志确认结果!")

    def _single_convert(self, input_file, output_dir, target_format):

        filename = os.path.basename(input_file)
        name_without_ext = os.path.splitext(filename)[0]

        if target_format == "ICO":
            ico_sizes = self._parse_ico_sizes()

            for size in ico_sizes:
                w, h = size
                output_path = os.path.join(output_dir, f"{name_without_ext}_{w}x{h}.ico")
                success, msg = create_single_size_ico(input_file, output_path, size)
                self._log(msg)
        else:
            # 普通格式转换
            output_ext = f".{target_format.lower()}"
            output_path = os.path.join(output_dir, f"{name_without_ext}{output_ext}")
            success, msg = convert_image(input_file, output_path, target_format)
            self._log(msg)


# ====================== 程序入口 ======================
if __name__ == "__main__":

    # 启动GUI
    root = tk.Tk()
    app = ImageConverterGUI(root)
    root.mainloop()

核心思路

📥 前期准备

  1. 环境配置 :确保电脑安装了 Python,打开命令行输入 pip install --upgrade pillow 安装 / 升级图片处理依赖库(这是工具能正常运行的基础);
  2. 启动工具:双击运行工具的 Python 脚本,弹出操作窗口即可开始使用。

🚀 核心操作步骤(5 步完成转换)

  1. 选待转换图片:在窗口「输入选择」区域点击「选择文件」,从电脑中挑选要转换的图片(支持 PNG、JPG、BMP、GIF、TIFF 等常见格式),选好后日志区会显示已选文件路径;
  2. 指定保存位置:在「输出设置」区域点击「选择」按钮,选一个文件夹作为 ICO 文件的保存路径,日志区会同步显示保存位置;
  3. 选目标格式为 ICO:点击「目标格式」下拉菜单,选择「ICO」选项,窗口会自动展开「ICO 尺寸选择」区域;
  4. 选需要的 ICO 尺寸
    • 常用尺寸:直接勾选 16x16、32x32、48x48 等预设尺寸(可多选);
    • 自定义尺寸:在输入框按「宽,高;宽,高」格式填写(如 50,50;64,64),多个尺寸用分号分隔,工具会自动解析并去重;
    • 若未选任何尺寸,工具会默认使用 16x16、32x32、48x48 三个常用尺寸;
  5. 开始转换:点击「开始转换」按钮,工具会自动处理图片并生成 ICO 文件,日志区会实时显示每个尺寸的生成状态(成功 / 失败),转换完成后会弹出 "转换任务完成" 提示。

💡 关键特性与注意事项

  1. 智能处理非标准图片:若原图是长方形、扁形等非正方形,工具会先按比例缩放至覆盖目标尺寸,再从图片中心裁剪出正方形区域(类似裁证件照),避免 ICO 变形;
  2. 兼容 Windows 系统:生成的 ICO 文件用 PIL 库原生功能保存,百分百兼容 Windows,可直接用照片查看器打开,每个尺寸对应一个独立文件(命名规则:原文件名_宽 x 高.ico);
  3. 容错与提示
    • 若自定义尺寸格式错误(如输成 32,32),日志区会提示错误,仍会用勾选的尺寸继续转换;
    • 转换 JPG 图片时,会自动用白色填充透明区域(JPG 不支持透明);
    • 日志区带时间戳,可清晰查看每一步操作结果,方便排查问题;
  4. 中文适配:工具界面已适配 Windows 中文显示,不会出现乱码问题。

📂 查看结果

转换完成后,前往选定的保存文件夹,即可看到生成的 ICO 文件(如图标_16x16.ico、图标_32x32.ico),直接双击就能正常打开,非正方形原图转换后的 ICO 会保持内容居中、无变形。

相关推荐
大数据002 小时前
基于Ollama大模型学习
python·flask·大模型·alibaba·ollama·springai·deepseek
YHLG2 小时前
LangChain v1.0+ 入门详解:概念、架构、组件、模板与实战
python·langchain
pen-ai2 小时前
PyTorch 张量维度处理详解
人工智能·pytorch·python
郝学胜-神的一滴2 小时前
Python对象的自省机制:深入探索对象的内心世界
开发语言·python·程序人生·算法
tjjucheng2 小时前
小程序定制开发哪家有数据支持
python
pen-ai2 小时前
【PyTorch】 nn.TransformerEncoderLayer 详解
人工智能·pytorch·python
山土成旧客2 小时前
【Python学习打卡-Day44】站在巨人的肩膀上:玩转PyTorch预训练模型与迁移学习
pytorch·python·学习
星河天欲瞩2 小时前
【深度学习Day1】环境配置(CUDA、PyTorch)
人工智能·pytorch·python·深度学习·学习·机器学习·conda
Irene.ll2 小时前
DAY32 官方文档的阅读
python