Files
celery/test_pil_options.py
gilesb fc9597456f
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m28s
Add JAX typography, xector primitives, deferred effect chains, and GPU streaming
- Add JAX text rendering with font atlas, styled text placement, and typography primitives
- Add xector (element-wise/reduction) operations library and sexp effects
- Add deferred effect chain fusion for JIT-compiled effect pipelines
- Expand drawing primitives with font management, alignment, shadow, and outline
- Add interpreter support for function-style define and require
- Add GPU persistence mode and hardware decode support to streaming
- Add new sexp effects: cell_pattern, halftone, mosaic, and derived definitions
- Add path registry for asset resolution
- Add integration, primitives, and xector tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 17:41:19 +00:00

184 lines
6.6 KiB
Python

#!/usr/bin/env python3
"""
Explore PIL text options and test if we can match them.
"""
import numpy as np
from PIL import Image, ImageDraw, ImageFont
def load_font(font_name=None, font_size=32):
"""Load a font."""
candidates = [
font_name,
'/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf',
'/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf',
'/usr/share/fonts/truetype/dejavu/DejaVuSans-Oblique.ttf',
]
for path in candidates:
if path is None:
continue
try:
return ImageFont.truetype(path, font_size)
except (IOError, OSError):
continue
return ImageFont.load_default()
def test_pil_options():
"""Test various PIL text options."""
# Create a test frame
frame_size = (600, 400)
font = load_font(None, 36)
font_bold = load_font('/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', 36)
font_italic = load_font('/usr/share/fonts/truetype/dejavu/DejaVuSans-Oblique.ttf', 36)
tests = []
# Test 1: Basic text
def basic_text():
img = Image.new('RGBA', frame_size, (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
draw.text((20, 20), "Basic Text", fill=(255, 255, 255, 255), font=font)
return img, "basic"
tests.append(basic_text)
# Test 2: Stroke/outline
def stroke_text():
img = Image.new('RGBA', frame_size, (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
draw.text((20, 20), "Stroke Text", fill=(255, 255, 255, 255), font=font,
stroke_width=2, stroke_fill=(255, 0, 0, 255))
return img, "stroke"
tests.append(stroke_text)
# Test 3: Bold font
def bold_text():
img = Image.new('RGBA', frame_size, (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
draw.text((20, 20), "Bold Text", fill=(255, 255, 255, 255), font=font_bold)
return img, "bold"
tests.append(bold_text)
# Test 4: Italic font
def italic_text():
img = Image.new('RGBA', frame_size, (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
draw.text((20, 20), "Italic Text", fill=(255, 255, 255, 255), font=font_italic)
return img, "italic"
tests.append(italic_text)
# Test 5: Different anchors
def anchor_text():
img = Image.new('RGBA', frame_size, (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
# Draw crosshairs at anchor points
for x in [100, 300, 500]:
draw.line([(x-10, 50), (x+10, 50)], fill=(100, 100, 100, 255))
draw.line([(x, 40), (x, 60)], fill=(100, 100, 100, 255))
draw.text((100, 50), "Left", fill=(255, 255, 255, 255), font=font, anchor="lm")
draw.text((300, 50), "Center", fill=(255, 255, 255, 255), font=font, anchor="mm")
draw.text((500, 50), "Right", fill=(255, 255, 255, 255), font=font, anchor="rm")
return img, "anchor"
tests.append(anchor_text)
# Test 6: Multiline text
def multiline_text():
img = Image.new('RGBA', frame_size, (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
draw.multiline_text((20, 20), "Line One\nLine Two\nLine Three",
fill=(255, 255, 255, 255), font=font, spacing=10)
return img, "multiline"
tests.append(multiline_text)
# Test 7: Semi-transparent text
def alpha_text():
img = Image.new('RGBA', frame_size, (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
draw.text((20, 20), "Alpha 100%", fill=(255, 255, 255, 255), font=font)
draw.text((20, 60), "Alpha 50%", fill=(255, 255, 255, 128), font=font)
draw.text((20, 100), "Alpha 25%", fill=(255, 255, 255, 64), font=font)
return img, "alpha"
tests.append(alpha_text)
# Test 8: Colored text
def colored_text():
img = Image.new('RGBA', frame_size, (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
draw.text((20, 20), "Red", fill=(255, 0, 0, 255), font=font)
draw.text((20, 60), "Green", fill=(0, 255, 0, 255), font=font)
draw.text((20, 100), "Blue", fill=(0, 0, 255, 255), font=font)
draw.text((20, 140), "Yellow", fill=(255, 255, 0, 255), font=font)
return img, "colored"
tests.append(colored_text)
# Test 9: Large stroke
def large_stroke():
img = Image.new('RGBA', frame_size, (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
draw.text((20, 20), "Big Stroke", fill=(255, 255, 255, 255), font=font,
stroke_width=5, stroke_fill=(0, 0, 0, 255))
return img, "large_stroke"
tests.append(large_stroke)
# Test 10: Emoji (if supported)
def emoji_text():
img = Image.new('RGBA', frame_size, (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
try:
# Try to find an emoji font
emoji_font = None
emoji_paths = [
'/usr/share/fonts/truetype/noto/NotoColorEmoji.ttf',
'/usr/share/fonts/truetype/ancient-scripts/Symbola_hint.ttf',
]
for p in emoji_paths:
try:
emoji_font = ImageFont.truetype(p, 36)
break
except:
pass
if emoji_font:
draw.text((20, 20), "Hello 🎵 World 🎸", fill=(255, 255, 255, 255), font=emoji_font)
else:
draw.text((20, 20), "No emoji font found", fill=(255, 255, 255, 255), font=font)
except Exception as e:
draw.text((20, 20), f"Emoji error: {e}", fill=(255, 255, 255, 255), font=font)
return img, "emoji"
tests.append(emoji_text)
# Run all tests
print("PIL Text Options Test")
print("=" * 60)
for test_fn in tests:
img, name = test_fn()
fname = f"/tmp/pil_test_{name}.png"
img.save(fname)
print(f"Saved: {fname}")
print("\nCheck /tmp/pil_test_*.png for results")
# Print available parameters
print("\n" + "=" * 60)
print("PIL draw.text() parameters:")
print(" - xy: position tuple")
print(" - text: string to draw")
print(" - fill: color (R,G,B) or (R,G,B,A)")
print(" - font: ImageFont object")
print(" - anchor: 2-char code (la=left-ascender, mm=middle-middle, etc.)")
print(" - spacing: line spacing for multiline")
print(" - align: 'left', 'center', 'right' for multiline")
print(" - direction: 'rtl', 'ltr', 'ttb' (requires libraqm)")
print(" - features: OpenType features list")
print(" - language: language code for shaping")
print(" - stroke_width: outline width in pixels")
print(" - stroke_fill: outline color")
print(" - embedded_color: use embedded color glyphs (emoji)")
if __name__ == "__main__":
test_pil_options()