更新版本,压缩图片跟小一点源码
resize2K.py
"""
批量处理图片像素大小,将大于目标像素的图片按比例调整到目标像素以下
目标像素: 3686400 (即 3686400 + 20000 的阈值)
"""
from PIL import Image
import os
import json
import glob
Image.MAX_IMAGE_PIXELS = None
TARGET_PIXELS = 3686400 / 2              
THRESHOLD_PIXELS = TARGET_PIXELS + 20000  
WHITELIST_FILE = "whitelist.json"  
def load_whitelist():
    """加载白名单"""
    if os.path.exists(WHITELIST_FILE):
        try:
            with open(WHITELIST_FILE, 'r', encoding='utf-8') as f:
                return set(json.load(f))
        except Exception as e:
            print(f"加载白名单失败: {e},将创建新的白名单")
            return set()
    return set()
def save_whitelist(whitelist):
    """保存白名单"""
    try:
        with open(WHITELIST_FILE, 'w', encoding='utf-8') as f:
            json.dump(list(whitelist), f, ensure_ascii=False, indent=2)
        print(f"白名单已保存: {WHITELIST_FILE}")
    except Exception as e:
        print(f"保存白名单失败: {e}")
def needs_resize(width, height):
    """检查图片是否需要调整"""
    total_pixels = width * height
    print(f"  像素检查: {width} x {height} = {total_pixels:,} (阈值: {THRESHOLD_PIXELS:,})")
    return total_pixels > THRESHOLD_PIXELS
def calculate_new_size(width, height):
    """计算调整后的新尺寸,保持宽高比"""
    
    current_pixels = width * height
    scale_ratio = (TARGET_PIXELS / current_pixels) ** 0.5  
    
    new_width = int(width * scale_ratio)
    new_height = int(height * scale_ratio)
    
    
    final_pixels = new_width * new_height
    if final_pixels > TARGET_PIXELS:
        
        adjustment = (TARGET_PIXELS / final_pixels) ** 0.5
        new_width = int(new_width * adjustment)
        new_height = int(new_height * adjustment)
    
    print(f"  缩放计算: {width}x{height} -> {new_width}x{new_height}")
    print(f"  像素变化: {current_pixels:,} -> {new_width * new_height:,}")
    
    return new_width, new_height
def resize_image_direct(input_path, output_path, quality=85):
    """直接处理图片 - 包含超大图片删除功能"""
    try:
        with Image.open(input_path) as img:
            
            if img.mode != 'RGB':
                img = img.convert('RGB')
            
            width, height = img.size
            total_pixels = width * height
            
            
            if total_pixels > 150000000:  
                print(f"  ⚠️ 图片像素过大: {total_pixels:,} > 150,000,000")
                print(f"  🗑️ 删除文件: {os.path.basename(input_path)}")
                
                
                img.close()
                
                
                try:
                    os.remove(input_path)
                    if os.path.exists(input_path):
                        print("  ✗ 文件删除失败")
                        return False
                    else:
                        print("  ✓ 文件已成功删除")
                        return True
                except Exception as delete_error:
                    print(f"  ✗ 删除文件时出错: {delete_error}")
                    return False
            
            print(f"  图片尺寸: {width}x{height} (像素: {total_pixels:,})")
            
            
            new_width, new_height = calculate_new_size(width, height)
            
            
            if new_width == width and new_height == height:
                print("  无需调整,尺寸相同")
                return False
            
            print(f"  新尺寸: {new_width}x{new_height}")
            print(f"  缩放比例: {new_width/width*100:.1f}%")
            
            
            resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
            
            
            resized_img.save(output_path, 'JPEG', quality=quality, optimize=True)
            
            
            if os.path.exists(output_path):
                
                new_size = os.path.getsize(output_path) / 1024
                print(f"  文件大小:  {new_size:.1f}KB")
                print(f"  ✓ 调整完成: {output_path}")
                return True
            else:
                print("  ✗ 文件保存失败")
                return False
            
    except Exception as e:
        print(f"  ✗ 处理失败: {e}")
        return False
def process_single_image(input_path, output_path=None, quality=85):
    """处理单张图片"""
    try:
        print(f"\n处理图片: {os.path.basename(input_path)}")
        
        
        if not os.path.exists(input_path):
            print(f"  ✗ 文件不存在: {input_path}")
            return False, 0
        
        with Image.open(input_path) as img:
            width, height = img.size
            total_pixels = width * height
            
            print(f"  原尺寸: {width}x{height}")
            print(f"  总像素: {total_pixels:,}")
            
            if not needs_resize(width, height):
                print("  ✓ 无需调整,像素未超过阈值")
                return False, total_pixels
            
            
            if output_path is None:
                output_path = input_path  
            
            success = resize_image_direct(input_path, output_path, quality)
            return success, total_pixels
            
    except Exception as e:
        print(f"  ✗ 处理错误: {e}")
        return False, 0
