Python 实现 等比例缩放图像到指定像素+填充

Python 实现 等比例缩放图像到指定像素+填充

flyfish

代码

python 复制代码
import os
from PIL import Image
from pathlib import Path

# ====================== 配置参数(可自行修改)======================
# 输入根目录(图片文件夹)
INPUT_ROOT = r"./input"
# 输出根目录(处理后的图片会保存在这里)
OUTPUT_ROOT = r"./output"
# 目标最大尺寸
TARGET_WIDTH = 1280
TARGET_HEIGHT = 720
# 填充颜色 (R, G, B)
FILL_COLOR = (114, 114, 114)
# 支持的图片格式(大小写都支持)
SUPPORT_FORMATS = (".jpg", ".JPG")
# =================================================================

def process_single_image(img_path: str, save_path: str):
    """
    处理单张图片:转换格式 + 等比例缩放 + 居中填充
    """
    try:
        # 1. 打开图片,自动处理各种格式异常
        with Image.open(img_path) as img:
            # 2. 统一转为 RGB 格式(解决灰度图、透明通道报错)
            if img.mode in ("RGBA", "LA"):
                # 透明图:先创建纯色背景,再粘贴图片
                background = Image.new("RGB", img.size, FILL_COLOR)
                background.paste(img, mask=img.split()[-1])
                img = background
            elif img.mode != "RGB":
                # 灰度图等其他格式直接转RGB
                img = img.convert("RGB")

            # 3. 等比例缩放计算
            orig_w, orig_h = img.size
            scale = min(TARGET_WIDTH / orig_w, TARGET_HEIGHT / orig_h)
            new_w = int(orig_w * scale)
            new_h = int(orig_h * scale)

            # 高质量缩放
            img_resized = img.resize((new_w, new_h), Image.Resampling.LANCZOS)

            # 4. 创建目标尺寸画布,居中放置图片
            canvas = Image.new("RGB", (TARGET_WIDTH, TARGET_HEIGHT), FILL_COLOR)
            offset_x = (TARGET_WIDTH - new_w) // 2
            offset_y = (TARGET_HEIGHT - new_h) // 2
            canvas.paste(img_resized, (offset_x, offset_y))

            # 5. 保存图片(质量95)
            canvas.save(save_path, "JPEG", quality=95)
            print(f"处理完成: {save_path}")

    except Exception as e:
        print(f"处理失败: {img_path} | 错误信息: {str(e)}")

def batch_process_images():
    """
    批量遍历文件夹,复刻目录结构,处理所有图片
    """
    # 创建输出根目录
    os.makedirs(OUTPUT_ROOT, exist_ok=True)

    # 遍历所有子文件夹
    for root, dirs, files in os.walk(INPUT_ROOT):
        # 复刻目录结构到输出文件夹
        relative_path = Path(root).relative_to(INPUT_ROOT)
        output_dir = os.path.join(OUTPUT_ROOT, relative_path)
        os.makedirs(output_dir, exist_ok=True)

        # 遍历当前文件夹所有文件
        for file in files:
            if file.endswith(SUPPORT_FORMATS):
                # 原始图片路径
                img_input_path = os.path.join(root, file)
                # 输出图片路径
                img_output_path = os.path.join(output_dir, file)
                # 处理单张图片
                process_single_image(img_input_path, img_output_path)

if __name__ == "__main__":
    print("=" * 60)
    print("开始批量处理图片,最大尺寸:{}x{},填充颜色:{}".format(TARGET_WIDTH, TARGET_HEIGHT, FILL_COLOR))
    print("=" * 60)
    
    batch_process_images()
    
    print("\n所有图片处理完成!")

可自定义参数

可以直接修改代码顶部的配置:

python 复制代码
INPUT_ROOT = r"./input"    # 输入文件夹
OUTPUT_ROOT = r"./output"  # 输出文件夹
TARGET_WIDTH = 1280        # 目标宽度
TARGET_HEIGHT = 720        # 目标高度
FILL_COLOR = (114,114,114) # 填充颜色

