图片等比压缩.md 4.7 KB

#python #前端

很多时候,网页和实际游戏不一样,是不需要使用到,太大尺寸,或者太大分辨率的,但是表现要基本一致,所以可以考虑,使用等比压缩图片; 在执行python脚本逻辑之前,需要确保一下,以下python库,是正常的,一个是路径,另一个是Pillow图像库

 pip install pathlib
 pip install Pillow

然后,是等比压缩的python脚本,逻辑实现:

resize.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
from PIL import Image
from pathlib import Path

def resize_image(
    input_path: str,
    output_path: str = None,
    max_size: tuple = None,
    scale: float = None,
    quality: int = 85,
    keep_exif: bool = True
) -> None:
    """
    等比缩小图片
    
    :param input_path: 输入图片路径
    :param output_path: 输出路径(默认添加后缀 _resized)
    :param max_size: 最大尺寸 (width, height),优先级高于 scale
    :param scale: 缩放比例(0-1之间)
    :param quality: 输出质量(1-100)
    :param keep_exif: 是否保留EXIF信息
    """
    if not os.path.exists(input_path):
        raise FileNotFoundError(f"输入文件不存在: {input_path}")
    
    if max_size is None and scale is None:
        raise ValueError("必须指定 max_size 或 scale 参数")
    
    # 设置默认输出路径
    if output_path is None:
        p = Path(input_path)
        output_path = str(p.parent / f"{p.stem}_resized{p.suffix}")
    
    with Image.open(input_path) as img:
        # 保留EXIF信息
        exif = img.info.get('exif') if keep_exif else None
        
        # 计算新尺寸
        width, height = img.size
        if max_size:
            new_width, new_height = max_size
            ratio = min(new_width/width, new_height/height)
        else:
            ratio = scale
        
        new_size = (int(width * ratio), int(height * ratio))
        
        # 使用LANCZOS算法保持高质量缩小
        img_resized = img.resize(new_size, Image.LANCZOS)
        
        # 保存图片(根据格式调整参数)
        save_kwargs = {'quality': quality}
        if input_path.lower().endswith('.png'):
            save_kwargs['compress_level'] = 6
        if exif:
            save_kwargs['exif'] = exif
            
        img_resized.save(output_path, **save_kwargs)
        print(f"图片已保存至: {output_path} (原始尺寸: {img.size} -> 新尺寸: {new_size})")

def batch_resize(
    input_dir: str,
    output_dir: str = None,
    **kwargs
) -> None:
    """
    批量处理目录中的所有图片
    """
    if not os.path.isdir(input_dir):
        raise NotADirectoryError(f"输入目录不存在: {input_dir}")
    
    if output_dir is None:
        output_dir = os.path.join(input_dir, "resized")
    os.makedirs(output_dir, exist_ok=True)
    
    supported_formats = ('.jpg', '.jpeg', '.png', '.webp')
    for filename in os.listdir(input_dir):
        if filename.lower().endswith(supported_formats):
            input_path = os.path.join(input_dir, filename)
            output_path = os.path.join(output_dir, filename)
            try:
                resize_image(input_path, output_path, **kwargs)
            except Exception as e:
                print(f"处理失败 {filename}: {str(e)}")

if __name__ == "__main__":
    import argparse
    
    parser = argparse.ArgumentParser(description="图片等比缩小工具")
    parser.add_argument("input", help="输入文件或目录路径")
    parser.add_argument("--output", help="输出路径(文件或目录)")
    parser.add_argument("--max_size", nargs=2, type=int, 
                       help="最大宽高(如 800 600)")
    parser.add_argument("--scale", type=float, 
                       help="缩放比例(如 0.5 表示缩小一半)")
    parser.add_argument("--quality", type=int, default=85,
                       help="输出质量(1-100,默认85)")
    parser.add_argument("--no_exif", action="store_true",
                       help="不保留EXIF信息")
    
    args = parser.parse_args()
    
    kwargs = {
        'max_size': tuple(args.max_size) if args.max_size else None,
        'scale': args.scale,
        'quality': args.quality,
        'keep_exif': not args.no_exif
    }
    
    if os.path.isfile(args.input):
        resize_image(args.input, args.output, **kwargs)
    elif os.path.isdir(args.input):
        batch_resize(args.input, args.output, **kwargs)
    else:
        print("错误:输入路径必须是文件或目录")

调用方式

同一文件夹,示例: 等比缩放0.6倍

python .\resize.py .\ImageReSize\ --output .\ImageReSize_2\ --scale 0.6

![[Pasted image 20250620103001.png]]