SVG Generation from Text Prompts with AI
SVG generation from text prompts is a must-have for designers. Raster images like PNGs are out; scalable vector paths are in. This guide shows you how to go straight from text prompt to clean, optimized SVG.
Two Approaches
Approach 1: Raster-to-Vector Pipeline Generate the image first, then vectorize it using a tracer. Simple and reliable, works with any image generator.
Approach 2: Direct SVG Generation Use methods like DiffVG or SVGCraft to generate SVG paths directly from text prompts. Higher quality but more setup required.
We'll cover both.
Setup
pip install diffusers transformers torch Pillow cairosvg svgwrite vtracer
Approach 1: Raster → Vector Pipeline
Step 1: Generate the Raster Image
import torch
from diffusers import StableDiffusionPipeline
from PIL import Image
def generate_raster(prompt: str, model_id: str = "runwayml/stable-diffusion-v1-5", steps: int = 30) -> Image.Image:
pipe = StableDiffusionPipeline.from_pretrained(model_id)
pipe.enable_attention_slicing()
image = pipe(
prompt=f"{prompt}, flat design, clean lines",
num_inference_steps=steps
).images[0]
return image
img = generate_raster("a mountain peak with sun rays")
img.save("mountain_logo.png")
Step 2: Preprocess for Vectorization
from PIL import ImageFilter, ImageEnhance
import numpy as np
def preprocess_for_vectorization(image: Image.Image) -> Image.Image:
img = image.convert("RGB")
# Remove background noise
arr = np.array(img)
mask = np.all(arr > 240, axis=2)
arr[mask] = [255, 255, 255]
img = Image.fromarray(arr)
# Posterize to reduce color regions
img = img.convert("P", palette=Image.ADAPTIVE, colors=6)
img = img.convert("RGB")
return img
clean_img = preprocess_for_vectorization(img)
clean_img.save("mountain_logo_clean.png")
Step 3: Vectorize to SVG
import subprocess
import vtracer
def vectorize_to_svg(input_path: str, output_path: str) -> None:
vtracer.convert_image_to_svg_py(
input_path,
output_path,
colormode="color",
hierarchical="stacked"
)
svg = vectorize_to_svg("mountain_logo_clean.png", "mountain_logo.svg")
Approach 2: Direct SVG Path Generation
For icons, use a local LLM to describe the shapes and render them directly.
import svgwrite
import json
import requests
def generate_svg_with_llm(prompt: str) -> str:
system = f"Output ONLY a JSON array of SVG shapes. 3-8 shapes only."
try:
resp = requests.post(
"http://localhost:11434/api/generate",
json={"model": "llama3.2:3b", "prompt": prompt, "system": system}
)
raw = resp.json()["response"]
start = raw.find("[")
end = raw.rfind("]") + 1
shapes = json.loads(raw[start:end])
except Exception:
# Fallback: simple geometric shapes for common prompts
shapes = [
{"type": "circle", "cx": 100, "cy": 100, "r": 60},
{"type": "rect", "x": 60, "y": 60, "width": 80, "height": 80}
]
dwg = svgwrite.Drawing(size=(200, 200))
for shape in shapes:
if shape["type"] == "circle":
dwg.add(dwg.circle(center=(shape["cx"], shape["cy"]), r=shape["r"]))
elif shape["type"] == "rect":
dwg.add(dwg.rect(insert=(shape["x"], shape["y"]),
size=(shape["width"], shape["height"])))
return dwg.tostring()
svg_content = generate_svg_with_llm("a simple wifi signal icon")
with open("wifi_icon.svg", "w") as f:
f.write(svg_content)
Post-Processing: Clean SVG Optimization
def optimize_svg(input_path: str, output_path: str) -> None:
result = subprocess.run(
["svgo", "--input", input_path, "--output", output_path],
capture_output=True, text=True
)
before = os.path.getsize(input_path)
after = os.path.getsize(output_path)
reduction = (1 - after/before) * 100
print(f"Optimized: {before:,} → {after:,} bytes ({reduction:.1f}% reduction)")
optimize_svg("compass.svg", "compass_optimized.svg")
Quality Tips
- More reduction colors = fewer SVG paths (simpler output)
filter_speckle=8removes small islands- White background prevents bleeding into shapes
- For logos, use 2–4 colors at the raster stage for cleaner vector result
Need all this in one place? Check out my full Vector Workspace.



