zcbot/skills/ppt/references/svg-image-embedding.md

7.5 KiB

See shared-standards.md for common technical constraints.

SVG Image Embedding Guide

Technical spec and workflow for adding images to SVG files.


Image Resource List Format

Defined in the Design Specification & Content Outline; each image carries an Acquire Via field plus a status annotation. This file is authoritative for status names and SVG embedding behavior. If image approach includes "B) User-provided": run analyze_images.py right after the Eight Confirmations and complete the list before outputting the design spec.

| Filename | Dimensions | Purpose | Type | Acquire Via | Status | Reference |
|----------|------------|---------|------|-------------|--------|-----------|
| cover_bg.png | 1280x720 | Cover background | Background | ai | Pending | Modern tech abstract, deep blue gradient |
| team.jpg | 800x600 | Team photo | Photography | web | Pending | Diverse engineering team in modern office |
| product.png | 600x400 | Page 3 product photo | Photography | user | Existing | - |
| formula_001.png | 736x168 | Page 3 block equation | Latex Formula | formula | Rendered | `E = mc^2` |
| chart.png | 600x400 | Page 5 placeholder | Illustration | placeholder | Placeholder | Team collaboration scene to be added later |

Image Status Enum

Status Meaning Executor Handling
Pending Acquisition needed (Acquire Via: ai or web); not yet attempted Image Acquisition Phase (Step 5) consumes this; must not remain after Step 5
Generated AI-generated file exists at expected path Reference from ../images/; no on-slide credit needed
Sourced Web-sourced file exists at expected path Reference from ../images/; check image_sources.json for license_tier — if attribution-required, render an inline credit element on the slide (see executor-base.md §6 and image-searcher.md §7 for the visual spec)
Rendered Deterministic formula PNG exists at expected path (Acquire Via: formula) Reference from ../images/; use preserveAspectRatio="xMidYMid meet" and do not crop
Needs-Manual Acquisition attempted once + one retry, failed Dashed placeholder unless user has manually supplied the file
Existing User already has image (Acquire Via: user) Place in images/, reference with <image>
Placeholder Intentionally not prepared yet (Acquire Via: placeholder) Dashed border placeholder; replace later

Workflow

1. Strategist defines image needs → Add image resource list with Acquire Via + Status per row
2. Image Acquisition (Step 5):
   - Pending + ai  → Image_Generator runs image_gen.py     → Generated
   - Pending + web → Image_Searcher runs image_search.py   → Sourced
   - formula / user / placeholder rows are skipped
3. Executor generates SVGs (svg_output/)
   ├── Existing / Generated → <image href="../images/xxx.png" .../>
   ├── Sourced + license_tier=no-attribution → <image href=...> only
   ├── Sourced + license_tier=attribution-required → <image href=...> + small <text> credit element on the slide
   ├── Rendered formula → <image href="../images/formula_001.png" preserveAspectRatio="xMidYMid meet" .../>
   └── Placeholder / Needs-Manual without file → Dashed border + description text
4. Preview: python3 -m http.server -d <project_path> 8000 → /svg_output/<filename>.svg
5. Post-processing & Export → follow shared-standards.md §5

Keep external references in svg_output/ during generation. finalize_svg.py auto-embeds images into svg_final/; export PPTX from svg_final/.


External Reference vs Base64 Embedding

Method Pros Cons Suitable For
External reference Small file size, fast iteration, easy to replace Preview requires HTTP server from project root svg_output/ development phase
Base64 embedding Self-contained file, stable export Large file size svg_final/ delivery phase

Syntax

<image href="../images/image.png" x="0" y="0" width="1280" height="720"
       preserveAspectRatio="xMidYMid slice"/>

Key Attributes

Attribute Description Example
href Image path (relative or absolute) "../images/cover.png"
x, y Image top-left corner position x="0" y="0"
width, height Image display dimensions width="1280" height="720"
preserveAspectRatio Scaling mode "xMidYMid slice"

preserveAspectRatio Common Values

Value Effect
xMidYMid slice Center crop (similar to CSS cover)
xMidYMid meet Complete display (similar to CSS contain)
none Stretch to fill, no aspect ratio preservation

Preview Method

Browser security blocks external images on directly opened SVGs. Serve via HTTP from the project root:

python3 -m http.server -d <project_path> 8000
# Visit http://localhost:8000/svg_output/your_file.svg

Syntax

<image href="data:image/png;base64,iVBORw0KGgo..." x="0" y="0" width="1280" height="720"/>

MIME Types

MIME Type File Format
image/png PNG
image/jpeg JPG/JPEG
image/gif GIF
image/webp WebP
image/svg+xml SVG

Conversion Process

Use the unified pipeline in shared-standards.md §5. finalize_svg.py runs before export so image references in svg_output/ become embedded assets in svg_final/.

python3 scripts/finalize_svg.py <project_path>
python3 scripts/svg_to_pptx.py <project_path>

Standalone: embed_images.py (advanced)

For processing specific SVGs without the full pipeline:

python3 scripts/svg_finalize/embed_images.py <svg_file>                         # Single file
python3 scripts/svg_finalize/embed_images.py <project_path>/svg_output/*.svg    # Batch
python3 scripts/svg_finalize/embed_images.py --dry-run <project_path>/svg_output/*.svg  # Preview

Best Practices

Image Optimization

Compress before embedding to reduce file size:

convert input.png -quality 85 -resize 1920x1080\> output.png  # ImageMagick
pngquant --quality=65-80 input.png -o output.png               # pngquant (recommended)

File Organization

project/
├── images/            # Image assets
├── sources/           # Source files and their accompanying images
│   └── article_files/
├── svg_output/        # Raw version (external references)
└── svg_final/         # Final version (images embedded)

Rounded Corner / Non-rectangular Image Cropping

clipPath on <image> elements is conditionally allowed — authoritative constraints in shared-standards.md §1.2; do not restate or relax here.

Fallback when clipPath doesn't fit: bake rounded corners into the source image (PNG with alpha) before embedding.


FAQ

Q: Can't see images when opening SVG directly? Browser security blocks cross-directory requests. Serve via HTTP from project root, or run finalize_svg.py first and view from svg_final/.

Q: Base64 file too large? Compress the source, use JPEG, reduce resolution to match actual display dimensions.

Q: How to reverse-extract a Base64 image?

base64 -d image.b64 > image.png