> See shared-standards.md for common technical constraints.

# Image Layout Specification

Layout rules for pages where the image is placed **side-by-side with body text** as a container block. Both the Strategist planning phase and Executor generation phase must follow these rules when the image's narrative intent is *side-by-side*.

**Core principle (side-by-side): Calculate container layout based on the image's original aspect ratio, ensuring the image is displayed completely without excess whitespace or cropping.**

> **Scope note.** This spec applies to the *side-by-side* image intent — the most common case for content pages. For other intents (hero / full-bleed, atmosphere / background layer, accent / inline), container ratio alignment is not a constraint; see `references/strategist.md` §h "Image narrative intent" for how to decide between them. Hero and atmosphere intents intentionally use full-bleed placement (image fills canvas, cropping is expected); the ratio→split table below does NOT apply to them.

---

## Layout Decision Flow

```
1. Decide narrative intent (hero / atmosphere / side-by-side / accent) — see strategist.md §h
2. If intent = side-by-side: continue below. Otherwise: compose per narrative; this spec does not apply.
3. Get image original dimensions → Calculate ratio (width/height)
4. Select layout type based on ratio
5. Calculate maximum display size for the image
6. Allocate remaining space for text area
7. Fill results into the Design Specification's image resource list
```

**When to execute**: If the image approach includes "B) User-provided", after the Strategist completes the Eight Confirmations and before content analysis and outlining, the scan must be run and the image resource list populated.

---

## Layout Type Selection (side-by-side intent)

| Image Ratio | Layout Type | Image Position | Description |
|-------------|-------------|----------------|-------------|
| > 2.0 (ultra-wide) | Top-bottom split | Top full-width | Image spans canvas width, height proportional |
| 1.5-2.0 (wide) | Top-bottom split | Top | Image width = content area width, height proportional |
| 1.2-1.5 (standard) | Left-right split | Left | Image height-first fit, width proportional |
| 0.8-1.2 (square) | Left-right split | Left | Image takes content area height, width proportional |
| < 0.8 (portrait) | Left-right split | Left | Image height = content area height, width proportional |

> Edge cases: When ratio is at a boundary (e.g., 1.5), decide based on text volume. More text → left-right; less text → top-bottom.

---

## Dimension Calculation Formulas

### Canvas Parameters (All Formats)

| Format | Canvas | Margins (L/R, T/B) | Content Area (W x H) | Title Height | Content Start Y |
|--------|--------|--------------------|-----------------------|-------------|----------------|
| PPT 16:9 | 1280x720 | 60, 60 | 1160 x 600 | 60px | 80px |
| PPT 4:3 | 1024x768 | 50, 50 | 924 x 608 | 60px | 70px |
| Xiaohongshu | 1242x1660 | 60, 80 | 1122 x 1500 | 80px | 100px |
| WeChat Moments | 1080x1080 | 60, 60 | 960 x 960 | 60px | 80px |
| Story | 1080x1920 | 60, 120/180 | 960 x 1620 | 80px | 140px |
| WeChat Article | 900x383 | 40, 40 | 820 x 303 | 40px | 50px |

> In the formulas below, **W** = content area width, **H** = content area height (already excludes title). The PPT 16:9 example uses W=1160, H=600.

### Top-Bottom Layout Calculation

```
Image width = W = 1160 px
Image height = W / R = 1160 / R px
Text area height = H - image height - gap(20px)

Validation: Text area height >= 150px (at least 3-4 lines of text)
If not satisfied → Switch to left-right layout
```

### Left-Right Layout Calculation

**Method 1 (height-first, suitable for portrait images)**:
```
Image height = H = 600 px
Image width = H x R = 600 x R px
Text area width = W - image width - gap(20px)
```

**Method 2 (width-constrained, for wide images converted to left-right)**:
```
Image width = W x 0.7 = 812 px
Image height = image width / R
Text area width = W - image width - gap(20px)
```

**Validation**: Text area width >= 280px; otherwise reduce image area width.

---

## Layout Examples

### Ultra-wide Image (ratio 2.45)

```
Original: 1960x800, R=2.45 → Top-bottom split
Image: 1160x473, Text area: 1160x147 → 7:3 top-bottom
```

### Standard Landscape (ratio 1.38)

```
Original: 1614x1171, R=1.38 → Left-right split
Image: 773x560 (left), Text area: 367x560 (right) → 7:3 left-right
```

### Wide Image Edge Case (ratio 1.75)

```
Original: 1820x1040, R=1.75
Try top-bottom: image height=663, text area=-43 ❌
Switch to left-right: image 780x446 (left), text area 360x600 (right) → 7:3 left-right
```

---

## Portrait Canvas Override

The default layout type selection table assumes a **landscape or square canvas**. For portrait canvases (height > width), the rules change because left-right splits make both columns too narrow.

