调整验证码图片大小

This commit is contained in:
2026-06-12 20:18:23 +08:00
parent 131f06c720
commit bac4a507aa
4 changed files with 56 additions and 15 deletions

View File

@@ -38,6 +38,16 @@ NAME_REGEX = re.compile(r'^[\u4e00-\u9fa5a-zA-Z0-9_]{2,20}$')
# 文件名中不安全的字符
UNSAFE_FILENAME_CHARS = re.compile(r'[<>:"/\\|?*\x00-\x1f]')
# 验证码图片参数
CAPTCHA_IMAGE_SIZE = (320, 100)
CAPTCHA_FONT_SIZE = 68
CAPTCHA_FONT_PATHS = (
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
"/usr/local/share/fonts/DejaVuSans-Bold.ttf",
"/System/Library/Fonts/Supplemental/Arial Bold.ttf",
"/System/Library/Fonts/Supplemental/Verdana Bold.ttf",
)
# ── 工具函数 ────────────────────────────────────────────────────────
def sanitize_name(name: str) -> str | None:
@@ -88,9 +98,25 @@ def generate_captcha_text(length: int = 4) -> str:
return ''.join(random.choices(chars, k=length))
def load_captcha_font(size: int = CAPTCHA_FONT_SIZE) -> ImageFont.ImageFont:
"""加载适合验证码的大号字体,兼容 Linux/Docker 和 macOS 本地环境"""
for font_path in CAPTCHA_FONT_PATHS:
if not os.path.exists(font_path):
continue
try:
return ImageFont.truetype(font_path, size)
except OSError:
continue
try:
return ImageFont.truetype("DejaVuSans-Bold.ttf", size)
except OSError:
return ImageFont.load_default(size=size)
def generate_captcha_image(text: str) -> Image.Image:
"""生成验证码图片(含干扰线和噪点)"""
width, height = 320, 100
width, height = CAPTCHA_IMAGE_SIZE
# 浅色随机背景
bg_color = (random.randint(235, 255), random.randint(235, 255), random.randint(235, 255))
image = Image.new('RGB', (width, height), bg_color)
@@ -109,15 +135,15 @@ def generate_captcha_image(text: str) -> Image.Image:
dot_color = (random.randint(140, 200), random.randint(140, 200), random.randint(140, 200))
draw.point((x, y), fill=dot_color)
# 绘制文字
try:
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 65)
except OSError:
font = ImageFont.load_default()
font = load_captcha_font()
char_slot_width = width // len(text)
for i, char in enumerate(text):
x = 20 + i * 72
y = random.randint(6, 18)
bbox = draw.textbbox((0, 0), char, font=font)
char_width = bbox[2] - bbox[0]
char_height = bbox[3] - bbox[1]
x = i * char_slot_width + (char_slot_width - char_width) // 2 - bbox[0] + random.randint(-4, 4)
y = (height - char_height) // 2 - bbox[1] + random.randint(-5, 5)
color = (random.randint(0, 80), random.randint(0, 80), random.randint(0, 80))
draw.text((x, y), char, font=font, fill=color)