177 lines
5.7 KiB
Python
177 lines
5.7 KiB
Python
import os
|
||
import sys
|
||
from PIL import Image
|
||
|
||
def png_to_jpg(input_dir=None, bg_color=(0, 0, 0), quality=100):
|
||
"""
|
||
将指定目录下的所有PNG图片转换为JPG格式
|
||
|
||
Args:
|
||
input_dir: 输入目录,默认为当前目录
|
||
bg_color: 背景颜色,默认为黑色(0, 0, 0)
|
||
quality: JPG质量,默认为100
|
||
"""
|
||
# 如果未指定输入目录,使用当前目录
|
||
if input_dir is None:
|
||
input_dir = os.getcwd()
|
||
|
||
# 确保目录存在
|
||
if not os.path.exists(input_dir):
|
||
print(f"错误: 目录 '{input_dir}' 不存在")
|
||
return False
|
||
|
||
# 获取所有PNG文件
|
||
png_files = [f for f in os.listdir(input_dir) if f.lower().endswith('.png')]
|
||
|
||
if not png_files:
|
||
print(f"在目录 '{input_dir}' 中未找到PNG文件")
|
||
return True
|
||
|
||
print(f"找到 {len(png_files)} 个PNG文件")
|
||
|
||
# 转换每个PNG文件
|
||
successful = 0
|
||
failed = 0
|
||
|
||
for png_file in png_files:
|
||
try:
|
||
# 构建完整的文件路径
|
||
png_path = os.path.join(input_dir, png_file)
|
||
|
||
# 打开PNG图像
|
||
img = Image.open(png_path)
|
||
|
||
# 如果图像有alpha通道(透明通道),处理透明部分
|
||
if img.mode in ('RGBA', 'LA', 'P'):
|
||
# 创建新的RGB图像,背景为指定颜色
|
||
rgb_img = Image.new('RGB', img.size, bg_color)
|
||
|
||
# 如果是P模式(调色板),先转换为RGBA
|
||
if img.mode == 'P':
|
||
img = img.convert('RGBA')
|
||
|
||
# 将原图像粘贴到新背景上
|
||
if img.mode == 'RGBA':
|
||
# RGBA图像需要分离alpha通道
|
||
rgb_img.paste(img, mask=img.split()[3]) # 使用alpha通道作为蒙版
|
||
elif img.mode == 'LA':
|
||
# LA模式:L是亮度,A是alpha
|
||
rgb_img.paste(img.convert('RGBA'), mask=img.split()[1])
|
||
else:
|
||
# 如果没有alpha通道,直接转换为RGB
|
||
rgb_img = img.convert('RGB')
|
||
|
||
# 生成输出文件名(将.png替换为.jpg)
|
||
jpg_file = os.path.splitext(png_file)[0] + '.jpg'
|
||
jpg_path = os.path.join(input_dir, jpg_file)
|
||
|
||
# 保存为JPG
|
||
rgb_img.save(jpg_path, 'JPEG', quality=quality, optimize=True)
|
||
|
||
print(f"✓ 转换成功: {png_file} -> {jpg_file}")
|
||
successful += 1
|
||
|
||
except Exception as e:
|
||
print(f"✗ 转换失败 {png_file}: {str(e)}")
|
||
failed += 1
|
||
|
||
print(f"\n转换完成: 成功 {successful} 个, 失败 {failed} 个")
|
||
return failed == 0
|
||
|
||
def main():
|
||
"""主函数,处理命令行参数"""
|
||
import argparse
|
||
|
||
parser = argparse.ArgumentParser(
|
||
description='将PNG图片转换为JPG格式,透明背景转为指定颜色',
|
||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||
epilog="""
|
||
示例:
|
||
%(prog)s # 转换当前目录所有PNG,黑色背景,质量100
|
||
%(prog)s -d /path/to/images # 转换指定目录
|
||
%(prog)s -c white -q 90 # 白色背景,质量90
|
||
%(prog)s -c 255,255,255 # 使用RGB值指定白色背景
|
||
"""
|
||
)
|
||
|
||
parser.add_argument(
|
||
'-d', '--directory',
|
||
default='.',
|
||
help='输入目录,默认为当前目录'
|
||
)
|
||
|
||
parser.add_argument(
|
||
'-c', '--color',
|
||
default='black',
|
||
help='背景颜色,支持颜色名或RGB值(如"white"、"255,255,255"),默认为black'
|
||
)
|
||
|
||
parser.add_argument(
|
||
'-q', '--quality',
|
||
type=int,
|
||
default=100,
|
||
choices=range(1, 101),
|
||
metavar='[1-100]',
|
||
help='JPG质量,1-100,默认为100'
|
||
)
|
||
|
||
parser.add_argument(
|
||
'-r', '--recursive',
|
||
action='store_true',
|
||
help='递归处理子目录(注意:本脚本当前版本不支持,已预留接口)'
|
||
)
|
||
|
||
args = parser.parse_args()
|
||
|
||
# 解析颜色参数
|
||
bg_color = (0, 0, 0) # 默认黑色
|
||
|
||
if args.color:
|
||
color_str = args.color.lower().strip()
|
||
|
||
# 预定义颜色
|
||
color_map = {
|
||
'black': (0, 0, 0),
|
||
'white': (255, 255, 255),
|
||
'red': (255, 0, 0),
|
||
'green': (0, 255, 0),
|
||
'blue': (0, 0, 255),
|
||
'transparent': None,
|
||
}
|
||
|
||
if color_str in color_map:
|
||
bg_color = color_map[color_str]
|
||
elif ',' in color_str:
|
||
# 尝试解析RGB值
|
||
try:
|
||
rgb = [int(x.strip()) for x in color_str.split(',')]
|
||
if len(rgb) == 3 and all(0 <= x <= 255 for x in rgb):
|
||
bg_color = tuple(rgb)
|
||
else:
|
||
print(f"警告: 颜色值无效,使用默认黑色")
|
||
except ValueError:
|
||
print(f"警告: 颜色格式无效,使用默认黑色")
|
||
else:
|
||
print(f"警告: 颜色 '{args.color}' 不被识别,使用默认黑色")
|
||
|
||
print(f"设置:")
|
||
print(f" 目录: {args.directory}")
|
||
print(f" 背景色: RGB{bg_color}")
|
||
print(f" 质量: {args.quality}")
|
||
print(f" 递归: {'是' if args.recursive else '否'}")
|
||
print("-" * 40)
|
||
|
||
# 执行转换
|
||
try:
|
||
success = png_to_jpg(args.directory, bg_color, args.quality)
|
||
return 0 if success else 1
|
||
except KeyboardInterrupt:
|
||
print("\n操作被用户中断")
|
||
return 130
|
||
except Exception as e:
|
||
print(f"错误: {str(e)}")
|
||
return 1
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|