如何在PIL图像中单独旋转每个验证码字符?
实现PIL验证码单个字符单独旋转的方法
核心思路是为每个字符创建独立的透明临时图像,绘制字符后进行旋转,再将旋转后的图像粘贴到主验证码画布上,解决直接绘制无法旋转字符的问题。以下是修改后的完整代码:
import random from PIL import Image, ImageDraw, ImageFont def generate_random_string(length): random_string = "" for i in range(length): random_string += random.choice('1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ') return random_string def draw_random_ellipse(draw): # 补充原代码缺失的随机椭圆绘制函数 x1 = random.randint(0, 400) y1 = random.randint(0, 200) x2 = x1 + random.randint(10, 50) y2 = y1 + random.randint(10, 50) draw.ellipse([x1, y1, x2, y2], fill=(random.randint(150,255), random.randint(150,255), random.randint(150,255), 128)) def generate_captcha(): fonts = ["Aaargh.ttf", "SerpentineBoldItalic.ttf", "FUTURAM.ttf"] character_count = random.randrange(6, 10) captcha_string = generate_random_string(character_count) # 定义背景色(替换原代码未定义的default_color变量) bg_color = (255, 255, 255) captcha_image = Image.new("RGBA", (400, 200), bg_color) draw = ImageDraw.Draw(captcha_image, "RGBA") # 绘制干扰椭圆 for i in range(20): draw_random_ellipse(draw) # 初始位置 x = 10 + random.randrange(0, 50) y = 100 + random.randrange(-20, 20) for letter in captcha_string: selected_font = random.choice(fonts) font_style = ImageFont.truetype(selected_font, 50) # 1. 创建透明临时图像,尺寸足够容纳旋转后的字符 temp_img = Image.new("RGBA", (80, 80), (255, 255, 255, 0)) temp_draw = ImageDraw.Draw(temp_img) # 2. 在临时图像居中位置绘制字符,避免旋转裁剪 text_bbox = temp_draw.textbbox((0,0), letter, font=font_style) text_width = text_bbox[2] - text_bbox[0] text_height = text_bbox[3] - text_bbox[1] temp_x = (80 - text_width) // 2 temp_y = (80 - text_height) // 2 temp_draw.text((temp_x, temp_y), letter, (0, 0, 0), font=font_style) # 3. 随机生成旋转角度(-30到30度区间) rotate_angle = random.randint(-30, 30) rotated_img = temp_img.rotate(rotate_angle, expand=True) # 4. 计算粘贴位置,让字符垂直居中于基准线 rotated_height = rotated_img.height paste_y = y - rotated_height // 2 # 5. 粘贴旋转后的字符,用alpha通道做掩码保证透明效果 captcha_image.paste(rotated_img, (x, paste_y), rotated_img) # 6. 更新x坐标,根据旋转后的宽度调整间距避免重叠 x += rotated_img.width + random.randint(5, 15) return (captcha_image, captcha_string)
关键细节说明
- 透明临时图像:采用
RGBA模式并设置全透明背景,确保旋转后的字符边缘不会覆盖主图的背景或干扰元素。 - 居中绘制字符:通过
textbbox获取字符的精确尺寸,在临时图像中居中绘制,避免旋转时字符被裁剪。 - 旋转参数:
rotate方法的expand=True参数会自动扩展图像尺寸,完整容纳旋转后的字符内容。 - 掩码粘贴:
paste方法传入旋转后的图像作为第三个参数,利用其alpha通道作为掩码,仅粘贴字符的非透明区域。
内容的提问来源于stack exchange,提问作者mattdub
相关产品推荐
相关产品推荐

