【Python】批量转换文件夹内的图片为ICO

import os
from PIL import Image
import sys


def convert_folder_to_ico(input_folder, output_folder=None, sizes=None):
    """
    批量转换文件夹内的图片为ICO

    Args:
        input_folder: 输入文件夹路径
        output_folder: 输出文件夹路径(默认为输入文件夹内的ico_output)
        sizes: ICO尺寸列表,默认为[16, 32, 48, 64, 128, 256]
    """
    # 支持的图片格式
    supported_formats = ('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.tiff', '.webp')

    # 设置默认尺寸
    if sizes is None:
        sizes = [16, 32, 48, 64, 128, 256]

    # 设置输出文件夹
    if output_folder is None:
        output_folder = os.path.join(input_folder, 'ico_output')

    # 创建输出文件夹
    os.makedirs(output_folder, exist_ok=True)

    # 统计变量
    success_count = 0
    error_count = 0

    # 遍历文件夹
    for filename in os.listdir(input_folder):
        # 检查是否为支持的图片格式
        if filename.lower().endswith(supported_formats):
            input_path = os.path.join(input_folder, filename)

            try:
                # 打开图片
                img = Image.open(input_path)

                # 准备不同尺寸的图片
                icon_sizes = []
                for size in sizes:
                    # 兼容不同Pillow版本的重采样方法
                    try:
                        # 新版本写法
                        resized_img = img.resize((size, size), Image.Resampling.LANCZOS)
                    except AttributeError:
                        try:
                            # 较新版本写法
                            resized_img = img.resize((size, size), Image.LANCZOS)
                        except:
                            # 旧版本写法
                            resized_img = img.resize((size, size), Image.ANTIALIAS)
                    icon_sizes.append(resized_img)

                # 生成输出文件名
                base_name = os.path.splitext(filename)[0]
                output_path = os.path.join(output_folder, f"{base_name}.ico")

                # 保存为ICO(兼容不同版本的保存方式)
                try:
                    # 新版本保存方式
                    icon_sizes[0].save(
                        output_path,
                        format='ICO',
                        sizes=[(size, size) for size in sizes],
                        append_images=icon_sizes[1:] if len(icon_sizes) > 1 else None
                    )
                except:
                    # 旧版本保存方式
                    # 如果保存失败,尝试只保存256x256尺寸
                    img_resized = img.resize((256, 256), Image.Resampling.LANCZOS if hasattr(Image,
                                                                                             'Resampling') else Image.LANCZOS)
                    img_resized.save(output_path, format='ICO')

                print(f"✓ 转换成功: {filename} -> {base_name}.ico")
                success_count += 1

            except Exception as e:
                print(f"✗ 转换失败: {filename} - 错误: {str(e)}")
                error_count += 1
                import traceback
                traceback.print_exc()  # 打印详细错误信息

    print(f"\n转换完成!成功: {success_count}个,失败: {error_count}个")
    print(f"输出文件夹: {output_folder}")


# 简化版本,兼容性更好
def convert_folder_to_ico_simple(input_folder, output_folder=None):
    """
    简化版批量转换,兼容性更好
    """
    # 支持的图片格式
    supported_formats = ('.png', '.jpg', '.jpeg')

    # 设置输出文件夹
    if output_folder is None:
        output_folder = os.path.join(input_folder, 'ico_output')

    # 创建输出文件夹
    os.makedirs(output_folder, exist_ok=True)

    # 统计变量
    success_count = 0
    error_count = 0

    # 遍历文件夹
    for filename in os.listdir(input_folder):
        # 检查是否为支持的图片格式
        if filename.lower().endswith(supported_formats):
            input_path = os.path.join(input_folder, filename)

            try:
                # 打开图片
                img = Image.open(input_path)

                # 生成输出文件名
                base_name = os.path.splitext(filename)[0]
                output_path = os.path.join(output_folder, f"{base_name}.ico")

                # 简化:只保存256x256尺寸
                # 确定重采样方法
                if hasattr(Image, 'Resampling'):
                    resample_method = Image.Resampling.LANCZOS
                elif hasattr(Image, 'LANCZOS'):
                    resample_method = Image.LANCZOS
                else:
                    resample_method = Image.ANTIALIAS

                # 调整大小
                img_resized = img.resize((256, 256), resample_method)

                # 保存为ICO
                img_resized.save(output_path, format='ICO')

                print(f"✓ 转换成功: {filename} -> {base_name}.ico")
                success_count += 1

            except Exception as e:
                print(f"✗ 转换失败: {filename} - 错误: {str(e)}")
                error_count += 1

    print(f"\n转换完成!成功: {success_count}个,失败: {error_count}个")
    print(f"输出文件夹: {output_folder}")