def batch_process_images(quality=85, overwrite=True):
    """批量处理当前目录下的所有JPG图片"""
    print("开始批量处理图片...")
    print(f"目标像素: {TARGET_PIXELS:,}")
    print(f"调整阈值: {THRESHOLD_PIXELS:,}")
    print("-" * 60)
    
    
    jpg_files = []
    for pattern in ["*.jpg", "*.JPG", "*.jpeg", "*.JPEG"]:
        jpg_files.extend(glob.glob(pattern))
    
    
    jpg_files = list(set(jpg_files))
    
    if not jpg_files:
        print("当前目录下未找到JPG图片文件")
        print("支持的格式: .jpg, .jpeg (不区分大小写)")
        return
    
    print(f"找到 {len(jpg_files)} 个JPG文件:")
    for i, file in enumerate(jpg_files, 1):
        print(f"  {i}. {file}")
    print()
    
    
    whitelist = load_whitelist()
    if whitelist:
        print(f"白名单中有 {len(whitelist)} 个文件:")
        for file in whitelist:
            print(f"  - {file}")
    else:
        print("白名单为空")
    print()
    
    
    processed_count = 0
    resized_count = 0
    skipped_whitelist = 0
    skipped_small = 0
    
    for jpg_file in jpg_files:
        filename = os.path.basename(jpg_file)
        
        
        if filename in whitelist:
            print(f"跳过白名单文件: {filename}")
            skipped_whitelist += 1
            continue
        
        
        if overwrite:
            output_path = jpg_file  
        else:
            name, ext = os.path.splitext(jpg_file)
            output_path = f"{name}_resized{ext}"
        
        success, original_pixels = process_single_image(jpg_file, output_path, quality)
        
        if success:
            processed_count += 1
            resized_count += 1
        else:
            processed_count += 1
            if original_pixels <= THRESHOLD_PIXELS and original_pixels > 0:
                
                whitelist.add(filename)
                skipped_small += 1
                print(f"  ✓ 添加到白名单: {filename}")
    
    
    if skipped_small > 0:
        save_whitelist(whitelist)
    
    
    print("-" * 60)
    print("处理完成!统计信息:")
    print(f"总文件数: {len(jpg_files)}")
    print(f"已处理: {processed_count}")
    print(f"已调整: {resized_count}")
    print(f"跳过(白名单): {skipped_whitelist}")
    print(f"跳过(像素小): {skipped_small}")
    print(f"白名单文件数: {len(whitelist)}")
def debug_single_file(filename):
    """调试单个文件"""
    if not os.path.exists(filename):
        print(f"文件不存在: {filename}")
        return
    
    print(f"调试文件: {filename}")
    with Image.open(filename) as img:
        width, height = img.size
        total_pixels = width * height
        print(f"尺寸: {width}x{height}")
        print(f"像素: {total_pixels:,}")
        print(f"阈值: {THRESHOLD_PIXELS:,}")
        print(f"需要调整: {needs_resize(width, height)}")
        
        if needs_resize(width, height):
            new_width, new_height = calculate_new_size(width, height)
            print(f"新尺寸: {new_width}x{new_height}")
            print(f"新像素: {new_width * new_height:,}")
def main():
    """主函数"""
    import argparse
    
    parser = argparse.ArgumentParser(description='批量调整图片像素大小')
    parser.add_argument('--quality', '-q', type=int, default=85, 
                       help='JPEG质量 (1-100,默认85)')
    parser.add_argument('--no-overwrite', action='store_true',
                       help='不覆盖原文件,创建新文件')
    parser.add_argument('--whitelist', action='store_true',
                       help='显示白名单')
    parser.add_argument('--remove', metavar='FILENAME',
                       help='从白名单中移除指定文件')
    parser.add_argument('--clear-whitelist', action='store_true',
                       help='清空白名单')
    parser.add_argument('--debug', metavar='FILENAME',
                       help='调试单个文件')
    
    args = parser.parse_args()
    
    
    if not 1 <= args.quality <= 100:
        print("错误:质量参数必须在1-100之间")
        return
    
    
    if args.debug:
        debug_single_file(args.debug)
    elif args.whitelist:
        whitelist = load_whitelist()
        if whitelist:
            print("白名单文件:")
            for filename in sorted(whitelist):
                print(f"  - {filename}")
        else:
            print("白名单为空")
    elif args.remove:
        whitelist = load_whitelist()
        if args.remove in whitelist:
            whitelist.remove(args.remove)
            save_whitelist(whitelist)
            print(f"已从白名单移除: {args.remove}")
        else:
            print(f"文件不在白名单中: {args.remove}")
    elif args.clear_whitelist:
        if os.path.exists(WHITELIST_FILE):
            os.remove(WHITELIST_FILE)
            print("白名单已清空")
        else:
            print("白名单文件不存在")
    else:
        
        overwrite = not args.no_overwrite
        batch_process_images(quality=args.quality, overwrite=overwrite)
if __name__ == "__main__":
    
    import sys
    if len(sys.argv) == 1:
        print("图片像素批量调整工具")
        print("功能:将像素大于3,706,400的图片调整到3,686,400像素以下")
        print("\n直接开始批量处理...")
        print("=" * 60)
        batch_process_images(quality=85, overwrite=True)
    else:
        main()