等比例约束缩放,目标是:保证图片不变形的前提下,缩放后宽不超过 1280、高不超过 720,且图片尺寸尽可能大

逻辑

第 1 步:分别计算两个方向的缩放倍数

先拿目标尺寸和原图尺寸做除法,算出:

宽度方向:如果想让图片宽度刚好等于 1280,需要把原图放大/缩小多少倍

高度方向:如果想让图片高度刚好等于 720,需要把原图放大/缩小多少倍

公式:

复制代码
宽度缩放比 = 目标宽度 / 原图宽度 = 1280 / 原图宽
高度缩放比 = 目标高度 / 原图高度 = 720 / 原图高

第 2 步:取两个倍数里更小的那个作为最终缩放比例

这是最关键的一步:选更小的缩放比,才能保证缩放后宽和高都不超出目标尺寸

如果选大的倍数,必然会有一个方向超过 1280 或 720,不符合"最大尺寸"的约束。

选小的倍数,会有一个方向刚好"顶到"目标边界,另一个方向小于目标尺寸,后续用填充补齐。

公式:

复制代码
最终缩放比 = min(宽度缩放比, 高度缩放比)

第 3 步:计算缩放后的实际图片尺寸

用最终缩放比同时乘以原图宽高,保证宽高比和原图完全一致,不会拉伸变形。

公式:

复制代码
缩放后宽度 = 原图宽度 × 最终缩放比
缩放后高度 = 原图高度 × 最终缩放比

第 4 步:居中放置 + 背景填充

创建一张 1280×720 的纯色画布,把缩放后的图片放在正中间,剩下的区域用填充色(114,114,114)填满。

举例子

例子 1:宽图(横版长图)

原图尺寸:2000 × 1000(宽高比 2:1)

  1. 宽度缩放比 = 1280 / 2000 = 0.64
  2. 高度缩放比 = 720 / 1000 = 0.72
  3. 取更小值:最终缩放比 = 0.64
  4. 缩放后尺寸:2000×0.64 = 1280 宽,1000×0.64 = 640 高
  5. 结果:宽度刚好顶满 1280,高度 640 < 720,上下用灰色填充

例子 2:竖图(高图)

原图尺寸:800 × 1200(宽高比 2:3)

  1. 宽度缩放比 = 1280 / 800 = 1.6
  2. 高度缩放比 = 720 / 1200 = 0.6
  3. 取更小值:最终缩放比 = 0.6
  4. 缩放后尺寸:800×0.6 = 480 宽,1200×0.6 = 720 高
  5. 结果:高度刚好顶满 720,宽度 480 < 1280,左右用灰色填充

例子 3:小图放大(你的需求场景)

原图尺寸:400 × 300(小图,宽高比 4:3)

  1. 宽度缩放比 = 1280 / 400 = 3.2
  2. 高度缩放比 = 720 / 300 = 2.4
  3. 取更小值:最终缩放比 = 2.4
  4. 缩放后尺寸:400×2.4 = 960 宽,300×2.4 = 720 高
  5. 结果:高度放大到 720 顶满,宽度 960 < 1280,左右用灰色填充

对应代码里的实现

python 复制代码
# 第1步:拿到原图宽高
orig_w, orig_h = img.size

# 第2步:算两个方向的缩放比,取最小值
scale = min(TARGET_WIDTH / orig_w, TARGET_HEIGHT / orig_h)

# 第3步:计算缩放后的实际尺寸
new_w = int(orig_w * scale)
new_h = int(orig_h * scale)

# 执行高质量缩放
img_resized = img.resize((new_w, new_h), Image.Resampling.LANCZOS)

# 第4步:创建1280×720画布,居中粘贴图片
canvas = Image.new("RGB", (TARGET_WIDTH, TARGET_HEIGHT), FILL_COLOR)
offset_x = (TARGET_WIDTH - new_w) // 2  # 水平居中偏移
offset_y = (TARGET_HEIGHT - new_h) // 2  # 垂直居中偏移
canvas.paste(img_resized, (offset_x, offset_y))