如何批量转换多张图片格式
← 返回博客
如何批量转换多张图片格式
· 5 分钟阅读
批量转换的应用场景
在以下场景中,批量转换图片是必要的:电商平台需要将大量产品照片从 PNG 转为 WebP 以优化加载速度;博客或新闻站点有大量历史 JPG 图片需要迁移到 WebP;扫描了大量 BMP 格式的旧照片需要转换为 JPG 存档;网站重构时需要统一所有图片格式;游戏开发中需要将设计师提供的 PSD/PNG 批量转换为引擎支持的格式。
方法1:ImageMagick 命令行(推荐)
# ImageMagick 批量转换大全
# ImageMagick batch conversion complete guide
# 安装 / Install
# macOS: brew install imagemagick
# Ubuntu: sudo apt install imagemagick
# 批量 JPG 转 WebP(保留原文件)
# Batch JPG to WebP (keep originals)
for f in *.jpg *.jpeg; do
[ -f "$f" ] && convert "$f" -quality 80 "${f%.*}.webp"
done
# 批量 PNG 转 WebP(无损)
# Batch PNG to WebP (lossless)
for f in *.png; do
[ -f "$f" ] && convert "$f" -define webp:lossless=true "${f%.png}.webp"
done
# 使用 mogrify 就地转换(替换原文件格式)
# Use mogrify for in-place conversion (change format in directory)
mogrify -format webp -quality 80 *.jpg
mogrify -format jpg -quality 85 *.bmp
# 递归处理子目录
# Process subdirectories recursively
find . -name "*.jpg" -exec sh -c \
'convert "$1" -quality 80 "${1%.jpg}.webp"' _ {} \;
# 并行转换(利用多核 CPU)
# Parallel conversion (using multiple CPU cores)
find . -name "*.jpg" | \
xargs -P 8 -I{} sh -c 'convert "$1" -quality 80 "${1%.jpg}.webp"' _ {}
方法2:Python 脚本(灵活定制)
from PIL import Image
import os
import glob
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
import time
def convert_image(input_path, output_format, quality=80, output_dir=None):
"""单图片转换函数"""
input_path = Path(input_path)
if output_dir:
output_path = Path(output_dir) / input_path.with_suffix(f'.{output_format}').name
else:
output_path = input_path.with_suffix(f'.{output_format}')
try:
with Image.open(input_path) as img:
orig_size = input_path.stat().st_size
if output_format.lower() == 'webp':
if img.mode in ('RGBA', 'P'):
img.save(output_path, 'WEBP', lossless=True)
else:
img.convert('RGB').save(output_path, 'WEBP', quality=quality)
elif output_format.lower() in ('jpg', 'jpeg'):
if img.mode != 'RGB':
img = img.convert('RGB')
img.save(output_path, 'JPEG', quality=quality)
else:
img.save(output_path, output_format.upper())
new_size = output_path.stat().st_size
reduction = (1 - new_size / orig_size) * 100
return (str(input_path), reduction)
except Exception as e:
return (str(input_path), f"ERROR: {e}")
def batch_convert(source_dir, output_format='webp', quality=80,
output_dir=None, workers=4):
"""批量转换图片"""
if output_dir:
os.makedirs(output_dir, exist_ok=True)
patterns = ['*.jpg', '*.jpeg', '*.png', '*.bmp']
files = []
for pattern in patterns:
files.extend(glob.glob(os.path.join(source_dir, pattern)))
print(f"Found {len(files)} images to convert...")
start = time.time()
with ThreadPoolExecutor(max_workers=workers) as executor:
results = list(executor.map(
lambda f: convert_image(f, output_format, quality, output_dir),
files
))
elapsed = time.time() - start
successes = [r for r in results if isinstance(r[1], float)]
avg_reduction = sum(r[1] for r in successes) / len(successes) if successes else 0
print(f"Done: {len(successes)}/{len(files)} files in {elapsed:.1f}s")
print(f"Average size reduction: {avg_reduction:.1f}%")
batch_convert('./images', output_format='webp', quality=80,
output_dir='./images_webp', workers=8)
方法3:Sharp (Node.js) 高性能批量转换
// npm install sharp glob
const sharp = require('sharp');
const glob = require('glob');
const path = require('path');
const fs = require('fs');
async function batchConvert(sourceDir, outputFormat, quality = 80) {
const files = glob.sync(`${sourceDir}/**/*.{jpg,jpeg,png,bmp}`);
const outputDir = `${sourceDir}_${outputFormat}`;
fs.mkdirSync(outputDir, { recursive: true });
let converted = 0;
let totalSaved = 0;
// 并行处理,每批 10 个文件
// Process in parallel, 10 files per batch
for (let i = 0; i {
const relPath = path.relative(sourceDir, file);
const outputPath = path.join(outputDir,
relPath.replace(/\.[^.]+$/, `.${outputFormat}`));
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
const origSize = fs.statSync(file).size;
await sharp(file)[outputFormat]({ quality }).toFile(outputPath);
const newSize = fs.statSync(outputPath).size;
totalSaved += origSize - newSize;
converted++;
}));
process.stdout.write(`\rConverted: ${converted}/${files.length}`);
}
console.log(`\nDone! Saved ${(totalSaved/1024/1024).toFixed(1)} MB total`);
}
batchConvert('./public/images', 'webp', 80);
自动化工作流:文件夹监控
对于需要持续添加新图片的场景(如电商每日上架新产品),可以设置文件夹监控:一旦有新图片添加到"上传"文件夹,自动触发转换脚本,将图片转换为 WebP 并保存到"发布"文件夹。在 Linux/macOS 上可以使用 inotifywait 或 fswatch;在 Node.js 中可以使用 chokidar 库;在 Python 中可以使用 watchdog 库。
# Python 文件夹监控自动转换
# Python folder monitoring auto-conversion
# pip install watchdog pillow
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from PIL import Image
import time, os
class ImageHandler(FileSystemEventHandler):
def on_created(self, event):
if event.is_directory:
return
if event.src_path.lower().endswith(('.jpg', '.png', '.jpeg')):
self.convert_to_webp(event.src_path)
def convert_to_webp(self, path):
output = path.rsplit('.', 1)[0] + '.webp'
with Image.open(path) as img:
img.save(output, 'WEBP', quality=80)
print(f"Auto-converted: {path} -> {output}")
observer = Observer()
observer.schedule(ImageHandler(), path='./uploads', recursive=False)
observer.start()
print("Monitoring ./uploads for new images...")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
批量转换的性能优化
处理大量图片时,性能优化非常重要。关键建议:(1)使用多线程/多进程并行处理,充分利用多核 CPU;(2)Sharp(Node.js)比 Pillow(Python)快 5–10 倍,处理大量图片时推荐 Sharp;(3)如果图片数量超过 10000 张,考虑分批处理(每批 500–1000 张)以防内存溢出;(4)在 SSD 上运行比在 HDD 上快 3–5 倍(I/O 是瓶颈);(5)预先检查并跳过已经转换过的文件,避免重复工作。
立即尝试在线工具,无需安装,免费使用。
打开工具 →
立即免费使用相关工具
免费使用 →