Python代码

from PIL import Image
import os # 导入os模块,用于文件和目录操作
 
def get_image_paths_from_folder(folder_path, extensions=('.png', '.jpg', '.jpeg', '.gif', '.bmp')):
    """
    从指定文件夹中获取所有指定扩展名的图片文件路径。
 
    Args:
        folder_path (str): 图片所在的文件夹路径。
        extensions (tuple): 包含图片文件扩展名的元组,默认为常见图片格式。
 
    Returns:
        list: 包含所有图片文件完整路径的列表。
    """
    image_paths = []
    if not os.path.exists(folder_path): # 检查文件夹是否存在
        print(f"错误: 文件夹 '{folder_path}' 不存在。")
        return image_paths
    
    for filename in os.listdir(folder_path): # 遍历文件夹中的所有文件和子文件夹
        if filename.lower().endswith(extensions): # 检查文件是否为图片(大小写不敏感)
            full_path = os.path.join(folder_path, filename) # 拼接完整文件路径
            if os.path.isfile(full_path): # 再次确认是文件而不是子文件夹
                image_paths.append(full_path)
    
    image_paths.sort() # 为了保证拼接顺序,可以根据文件名排序
    return image_paths
 
def stitch_and_compress_images(image_paths, output_path, quality=85):
    """
    将多张长宽相同的图片横向拼接成一张图,并对结果图进行压缩。
    (此函数与之前基本相同,但为完整性再次包含)
 
    Args:
        image_paths (list): 包含所有待拼接图片文件路径的列表。
        output_path (str): 拼接完成后图片的保存路径。
        quality (int, optional): 压缩质量,范围0-95,越高图片质量越好,文件越大。
                                 默认为85,适用于JPEG格式。
    """
    if not image_paths:
        print("图片路径列表不能为空,无法进行拼接!")
        return
 
    # 尝试打开第一张图片以获取基准尺寸
    try:
        first_image = Image.open(image_paths[0])
        width, height = first_image.size
    except FileNotFoundError:
        print(f"错误: 找不到第一张图片 {image_paths[0]},无法获取基准尺寸。")
        return
    except Exception as e:
        print(f"打开第一张图片 {image_paths[0]} 时发生错误: {e}")
        return
    finally:
        first_image.close() # 立即关闭第一张图片,避免长时间占用
 
    # 过滤掉尺寸不匹配的图片,并重新构建一个有效图片路径列表
    valid_image_paths = []
    print(f"基准图片尺寸: ({width}, {height})")
    for path in image_paths:
        try:
            with Image.open(path) as img: # 使用with语句确保图片自动关闭
                if img.size == (width, height):
                    valid_image_paths.append(path)
                else:
                    print(f"警告: 图片 '{os.path.basename(path)}' 的尺寸 ({img.size}) 与基准尺寸不符,已跳过。")
        except FileNotFoundError:
            print(f"错误: 找不到文件 '{os.path.basename(path)}',已跳过。")
        except Exception as e:
            print(f"处理图片 '{os.path.basename(path)}' 时发生错误: {e},已跳过。")
 
    if not valid_image_paths:
        print("没有找到符合尺寸要求的图片,无法进行拼接!")
        return
    
    # 计算拼接后图片的宽度
    total_width = width * len(valid_image_paths)
    
    # 创建一张新的空白图片,用于存放拼接后的内容
    new_image = Image.new('RGB', (total_width, height))
 
    x_offset = 0 # 记录当前图片粘贴的起始X坐标
    for path in valid_image_paths: # 遍历有效图片路径列表
        try:
            with Image.open(path) as img: # 使用with语句确保图片自动关闭
                # 将当前图片粘贴到新图片上
                new_image.paste(img, (x_offset, 0))
                x_offset += width # 更新下一个图片粘贴的X坐标
        except Exception as e:
            print(f"粘贴图片 '{os.path.basename(path)}' 时发生错误: {e},已跳过。")
 
    # 保存拼接后的图片并进行压缩
    try:
        new_image.save(output_path, quality=quality, optimize=True)
        print(f"图片拼接与压缩完成,保存至: {output_path}")
    except Exception as e:
        print(f"保存或压缩图片时发生错误: {e}")
    finally:
        new_image.close() # 关闭新创建的图片
 
# 示例使用
if __name__ == "__main__":
    # 1. 创建一个用于存放示例图片的文件夹
    input_folder = '2'
    os.makedirs(input_folder, exist_ok=True) # 如果文件夹不存在则创建
 
    # 2. 创建一些示例图片放入该文件夹
    try:
        # 尺寸相同的图片
        img1 = Image.new('RGB', (100, 50), color = 'red')
        img1.save(os.path.join(input_folder, 'image1.png'))
        img2 = Image.new('RGB', (100, 50), color = 'green')
        img2.save(os.path.join(input_folder, 'image2.jpg'))
        img3 = Image.new('RGB', (100, 50), color = 'blue')
        img3.save(os.path.join(input_folder, 'image3.png'))
        
        # 一张尺寸不同的图片,用于测试过滤功能
        img_diff_size = Image.new('RGB', (50, 50), color = 'yellow')
        img_diff_size.save(os.path.join(input_folder, 'diff_size_image.png'))
 
        # 一张非图片文件,确保不会被误读
        with open(os.path.join(input_folder, 'not_an_image.txt'), 'w') as f:
            f.write("This is not an image.")
 
        print(f"示例图片已创建在 '{input_folder}' 文件夹中。")
    except ImportError:
        print("Pillow 库未安装。请使用 'pip install Pillow' 安装。")
        exit()
 
    # 3. 设置输出文件路径
    output_merged_file = 'output.jpg'
    
    print("\n--- 开始处理 ---")
    # 4. 获取文件夹中的图片路径
    all_image_paths = get_image_paths_from_folder(input_folder)
 
    # 5. 调用拼接和压缩函数
    stitch_and_compress_images(all_image_paths, output_merged_file, quality=75)
 
    print("\n--- 任务完成 ---")
    # 清理示例图片 (可选)
    # import shutil
    # shutil.rmtree(input_folder) 
    # print(f"清理了示例文件夹 '{input_folder}'。")

主要功能和解释

这个脚本用于从指定文件夹读取图片(按文件名排序、只取指定扩展名),把尺寸相同的多张图片按水平方向拼接成一张大图并保存,同时对结果进行压缩(主要用于 JPEG)。

使用注意

  1. 只会拼接与第一张图片尺寸完全相同的图片;若要包含不同尺寸可以先统一缩放/裁剪。
  2. quality 参数对 JPEG 有效;如果输出 PNG,可使用 optimize=True 和 ompress_level 参数(Pillow 支持)。
  3. 大量或超长图片拼接可能占用大量内存,需谨慎(可考虑按块处理或增加临时磁盘缓存)。
  4. 如果需要保留透明通道,创建新图时应使用模式 ‘RGBA’ 并保存为 PNG。