176 lines
4.7 KiB
Python
176 lines
4.7 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
相册缩略图生成工具
|
||
为当前目录及所有子目录下的图片生成缩略图
|
||
缩略图存放在每个相册的 thumbnails/ 子目录下
|
||
|
||
特性:
|
||
- 可在任意目录执行(不限定 /home/ubuntu/albums)
|
||
- 递归处理当前目录下所有子目录(不限子目录名称)
|
||
- 已存在的缩略图自动跳过
|
||
- 只处理 jpg/jpeg/png 图片,跳过视频等其他文件
|
||
|
||
使用方法:
|
||
cd 任意目录
|
||
python3 generate_thumbnails.py
|
||
"""
|
||
import os
|
||
import subprocess
|
||
from pathlib import Path
|
||
import time
|
||
|
||
# 配置
|
||
THUMB_WIDTH = 320
|
||
THUMB_QUALITY = 85
|
||
|
||
# 支持的图片格式(只处理图片,跳过视频等其他文件)
|
||
IMAGE_EXTENSIONS = {'.jpg', '.jpeg', '.png'}
|
||
|
||
# 统计信息
|
||
stats = {
|
||
'albums': 0,
|
||
'images_found': 0,
|
||
'generated': 0,
|
||
'skipped': 0,
|
||
'failed': 0
|
||
}
|
||
|
||
|
||
def is_image(filename):
|
||
"""检查是否为图片文件"""
|
||
return Path(filename).suffix.lower() in IMAGE_EXTENSIONS
|
||
|
||
|
||
def generate_thumbnail(img_path, thumb_path):
|
||
"""生成单个缩略图"""
|
||
try:
|
||
# 确保缩略图目录存在
|
||
thumb_path.parent.mkdir(parents=True, exist_ok=True)
|
||
|
||
cmd = [
|
||
'convert', str(img_path),
|
||
'-resize', f'{THUMB_WIDTH}x>',
|
||
'-quality', str(THUMB_QUALITY),
|
||
str(thumb_path)
|
||
]
|
||
subprocess.run(cmd, check=True, capture_output=True, timeout=30)
|
||
return True
|
||
except Exception as e:
|
||
print(f" ❌ 失败: {img_path.name}")
|
||
return False
|
||
|
||
|
||
def process_directory(dir_path, depth=0):
|
||
"""
|
||
递归处理目录
|
||
为当前目录下的每张图片生成缩略图(如果尚未存在)
|
||
"""
|
||
global stats
|
||
|
||
if not dir_path.is_dir():
|
||
return False
|
||
|
||
# 跳过 thumbnails 目录
|
||
if dir_path.name == 'thumbnails':
|
||
return False
|
||
|
||
indent = " " * depth
|
||
|
||
# 收集当前目录的图片
|
||
images = []
|
||
subdirs = []
|
||
|
||
for item in dir_path.iterdir():
|
||
if item.is_dir() and item.name != 'thumbnails':
|
||
subdirs.append(item)
|
||
elif item.is_file() and is_image(item.name):
|
||
images.append(item)
|
||
|
||
# 处理当前目录的图片
|
||
if images:
|
||
stats['albums'] += 1
|
||
print(f"\n{indent}📁 {dir_path.name}")
|
||
print(f"{indent} 发现 {len(images)} 张图片")
|
||
|
||
# 确保 thumbnails 目录存在
|
||
thumb_dir = dir_path / 'thumbnails'
|
||
thumb_dir.mkdir(exist_ok=True)
|
||
|
||
for img in images:
|
||
stats['images_found'] += 1
|
||
|
||
# 检查缩略图是否已存在
|
||
thumb_path = thumb_dir / img.name
|
||
|
||
if thumb_path.exists():
|
||
# 缩略图已存在,跳过
|
||
stats['skipped'] += 1
|
||
continue
|
||
|
||
# 生成缩略图
|
||
if generate_thumbnail(img, thumb_path):
|
||
stats['generated'] += 1
|
||
print(f"{indent} ✓ {img.name}")
|
||
else:
|
||
stats['failed'] += 1
|
||
|
||
# 递归处理子目录(所有子目录,不限名称)
|
||
for subdir in subdirs:
|
||
process_directory(subdir, depth + 1)
|
||
|
||
return len(images) > 0 or len(subdirs) > 0
|
||
|
||
|
||
def print_stats(start_time):
|
||
"""打印统计信息"""
|
||
elapsed = time.time() - start_time
|
||
|
||
print("\n" + "=" * 60)
|
||
print("✅ 缩略图生成完成!")
|
||
print("=" * 60)
|
||
print(f" 处理相册: {stats['albums']} 个")
|
||
print(f" 图片总数: {stats['images_found']} 张")
|
||
print(f" 新生成: {stats['generated']} 张")
|
||
print(f" 跳过(已存在): {stats['skipped']} 张")
|
||
print(f" 失败: {stats['failed']} 张")
|
||
print(f" 耗时: {elapsed:.1f}秒")
|
||
print("=" * 60)
|
||
|
||
|
||
def main():
|
||
"""主函数"""
|
||
# 获取当前目录(执行时所在的目录,不是工具所在目录)
|
||
current_dir = Path.cwd()
|
||
|
||
print("=" * 60)
|
||
print("🖼️ 相册缩略图生成工具")
|
||
print(f" 目标目录: {current_dir}")
|
||
print(f" 缩略图宽度: {THUMB_WIDTH}px")
|
||
print("=" * 60)
|
||
|
||
# 检查 ImageMagick
|
||
try:
|
||
subprocess.run(['convert', '--version'], capture_output=True, check=True)
|
||
except:
|
||
print("❌ 未安装 ImageMagick,请先安装: sudo apt install imagemagick")
|
||
return
|
||
|
||
start_time = time.time()
|
||
|
||
# 递归处理
|
||
print("\n🔍 扫描相册...")
|
||
process_directory(current_dir)
|
||
|
||
# 打印统计
|
||
print_stats(start_time)
|
||
|
||
# 提示
|
||
print("\n💡 提示:")
|
||
print(" - 可在任意目录执行此工具")
|
||
print(" - 已存在的缩略图会自动跳过")
|
||
print(" - 新增的图片会被自动处理")
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|