Don’t say much, just go to the code.

import os
from PIL import Image


def compress_image_to_target(input_path, output_path, max_size_kb):
    """
    严格限制文件大小不超过目标值。
    如果原图已经小于目标值,直接跳过,不做任何处理(保证画质)。
    """
    max_bytes = max_size_kb * 1024

    try:
        img = Image.open(input_path)
        # 兼容 PNG 等格式
        if img.mode in ("RGBA", "P"):
            img = img.convert("RGB")
    except Exception as e:
        print(f"[错误] 无法打开图片 {input_path}: {e}")
        return

    original_size = os.path.getsize(input_path)

    # --- 核心逻辑:只要小于目标值,直接复制/保存,不进行任何有损操作 ---
    if original_size <= max_bytes:
        # 这里用 quality=95 是为了确保存储效率,但几乎不损失画质
        # 如果是非 JPEG 格式,这里会转为 JPEG 以节省空间
        img.save(output_path, quality=95, optimize=True)
        print(f"[跳过] {os.path.basename(input_path)} ({original_size / 1024:.1f}KB) 已达标,保持原画质")
        return

    temp_path = output_path + ".tmp.jpg"

    # --- 阶段一:仅降低质量 (从 95 降到 10) ---
    quality = 95
    while quality > 10:
        img.save(temp_path, quality=quality, optimize=True)
        current_size = os.path.getsize(temp_path)

        # 只要小于等于目标值,立即成功退出
        if current_size <= max_bytes:
            os.replace(temp_path, output_path)
            print(f"[成功] {os.path.basename(input_path)} -> 质量{quality} -> {current_size / 1024:.1f}KB")
            return

        quality -= 5

    # --- 阶段二:缩小尺寸 ---
    # 如果降质量还是太大,开始按比例缩小
    width, height = img.size
    ratio = 0.9

    while ratio > 0.2:
        new_size = (int(width * ratio), int(height * ratio))
        if new_size[0] < 100 or new_size[1] < 100: break

        resized_img = img.resize(new_size, Image.Resampling.LANCZOS)
        resized_img.save(temp_path, quality=80, optimize=True)

        current_size = os.path.getsize(temp_path)

        if current_size <= max_bytes:
            os.replace(temp_path, output_path)
            print(f"[成功] {os.path.basename(input_path)} -> 尺寸{ratio * 100:.0f}% -> {current_size / 1024:.1f}KB")
            return

        ratio -= 0.1

    # --- 极限兜底 ---
    # 实在压不下来,强制保存一个版本
    final_size = (max(300, int(width * 0.5)), max(300, int(height * 0.5)))
    img.resize(final_size, Image.Resampling.LANCZOS).save(output_path, quality=60, optimize=True)
    print(f"[极限] {os.path.basename(input_path)} 强制压缩完成 -> {os.path.getsize(output_path) / 1024:.1f}KB")

    if os.path.exists(temp_path):
        os.remove(temp_path)


def batch_compress_images(input_dir, target_size_kb):
    """批量处理"""
    valid_ext = ('.jpg', '.jpeg', '.png', '.bmp', '.webp')
    output_dir = os.path.join(input_dir, f"已压缩至{target_size_kb}KB以下")

    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    files = [f for f in os.listdir(input_dir) if f.lower().endswith(valid_ext)]
    print(f"目标: 严格控制在 {target_size_kb}KB 以下")

    for filename in files:
        input_path = os.path.join(input_dir, filename)
        output_path = os.path.join(output_dir, filename)
        compress_image_to_target(input_path, output_path, target_size_kb)

    print("\n--- 任务全部完成 ---")


if __name__ == "__main__":
    # =================配置区域=================
    INPUT_FOLDER = r"/Users/admin/Pictures"
    TARGET_SIZE_KB = 50
    # =========================================

    if os.path.exists(INPUT_FOLDER):
        batch_compress_images(INPUT_FOLDER, TARGET_SIZE_KB)
    else:
        print(f"错误:找不到文件夹 {INPUT_FOLDER}")
如何使用这个神器?

使用它非常简单,你只需要三步:

第一步:准备环境

确保你已经安装了Python和Pillow库(PIL的现代版本)。如果没有安装Pillow,在终端或命令行中运行:

pip install pillow

第二步:修改配置

打开脚本,找到最下面的 if __name__ == "__main__": 部分。

  • INPUT_FOLDER: 修改为你存放原始图片的文件夹路径。
  • TARGET_SIZE_KB: 修改为你希望图片达到的目标大小(单位KB)。

第三步:运行脚本

在终端中运行这个Python文件,然后你就可以去喝杯咖啡,等待它自动完成所有工作啦!

python your_script_name.py
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