| Canvas Orientation | Image Ratio | Recommended Layout | Reason |
|-------------------|-------------|-------------------|--------|
| Portrait (Xiaohongshu, Story) | > 1.5 (wide) | Top-bottom | Same as landscape canvas |
| Portrait (Xiaohongshu, Story) | 1.2-1.5 (standard) | Top-bottom | Left-right too narrow on tall canvas |
| Portrait (Xiaohongshu, Story) | 0.8-1.2 (square) | Top-bottom | Image fits well in top half |
| Portrait (Xiaohongshu, Story) | 0.5-0.8 (portrait) | Left-right | Portrait image on tall canvas works |
| Portrait (Xiaohongshu, Story) | < 0.5 (extreme portrait) | Left-right | Image takes one side, text the other |

> On square canvases (WeChat Moments 1:1), use the standard landscape canvas rules.

---

## Multi-Image Layout

When a slide contains multiple images, use these formulas to divide the content area evenly.

### Grid Formulas

```
columns = number of columns
rows = number of rows
gap = 20px (PPT formats) or 30px (social formats)

cell_width  = (W - (columns - 1) * gap) / columns
cell_height = (H - (rows - 1) * gap) / rows
```

### Common Patterns

| Image Count | Layout | Grid | Description |
|-------------|--------|------|-------------|
| 2 (both landscape) | Side-by-side | 2x1 | Two equal columns |
| 2 (both portrait) | Stacked | 1x2 | Two equal rows |
| 2 (mixed) | 1 large + 1 small | Custom | Landscape top (full-width), portrait right-bottom |
| 3 | 1 large + 2 small | 1+2 | Left large (50% width), right column with 2 stacked |
| 4 | Grid | 2x2 | Equal-sized cells |

### Example: 2x2 Grid on PPT 16:9

```
W=1160, H=600, gap=20
cell_width  = (1160 - 20) / 2 = 570
cell_height = (600 - 20) / 2 = 290

Image positions:
  (60, 80)   570x290    (650, 80)  570x290
  (60, 390)  570x290    (650, 390) 570x290
```

> For multi-image slides, use `preserveAspectRatio="xMidYMid meet"` on all images to maintain consistent display within cells.

---

## Prohibited Practices

| Prohibited | Correct Approach |
|-----------|-----------------|
| Fixed 50:50 or arbitrary ratios | Dynamic calculation based on image ratio |
| Forcing wide image into square container | Use top-bottom layout or increase image area width |
| Placing portrait image in narrow horizontal strip | Use left-right layout, image on left |
| Image whitespace exceeding 10% | Recalculate layout or choose alternative approach |
| Cropping key image content | Use `preserveAspectRatio="xMidYMid meet"` |
| Text area too small to read | Ensure text area >= 150px (top-bottom) or >= 280px (left-right) |

---

## SVG Image Embedding Code

### Complete Display (recommended for data charts)

```xml
<image href="../images/xxx.png"
       x="60" y="80" width="780" height="446"
       preserveAspectRatio="xMidYMid meet"/>
```

### Crop-to-Fill (backgrounds only)

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

---

## Image Resource List Template

In the Design Specification & Content Outline, the image resource list must include:

| Field | Description | Example |
|-------|-------------|---------|
| Filename | Image filename | `p12_0.png` |
| Original dimensions | Width x Height | 1524x968 |
| Ratio | Width / Height | 1.57 |
| Page | Usage page number | Page 5 |
| Type | Visual type | Background / Photography / Illustration / Diagram / Decorative |
| Layout plan | Top-bottom/Left-right + split ratio | Top-bottom 6:4 or Left-right 7:3 |
| Image area | Image display dimensions | 1160x420 or 780x446 |
| Text area | Remaining space dimensions | 1160x200 or 360x600 |

**The Type field is used by Image_Generator to select the appropriate prompt strategy.**

---

## Automation Tool

```bash
node scripts/analyze_images.cjs <project_path>/images                    # Default: PPT 16:9
node scripts/analyze_images.cjs <project_path>/images --canvas ppt43     # PPT 4:3
node scripts/analyze_images.cjs <project_path>/images --canvas xiaohongshu  # Xiaohongshu
```

The `--canvas` parameter selects the target canvas format (default `ppt169`). The tool computes layout type (top-bottom / left-right), image display area, and text area dimensions based on the formulas in this spec. Output includes a Markdown table that can be directly pasted into the image resource list.

---

## Role Responsibilities

| Role | Responsibility |
|------|---------------|
| **Strategist** | Run analyze_images.cjs, calculate layout per this spec, populate image resource list |
| **Executor** | Strictly follow the layout plan and dimensions in the image resource list when generating SVGs |
