#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
批量占位图像生成器
使用 Pillow 库生成纯色或带文字标注的占位图。
支持自定义尺寸、颜色、格式和输出目录。
依赖安装:
pip install Pillow
"""
import argparse
import os
import random
from PIL import Image, ImageDraw, ImageFont
# 常见颜色映射 (名称 -> RGB)
COLOR_MAP = {
'red': (255, 99, 71), # 番茄红
'blue': (70, 130, 180), # 钢蓝
'green': (60, 179, 113), # 海洋绿
'gray': (169, 169, 169),
'darkgray': (105, 105, 105),
'lightgray': (211, 211, 211),
'white': (255, 255, 255),
'black': (0, 0, 0),
'yellow': (255, 255, 0),
'purple': (147, 112, 219),
'orange': (255, 165, 0),
'pink': (255, 182, 193),
}
def parse_color(color_str):
"""将颜色字符串解析为 RGB 元组,支持 #hex 或预定义名称。"""
if color_str is None:
return None
s = color_str.strip().lower()
if s.startswith('#'):
try:
hex_val = s.lstrip('#')
if len(hex_val) != 6:
raise ValueError(f"无效的十六进制颜色: {color_str}")
return tuple(int(hex_val[i:i+2], 16) for i in (0, 2, 4))
except ValueError as e:
raise argparse.ArgumentTypeError(f"颜色格式错误: {e}")
if s in COLOR_MAP:
return COLOR_MAP[s]
# 尝试解析为纯数字 RGB,"255,0,0"
if ',' in s:
parts = s.split(',')
if len(parts) == 3:
try:
return tuple(max(0, min(255, int(p.strip()))) for p in parts)
except ValueError:
pass
raise argparse.ArgumentTypeError(f"无法识别的颜色: {color_str},支持 #RRGGBB 或名称 {list(COLOR_MAP.keys())}")
def create_placeholder_image(width, height, color, text=None, font_size=None):
"""生成单张占位图像并返回 PIL Image 对象。"""
if color is None:
# 随机生成较柔和颜色
color = (random.randint(100, 230), random.randint(100, 230), random.randint(100, 230))
image = Image.new('RGB', (width, height), color)
if text:
draw = ImageDraw.Draw(image)
if font_size is None:
# 根据图像大小自适应字号
font_size = max(12, int(min(width, height) * 0.12))
try:
# 尝试加载默认字体,若失败则使用默认
font = ImageFont.load_default()
# 简单放大字体(Pillow 10+ 支持 size 参数)
font = ImageFont.truetype("DejaVuSans.ttf", font_size) if os.path.exists("DejaVuSans.ttf") else ImageFont.load_default()
except:
font = ImageFont.load_default()
# 计算文字位置居中
text_bbox = draw.textbbox((0, 0), text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
x = (width - text_width) / 2
y = (height - text_height) / 2 - text_bbox[1] # 调整基线
# 为了确保文字可读,在底部添加白色边框描边 (仅当颜色较深时)
draw.text((x, y), text, fill=(255, 255, 255), font=font, stroke_width=1, stroke_fill=(0,0,0))
return image
def main():
parser = argparse.ArgumentParser(
description="批量生成占位图,示例: python placeholder_gen.py --size 800x600 --count 10 --prefix banner --color #3498db --text 'Demo' --out ./images"
)
parser.add_argument('--size', '-s', type=str, default='800x600', help="图片尺寸 宽x高,800x600 或 1024x768")
parser.add_argument('--count', '-n', type=int, default=5, help="生成数量 (默认: 5)")
parser.add_argument('--out', '-o', type=str, default='./placeholder_images', help="输出目录 (默认: ./placeholder_images)")
parser.add_argument('--prefix', '-p', type=str, default='placeholder', help="文件名前缀 (默认: placeholder)")
parser.add_argument('--format', '-f', type=str, default='PNG', choices=['PNG', 'JPEG', 'WEBP', 'BMP'], help="图片格式 (默认: PNG)")
parser.add_argument('--color', '-c', type=str, default=None, help="背景颜色: 十六进制 #RRGGBB 或颜色名称,留空则随机")
parser.add_argument('--text', '-t', type=str, default=None, help="在图片中央显示的文本 (默认无)")
parser.add_argument('--font-size', type=int, default=None, help="文字字号 (默认自动)")
parser.add_argument('--seed', type=int, default=None, help="随机种子,固定颜色随机性")
parser.add_argument('--no-text', action='store_true', help="禁止文本,即使指定 --text 也忽略")
args = parser.parse_args()
# 解析尺寸
try:
w_str, h_str = args.size.lower().split('x')
width, height = int(w_str.strip()), int(h_str.strip())
if width <= 0 or height <= 0:
raise ValueError("宽高必须为正整数")
except ValueError as e:
parser.error(f"尺寸格式错误: {args.size},应类似 800x600")
if args.count <= 0:
parser.error("数量必须大于 0")
# 固定随机种子
if args.seed is not None:
random.seed(args.seed)
# 解析颜色
bg_color = None
if args.color:
try:
bg_color = parse_color(args.color)
except argparse.ArgumentTypeError as e:
parser.error(f"颜色参数错误: {e}")
# 创建输出目录
os.makedirs(args.out, exist_ok=True)
# 处理格式扩展名
ext = args.format.lower()
if ext == 'jpeg':
ext = 'jpg'
elif ext == 'webp':
ext = 'webp'
elif ext == 'bmp':
ext = 'bmp'
# 生成图片
generated = []
for i in range(1, args.count + 1):
filename = f"{args.prefix}_{i}.{ext}"
filepath = os.path.join(args.out, filename)
# 如果指定了文本且不禁用,则显示文本
text_content = args.text if (args.text and not args.no_text) else None
# 生成图像
img = create_placeholder_image(width, height, bg_color, text=text_content, font_size=args.font_size)
# 保存
try:
if ext == 'jpg':
img.save(filepath, quality=90)
else:
img.save(filepath)
generated.append(filepath)
except Exception as e:
print(f"[错误] 保存 {filepath} 失败: {e}")
# 打印结果
print(f"已生成 {len(generated)} 张占位图到: {os.path.abspath(args.out)}")
for p in generated:
print(f" - {p}")
if __name__ == '__main__':
main()
核心功能与使用场景
您可以通过命令行参数灵活控制生成图片的尺寸、数量、颜色和文字标注,适合用于前端开发、设计稿或数据填充。

- 基础用法:运行脚本时,通过
--size指定图片尺寸(如800x600),--count指定生成数量。 - 自定义外观:使用
--color设置背景色(支持#RRGGBB或颜色名称),使用--text在图片中央添加文字。 - 输出控制:通过
--out指定输出文件夹,--prefix设置文件名前缀,--format选择图片格式(PNG/JPEG等)。 - 高级选项:您可以设置
--seed固定随机颜色,或使用--no-text忽略文字参数,方便自动化测试。