function create_signature_image
Generates a synthetic signature image for a given name, either as stylized text or as a random hand-drawn curve, and saves it as a PNG file with transparent background.
/tf/active/vicechatdev/document_auditor/generate_sample_signatures.py
17 - 140
moderate
Purpose
This function creates realistic-looking signature images programmatically for use in document generation, testing, or mock data scenarios. It attempts to use handwriting-style fonts from the system and can generate either text-based signatures (with optional underlines or slant) or curve-based signatures that mimic hand-drawn signatures with random flourishes and loops.
Source Code
def create_signature_image(name, output_path, width=400, height=150, bg_color=(255, 255, 255, 0)):
"""
Create a signature image for the given name
Args:
name (str): Name of the person
output_path (str): Path to save the signature image
width (int): Width of the signature image
height (int): Height of the signature image
bg_color (tuple): Background color (RGBA)
Returns:
str: Path to the created signature image
"""
# Create a transparent image
image = Image.new('RGBA', (width, height), bg_color)
draw = ImageDraw.Draw(image)
# Try to load a font for the signature
try:
# Try to find a handwriting-like font
font_paths = [
'/usr/share/fonts/truetype/dejavu/DejaVuSans-Oblique.ttf', # Common in Linux
'/usr/share/fonts/truetype/liberation/LiberationSans-Italic.ttf', # Another Linux option
'/Library/Fonts/Apple Chancery.ttf', # Mac
'C:\\Windows\\Fonts\\BRUSHSCI.TTF', # Windows
'C:\\Windows\\Fonts\\PALSCRI.TTF', # Windows
]
font = None
for font_path in font_paths:
if os.path.exists(font_path):
font = ImageFont.truetype(font_path, 45)
logger.info(f"Using font: {font_path}")
break
if font is None:
# Fall back to default font
logger.warning("No handwriting fonts found, using default font")
font = ImageFont.load_default()
except Exception as e:
logger.warning(f"Error loading font: {e}")
font = ImageFont.load_default()
# Generate signature - either use the font or draw a random curve
if random.choice([True, False]) and font != ImageFont.load_default():
# Text-based signature
text_color = (0, 0, 128, 255) # Dark blue with full opacity
# Format the name nicely
name_parts = name.split()
if len(name_parts) > 1:
# Use first initial and last name
formatted_name = f"{name_parts[0][0]}. {name_parts[-1]}"
else:
formatted_name = name
# Add some random variation to the signature
if random.choice([True, False]):
# Underline
text_width = draw.textlength(formatted_name, font=font)
y_pos = height // 2
draw.text((width//2 - text_width//2, y_pos - 30), formatted_name, fill=text_color, font=font)
# Add underline
underline_y = y_pos + 10
underline_start = width//2 - text_width//2 - 10
underline_end = width//2 + text_width//2 + 10
# Random wavy underline
for x in range(int(underline_start), int(underline_end), 2):
y = underline_y + random.randint(-2, 2)
draw.line([(x, y), (x+2, y)], fill=text_color, width=2)
else:
# Slanted text
draw.text((width//2 - 100, height//2 - 20), formatted_name, fill=text_color, font=font)
else:
# Draw a random signature-like curve
curve_color = (0, 0, 0, 255) # Black with full opacity
points = []
# Create a random starting point in the left third of the image
x = random.randint(width // 6, width // 3)
y = random.randint(height // 3, 2 * height // 3)
# Add a series of connected points moving right
points.append((x, y))
# Number of segments in the signature
num_segments = random.randint(5, 15)
for _ in range(num_segments):
# Move right with some random up/down movement
x += random.randint(10, 40)
y += random.randint(-20, 20)
# Keep y within the image
y = max(10, min(height - 10, y))
# Keep x within the image
x = min(width - 10, x)
points.append((x, y))
# Draw connected lines
for i in range(len(points) - 1):
draw.line([points[i], points[i+1]], fill=curve_color, width=random.randint(2, 4))
# Add some random loops or flourishes
if random.choice([True, False]):
# Add a loop
loop_center_x = random.randint(width // 3, 2 * width // 3)
loop_center_y = random.randint(height // 3, 2 * height // 3)
loop_width = random.randint(30, 70)
loop_height = random.randint(20, 50)
# Draw an ellipse
draw.ellipse(
[(loop_center_x - loop_width//2, loop_center_y - loop_height//2),
(loop_center_x + loop_width//2, loop_center_y + loop_height//2)],
outline=curve_color, width=2
)
# Save the image
image.save(output_path, 'PNG')
logger.info(f"Created signature image: {output_path}")
return output_path
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
name |
- | - | positional_or_keyword |
output_path |
- | - | positional_or_keyword |
width |
- | 400 | positional_or_keyword |
height |
- | 150 | positional_or_keyword |
bg_color |
- | (255, 255, 255, 0) | positional_or_keyword |
Parameter Details
name: String containing the person's name. If multiple words are provided, the function may format it as an initial and last name (e.g., 'John Doe' becomes 'J. Doe'). Required parameter.
output_path: String specifying the file path where the signature image will be saved. Must be a valid path with write permissions. The image is saved in PNG format. Required parameter.
width: Integer specifying the width of the signature image in pixels. Default is 400. Must be positive.
height: Integer specifying the height of the signature image in pixels. Default is 150. Must be positive.
bg_color: Tuple of 4 integers (RGBA) specifying the background color. Default is (255, 255, 255, 0) which creates a transparent white background. Values should be in range 0-255.
Return Value
Returns a string containing the path to the created signature image file (same as the output_path parameter). The file is saved as a PNG with RGBA color mode before returning.
Dependencies
PILosloggingrandom
Required Imports
import os
import random
from PIL import Image, ImageDraw, ImageFont
Conditional/Optional Imports
These imports are only needed under specific conditions:
import logging
Condition: Required for logger.info() and logger.warning() calls within the function
Required (conditional)Usage Example
import os
import logging
import random
from PIL import Image, ImageDraw, ImageFont
# Setup logger
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
# Create signature image
name = "John Doe"
output_path = "signature.png"
signature_path = create_signature_image(
name=name,
output_path=output_path,
width=400,
height=150,
bg_color=(255, 255, 255, 0)
)
print(f"Signature saved to: {signature_path}")
# Custom size with white background
signature_path = create_signature_image(
name="Jane Smith",
output_path="signature_custom.png",
width=600,
height=200,
bg_color=(255, 255, 255, 255)
)
Best Practices
- Ensure a logger object is configured before calling this function to avoid NameError
- Verify that the output directory exists and has write permissions before calling
- The function uses randomization, so signatures will vary between calls even with the same name
- For production use, consider adding error handling around the image.save() call
- The function attempts to find handwriting fonts on multiple platforms (Linux, Mac, Windows) but falls back to default font if none are found
- The generated signatures are synthetic and should not be used for legal or authentication purposes
- Consider setting a random seed if reproducible signatures are needed for testing
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
class SignatureGenerator 67.3% similar
-
function main_v32 61.1% similar
-
class SignatureImage 44.1% similar
-
class SignatureImage_v1 43.7% similar
-
function add_watermark 42.1% similar