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

188 lines
7.5 KiB
Markdown

> 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.
```markdown
| 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](./executor-base.md) and [image-searcher.md §7](./image-searcher.md) 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 |
---
## Method 1: External Reference (Recommended for Generation Phase)
### Syntax
```xml
<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:
```bash
python3 -m http.server -d <project_path> 8000
# Visit http://localhost:8000/svg_output/your_file.svg
```
---
## Method 2: Base64 Embedding (Recommended for Delivery Phase)
### Syntax
```xml
<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](shared-standards.md). `finalize_svg.py` runs before export so image references in `svg_output/` become embedded assets in `svg_final/`.
```bash
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:
```bash
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:
```bash
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](shared-standards.md); 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?**
```bash
base64 -d image.b64 > image.png
```