# 增强版:支持多尺寸和格式转换
def convert_folder_to_ico_enhanced(input_folder, output_folder=None, sizes=None):
    """
    增强版批量转换
    """
    # 支持的图片格式
    supported_formats = ('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.tiff', '.webp')

    # 设置默认尺寸
    if sizes is None:
        sizes = [16, 32, 48, 64, 128, 256]

    # 设置输出文件夹
    if output_folder is None:
        output_folder = os.path.join(input_folder, 'ico_output')

    # 创建输出文件夹
    os.makedirs(output_folder, exist_ok=True)

    # 获取重采样方法
    def get_resample_method():
        if hasattr(Image, 'Resampling'):
            return Image.Resampling.LANCZOS
        elif hasattr(Image, 'LANCZOS'):
            return Image.LANCZOS
        else:
            return Image.ANTIALIAS

    resample_method = get_resample_method()

    # 统计变量
    success_count = 0
    error_count = 0

    # 遍历文件夹
    for filename in os.listdir(input_folder):
        # 检查是否为支持的图片格式
        if filename.lower().endswith(supported_formats):
            input_path = os.path.join(input_folder, filename)

            try:
                # 打开图片
                with Image.open(input_path) as img:
                    # 如果图片有透明通道,转换为RGBA
                    if img.mode in ('P', 'RGBA'):
                        img = img.convert('RGBA')
                    else:
                        img = img.convert('RGB')

                    # 生成输出文件名
                    base_name = os.path.splitext(filename)[0]
                    output_path = os.path.join(output_folder, f"{base_name}.ico")

                    # 创建不同尺寸的图像
                    images = []
                    for size in sizes:
                        resized = img.resize((size, size), resample_method)
                        images.append(resized)

                    # 保存为ICO
                    # 使用第一个图像作为主图像,附加其他尺寸
                    if len(images) > 0:
                        images[0].save(
                            output_path,
                            format='ICO',
                            append_images=images[1:] if len(images) > 1 else []
                        )

                    print(f"✓ 转换成功: {filename} -> {base_name}.ico")
                    success_count += 1

            except Exception as e:
                print(f"✗ 转换失败: {filename} - 错误: {str(e)}")
                error_count += 1

    print(f"\n转换完成!成功: {success_count}个,失败: {error_count}个")
    print(f"输出文件夹: {output_folder}")


if __name__ == "__main__":
    print("批量图片转ICO工具")
    print("=" * 40)

    # 获取输入路径
    if len(sys.argv) > 1:
        input_path = sys.argv[1]
    else:
        input_path = input("请输入图片文件夹路径: ").strip('"').strip("'")

    if not os.path.exists(input_path):
        print("错误:文件夹不存在!")
        sys.exit(1)

    print("\n选择转换模式:")
    print("1. 简单模式(快速,单尺寸)")
    print("2. 标准模式(推荐,多尺寸)")
    print("3. 增强模式(完整功能)")

    mode = input("\n请选择模式 (1/2/3, 默认2): ").strip()

    if mode == "1":
        convert_folder_to_ico_simple(input_path)
    elif mode == "3":
        # 自定义尺寸
        custom_sizes = input("请输入ICO尺寸(用逗号分隔,如: 16,32,48,64,128,256): ")
        if custom_sizes:
            sizes = [int(s.strip()) for s in custom_sizes.split(',')]
        else:
            sizes = None

        # 自定义输出文件夹
        output_path = input("请输入输出文件夹路径(直接回车使用默认): ").strip('"').strip("'")
        output_path = output_path if output_path else None

        convert_folder_to_ico_enhanced(input_path, output_path, sizes)
    else:
        convert_folder_to_ico(input_path)

运行结果
image

posted @ 2025-12-14 11:25  Phoenixy  阅读(3)  评论(0)    收藏  举报