#!/usr/bin/env python3 """ 图片尺寸压缩工具 将宽度超过 2180 像素的图片等比例压缩 """ import os import sys import subprocess from pathlib import Path # 配置 MAX_WIDTH = 2180 SOURCE_DIR = Path('/home/ubuntu/images') BACKUP_DIR = SOURCE_DIR / 'original_backup' def get_image_size(filepath): """获取图片尺寸""" try: result = subprocess.run( ['identify', '-format', '%w %h', str(filepath)], capture_output=True, text=True, check=True ) width, height = map(int, result.stdout.strip().split()) return width, height except: return None, None def resize_image(filepath, output_path): """压缩图片,保持比例,宽度限制为 MAX_WIDTH""" try: # 使用 ImageMagick convert # -resize 2180x> 表示宽度最大2180,高度自适应,>表示只缩小不放大 cmd = [ 'convert', str(filepath), '-resize', f'{MAX_WIDTH}x>', '-quality', '90', # 保持较好质量 str(output_path) ] subprocess.run(cmd, check=True, capture_output=True) return True except Exception as e: print(f" ❌ 压缩失败: {e}") return False def main(): print("=" * 60) print(f"🖼️ 图片尺寸压缩工具") print(f" 最大宽度: {MAX_WIDTH}px") print(f" 源目录: {SOURCE_DIR}") print("=" * 60) if not SOURCE_DIR.exists(): print(f"❌ 目录不存在: {SOURCE_DIR}") sys.exit(1) # 支持的图片格式 extensions = {'.jpg', '.jpeg', '.png', '.webp', '.gif', '.bmp'} # 收集需要处理的图片 to_process = [] for file in SOURCE_DIR.iterdir(): if file.is_file() and file.suffix.lower() in extensions: width, height = get_image_size(file) if width and width > MAX_WIDTH: to_process.append({ 'file': file, 'width': width, 'height': height }) if not to_process: print("\n✅ 所有图片尺寸都符合要求,无需压缩") return print(f"\n📋 发现 {len(to_process)} 张需要压缩的图片:\n") for item in to_process: print(f" {item['file'].name}: {item['width']}x{item['height']}") # 确认 print(f"\n⚠️ 将备份原图到: {BACKUP_DIR}") response = input("\n是否开始压缩? [y/N]: ").strip().lower() if response != 'y': print("\n❌ 已取消") return # 创建备份目录 BACKUP_DIR.mkdir(exist_ok=True) # 处理图片 print("\n" + "=" * 60) success_count = 0 for i, item in enumerate(to_process, 1): file = item['file'] print(f"\n[{i}/{len(to_process)}] {file.name}") print(f" 原尺寸: {item['width']}x{item['height']}") # 备份原图 backup_path = BACKUP_DIR / file.name try: os.rename(file, backup_path) except Exception as e: print(f" ❌ 备份失败: {e}") continue # 压缩 if resize_image(backup_path, file): new_width, new_height = get_image_size(file) orig_size = backup_path.stat().st_size / 1024 new_size = file.stat().st_size / 1024 print(f" 新尺寸: {new_width}x{new_height}") print(f" 大小: {orig_size:.1f}KB → {new_size:.1f}KB") success_count += 1 else: # 恢复备份 os.rename(backup_path, file) print(f" ❌ 已恢复原图") # 汇总 print("\n" + "=" * 60) print(f"✅ 完成: {success_count}/{len(to_process)} 张图片已压缩") print(f"📁 备份位置: {BACKUP_DIR}") if success_count > 0: print(f"\n💡 如需恢复,执行:") print(f" cp {BACKUP_DIR}/* {SOURCE_DIR}/") if __name__ == '__main__': main()