- Remove legacy_tasks.py, hybrid_state.py, render.py - Remove old task modules (analyze, execute, execute_sexp, orchestrate) - Add streaming interpreter from test repo - Add sexp_effects with primitives and video effects - Add streaming Celery task with CID-based asset resolution - Support both CID and friendly name references for assets - Add .dockerignore to prevent local clones from conflicting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
137 lines
3.6 KiB
Python
137 lines
3.6 KiB
Python
"""
|
|
Drawing Primitives Library
|
|
|
|
Draw shapes, text, and characters on images.
|
|
"""
|
|
import numpy as np
|
|
import cv2
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
|
|
# Default font (will be loaded lazily)
|
|
_default_font = None
|
|
|
|
|
|
def _get_default_font(size=16):
|
|
"""Get default font, creating if needed."""
|
|
global _default_font
|
|
if _default_font is None or _default_font.size != size:
|
|
try:
|
|
_default_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", size)
|
|
except:
|
|
_default_font = ImageFont.load_default()
|
|
return _default_font
|
|
|
|
|
|
def prim_draw_char(img, char, x, y, font_size=16, color=None):
|
|
"""Draw a single character at (x, y)."""
|
|
if color is None:
|
|
color = [255, 255, 255]
|
|
|
|
pil_img = Image.fromarray(img)
|
|
draw = ImageDraw.Draw(pil_img)
|
|
font = _get_default_font(font_size)
|
|
draw.text((x, y), char, fill=tuple(color), font=font)
|
|
return np.array(pil_img)
|
|
|
|
|
|
def prim_draw_text(img, text, x, y, font_size=16, color=None):
|
|
"""Draw text string at (x, y)."""
|
|
if color is None:
|
|
color = [255, 255, 255]
|
|
|
|
pil_img = Image.fromarray(img)
|
|
draw = ImageDraw.Draw(pil_img)
|
|
font = _get_default_font(font_size)
|
|
draw.text((x, y), text, fill=tuple(color), font=font)
|
|
return np.array(pil_img)
|
|
|
|
|
|
def prim_fill_rect(img, x, y, w, h, color=None):
|
|
"""Fill a rectangle with color."""
|
|
if color is None:
|
|
color = [255, 255, 255]
|
|
|
|
result = img.copy()
|
|
x, y, w, h = int(x), int(y), int(w), int(h)
|
|
result[y:y+h, x:x+w] = color
|
|
return result
|
|
|
|
|
|
def prim_draw_rect(img, x, y, w, h, color=None, thickness=1):
|
|
"""Draw rectangle outline."""
|
|
if color is None:
|
|
color = [255, 255, 255]
|
|
|
|
result = img.copy()
|
|
cv2.rectangle(result, (int(x), int(y)), (int(x+w), int(y+h)),
|
|
tuple(color), thickness)
|
|
return result
|
|
|
|
|
|
def prim_draw_line(img, x1, y1, x2, y2, color=None, thickness=1):
|
|
"""Draw a line from (x1, y1) to (x2, y2)."""
|
|
if color is None:
|
|
color = [255, 255, 255]
|
|
|
|
result = img.copy()
|
|
cv2.line(result, (int(x1), int(y1)), (int(x2), int(y2)),
|
|
tuple(color), thickness)
|
|
return result
|
|
|
|
|
|
def prim_draw_circle(img, cx, cy, radius, color=None, thickness=1, fill=False):
|
|
"""Draw a circle."""
|
|
if color is None:
|
|
color = [255, 255, 255]
|
|
|
|
result = img.copy()
|
|
t = -1 if fill else thickness
|
|
cv2.circle(result, (int(cx), int(cy)), int(radius), tuple(color), t)
|
|
return result
|
|
|
|
|
|
def prim_draw_ellipse(img, cx, cy, rx, ry, angle=0, color=None, thickness=1, fill=False):
|
|
"""Draw an ellipse."""
|
|
if color is None:
|
|
color = [255, 255, 255]
|
|
|
|
result = img.copy()
|
|
t = -1 if fill else thickness
|
|
cv2.ellipse(result, (int(cx), int(cy)), (int(rx), int(ry)),
|
|
angle, 0, 360, tuple(color), t)
|
|
return result
|
|
|
|
|
|
def prim_draw_polygon(img, points, color=None, thickness=1, fill=False):
|
|
"""Draw a polygon from list of [x, y] points."""
|
|
if color is None:
|
|
color = [255, 255, 255]
|
|
|
|
result = img.copy()
|
|
pts = np.array(points, dtype=np.int32).reshape((-1, 1, 2))
|
|
|
|
if fill:
|
|
cv2.fillPoly(result, [pts], tuple(color))
|
|
else:
|
|
cv2.polylines(result, [pts], True, tuple(color), thickness)
|
|
|
|
return result
|
|
|
|
|
|
PRIMITIVES = {
|
|
# Text
|
|
'draw-char': prim_draw_char,
|
|
'draw-text': prim_draw_text,
|
|
|
|
# Rectangles
|
|
'fill-rect': prim_fill_rect,
|
|
'draw-rect': prim_draw_rect,
|
|
|
|
# Lines and shapes
|
|
'draw-line': prim_draw_line,
|
|
'draw-circle': prim_draw_circle,
|
|
'draw-ellipse': prim_draw_ellipse,
|
|
'draw-polygon': prim_draw_polygon,
|
|
}
|