返回 ppt-master
image.md
根目录 / skills / ppt-master / scripts / docs / image.md
1 # Image Tools
2
3 > **Design boundary**: keep provider credentials explicit, keep in-pipeline
4 > acquisition manifest-driven, and treat external image references as authoring
5 > inputs while delivery writes self-contained SVG previews and native PPTX
6 > media.
7
8 Image tools cover prompt-based AI generation, web image search, image inspection,
9 and Gemini watermark removal. Native formula authoring belongs to the SVG
10 pipeline, not the image pipeline.
11
12 ## Legacy standalone `latex_render.py`
13
14 This retained standalone utility renders a user-authored
15 `images/formula_manifest.json` to PNG. Neither Default nor Quick Generate calls
16 it, and new projects do not create formula manifests or formula images. The
17 supported generated-deck path authors a native formula marker in SVG and lets
18 `svg_to_pptx.py` compile its LaTeX payload to editable PowerPoint OMML.
19
20 ```bash
21 python3 scripts/latex_render.py <project_path>
22 python3 scripts/latex_render.py <project_path> --dry-run
23 ```
24
25 Use it only for an explicitly requested external raster workflow. It is not a
26 compatibility fallback for Keynote, WPS, LibreOffice, or another client.
27
28 ## `image_gen.py`
29
30 Unified image generation entry point.
31
32 This script is the **Path A** API/proxy executor for generated images. Default
33 Generate checks `design_spec.md §I / AI Image Acquisition Path` before manifest
34 mode: only `api` / `auto` permits Path A; a missing or unknown value fails
35 closed and returns to Step 4 recovery. Quick Generate has no Design Spec: use
36 the explicit active-context path when supplied, otherwise `auto` selects the
37 A → B chain defined in
38 [`image-generator.md`](../../references/image-generator.md) §7 without asking;
39 exhausted automation triggers Quick's no-AI replan rather than Offline Manual.
40 In either profile, `host-native` uses the host image tool directly and an
41 explicit `manual` choice uses the read-only Markdown sidecar.
42
43 ```bash
44 python3 scripts/image_gen.py "A modern futuristic workspace"
45 python3 scripts/image_gen.py "Abstract tech background" --aspect_ratio 16:9 --image_size 4K
46 python3 scripts/image_gen.py "Concept car" -o projects/demo/images
47 python3 scripts/image_gen.py --list-backends
48 ```
49
50 Backends are grouped into Core / Extended / Experimental tiers. Run `python3 scripts/image_gen.py --list-backends` for the current list.
51
52 Backend selection:
53
54 ```bash
55 python3 scripts/image_gen.py "A cat" --backend openai
56 python3 scripts/image_gen.py "A cinematic portrait" --backend minimax
57 python3 scripts/image_gen.py "A product launch hero image" --backend qwen
58 python3 scripts/image_gen.py "科技感背景图" --backend zhipu
59 python3 scripts/image_gen.py "A product KV in cinematic style" --backend volcengine
60 ```
61
62 Configuration sources:
63
64 1. Current process environment variables
65 2. First `.env` found in this order:
66 - Current working directory
67 - Skill directory (e.g. `~/.agents/skills/ppt-master/.env`)
68 - Clone repo root
69 - `~/.ppt-master/.env`
70
71 The active backend must always be selected explicitly via `IMAGE_BACKEND`.
72
73 Example `.env`:
74
75 ```env
76 IMAGE_BACKEND=openai
77 OPENAI_API_KEY=sk-xxx
78 OPENAI_MODEL=gpt-image-2
79 # Optional proxy
80 # OPENAI_BASE_URL=http://127.0.0.1:3000/v1
81 # OpenAI-compatible provider knobs:
82 # OPENAI_SIZE_PRESET=auto
83 # OPENAI_RESPONSE_FORMAT=auto
84 # OPENAI_QUALITY=auto
85 # Allowed values: png / jpeg / webp
86 # OPENAI_OUTPUT_FORMAT=png
87 # jpeg/webp only, 0-100
88 # OPENAI_OUTPUT_COMPRESSION=80
89 # gpt-image-2: auto / opaque
90 # OPENAI_BACKGROUND=auto
91 # auto / low
92 # OPENAI_MODERATION=auto
93 ```
94
95 Example process environment:
96
97 ```bash
98 export IMAGE_BACKEND=openai
99 export OPENAI_API_KEY=sk-xxx
100 export OPENAI_MODEL=gpt-image-2
101 export OPENAI_OUTPUT_FORMAT=png
102 ```
103
104 Current process environment wins over `.env`.
105
106 OpenAI backend notes:
107 - `gpt-image-2` is the default OpenAI model.
108 - Requests are sent with plain `requests.post()` to improve compatibility with
109 OpenAI-compatible proxies that block the OpenAI SDK's `httpx` transport.
110 - For `gpt-image-2`, `image_size=512px` means a low-quality draft preset, not a literal 512px edge. The model requires both edges to be multiples of 16px, a long:short ratio no greater than 3:1, and total pixels between 655,360 and 8,294,400.
111 - `OPENAI_BACKGROUND=transparent` is not supported by `gpt-image-2`; use `auto` or `opaque`.
112 - If `OPENAI_OUTPUT_FORMAT=jpeg` or `webp`, generated files use `.jpg` or `.webp` extensions instead of `.png`.
113 - OpenAI-compatible providers that reject OpenAI-specific fields can use `OPENAI_RESPONSE_FORMAT=omit`, `OPENAI_QUALITY=omit`, and `OPENAI_SIZE_PRESET=<preset>`. Valid response formats are `auto`, `b64_json`, `url`, and `omit`; valid size presets are `auto`, `legacy`, `gpt-image`, `gpt-image-2`, and `dall-e-2`.
114
115 Example `.env` for Agnes AI through the OpenAI-compatible backend:
116
117 ```env
118 IMAGE_BACKEND=openai
119 OPENAI_API_KEY=your-agnes-key
120 OPENAI_MODEL=agnes-image-2.1-flash
121 OPENAI_BASE_URL=https://apihub.agnes-ai.com/v1
122 OPENAI_SIZE_PRESET=gpt-image-2
123 OPENAI_RESPONSE_FORMAT=omit
124 OPENAI_QUALITY=omit
125 ```
126
127 Use provider-specific keys only (e.g. `GEMINI_API_KEY`, `OPENAI_API_KEY`). See `.env.example` in clone mode or `${SKILL_DIR}/.env.example` in skill-install mode for the full list per backend.
128
129 `IMAGE_API_KEY`, `IMAGE_MODEL`, and `IMAGE_BASE_URL` are intentionally unsupported.
130
131 If you keep multiple providers in one `.env` or environment, `IMAGE_BACKEND` must explicitly select the active provider.
132
133 Recommendation:
134 - Default to the Core tier for routine PPT work
135 - Use Extended only when you need a specific model style
136 - Treat Experimental backends as opt-in
137
138 Example `.env` for MiniMax image backend:
139
140 ```env
141 IMAGE_BACKEND=minimax
142 MINIMAX_API_KEY=your-api-key
143 # Optional: override base URL (defaults to https://api.minimaxi.com, domestic China endpoint)
144 # Use https://api.minimax.io for overseas access
145 # MINIMAX_BASE_URL=https://api.minimax.io
146 # MINIMAX_MODEL=image-01
147 ```
148
149 ## `image_treat.py`
150
151 Create a non-destructive PNG derivative from one bitmap already prepared under
152 `<project_path>/images/`. Use this only when a slide needs a baked bitmap effect;
153 crop, mask, rotation, mirror, opacity, shadow, scrim, outline, and overlap remain
154 native SVG/PPT treatments. This tool does not perform semantic background
155 removal: use `slice_images.py --alpha --bg <key> --strict-alpha` for flat-color
156 keys (a pure red/green/blue key also recovers soft alpha and removes spill), an
157 already prepared RGBA asset or the active host image editor for a standalone cutout, and
158 [`image-generator.md`](../../references/image-generator.md) §4.4 only for
159 registered subject/base layers.
160
161 ```bash
162 python3 scripts/image_treat.py projects/demo hero.jpg \
163 --output hero_soft.png --brightness 0.9 --contrast 1.1 --blur 12
164
165 python3 scripts/image_treat.py projects/demo hero.jpg \
166 --output hero_duotone.png --duotone "#14213D" "#FCA311"
167 ```
168
169 Supported operations are brightness, contrast, desaturation/grayscale,
170 duotone, and Gaussian blur. They compose in a fixed order: brightness →
171 contrast → tone treatment → blur. Desaturation, grayscale, and duotone are
172 mutually exclusive. At least one option must produce a real change; animated
173 or multi-frame sources are rejected rather than reduced to one frame.
174
175 Both input and output are bare filenames directly under `images/`; output must
176 be a new `.png` file. The tool keeps the EXIF-corrected display dimensions,
177 leaves any alpha mask unchanged, and never overwrites the source or an existing
178 derivative. If `images/image_sources.json` contains the source filename, the
179 new record inherits that legal provenance and records `derived_from` plus the
180 ordered `treatments`. Run `analyze_images.py` after all planned derivatives are
181 ready so the inventory reflects the files that SVG authoring will consume.
182
183 ## `analyze_images.py`
184
185 Analyze objective image-file facts in a project directory before writing the
186 design spec or authoring SVG.
187
188 ```bash
189 python3 scripts/analyze_images.py <project_path>/images
190 ```
191
192 The tool does not resolve a canvas or recommend a left/right, top/bottom, or
193 other slide layout. Its atomic CSV records EXIF-corrected native dimensions and
194 `AspectRatio`, the objective aspect-ratio category, optional source
195 `SourceDisplayRatio`, format, actual transparent-pixel presence, usage count,
196 and bitmap/vector capability facts. An empty folder rewrites a header-only
197 report; unreadable supported files still refresh the report and produce a
198 non-zero exit.
199
200 Use this as the default factual inventory; it does not perform semantic image
201 understanding or choose composition. Generate planning follows the Strategist's
202 context-first boundary: source context, captions / alt text / titles, filenames,
203 user notes, and existing resource records come first. Only an already-selected
204 provided/web asset whose focal-safe crop, overlay contrast, or quiet region
205 remains materially ambiguous may be inspected for that placement; this never
206 reopens selection or provenance, never bulk-opens the image folder, and never
207 restores routine readback of AI-generated images.
208
209 ## `image_search.py`
210
211 Zero-config web image search across openly-licensed providers. Sister tool to `image_gen.py` — used when the resource list row has `Acquire Via: web`.
212
213 ```bash
214 python3 scripts/image_search.py "offshore wind farm" \
215 --filename cover_bg.jpg --slide 01_cover \
216 --orientation landscape -o projects/demo/images
217 ```
218
219 For multiple web rows, `--batch images/image_queries.json` searches them concurrently (modest default, `--concurrency N` / `IMAGE_SEARCH_CONCURRENCY` to tune) instead of one call per row — the web sister of `image_gen.py --manifest`. Schema and status semantics: [`image-searcher.md`](../../references/image-searcher.md) §5.
220
221 Providers (Pexels / Pixabay are tried first when keyed; Openverse and Wikimedia are zero-config fallbacks):
222
223 | Provider | Config | Strength |
224 |---|---|---|
225 | `pexels` | recommended: `PEXELS_API_KEY` | modern stock photography, people, workplace, lifestyle |
226 | `pixabay` | recommended: `PIXABAY_API_KEY` | broad type coverage including photos and illustrations |
227 | `openverse` | zero-config | fallback aggregator: Wikimedia + Flickr + museums + rawpixel |
228 | `wikimedia` | zero-config | educational, scientific, geographic, historical |
229
230 Default search chain (when `--provider` is unset): configured Pexels, configured Pixabay, Openverse, then Wikimedia. Missing keyed credentials are silently skipped. Keyed providers broaden stock-photo coverage but are optional; zero-config providers remain valid.
231
232 `image_search.py` uses the same `.env` lookup order as `image_gen.py`, so skill installs can keep `PEXELS_API_KEY` / `PIXABAY_API_KEY` in `~/.ppt-master/.env`.
233
234 Query guidance:
235
236 Keep the Design Spec §VIII `Reference` as the full visual/crop intent; write a separate concise provider query for this CLI. Start with the shortest phrase that preserves identity, but retain exact multi-word names and necessary disambiguators beyond four words.
237
238 For exact entities with multiple common names, add repeatable `--query-variant`
239 values (batch: `query_variants`) for materially different official
240 translations, spellings, aliases, or Chinese names. Results are aggregated and
241 deduplicated before ranking.
242
243 | Case | Pattern |
244 |---|---|
245 | Generic stock concept | `boardroom meeting` |
246 | China-specific landmark | Precise official place/identity name plus necessary geography |
247 | Avoid | Negative prompt wording such as `not tourist snapshot` |
248
249 License filter:
250
251 - **Default**: search all providers with `cc0,pdm,pexels,pixabay,cc by,cc by-sa` allowed together. The chosen image may be `no-attribution` or `attribution-required`; Executor adds an inline credit only when needed.
252 - `--strict-no-attribution` restricts the search to `cc0,pdm,pexels,pixabay` — useful for full-bleed hero images or templates that cannot host a credit element.
253
254 Pin a provider, refuse attribution, or override the manifest path:
255
256 ```bash
257 # Pin Wikimedia
258 python3 scripts/image_search.py "Olympics opening ceremony" \
259 --filename event.jpg --provider wikimedia \
260 --orientation landscape -o projects/demo/images
261
262 # Strict mode — refuse CC BY / CC BY-SA
263 python3 scripts/image_search.py "abstract gradient" \
264 --filename hero.jpg --strict-no-attribution \
265 -o projects/demo/images
266 ```
267
268 Suitability & manual replacement (a web top hit is metadata-relevant, not guaranteed visually right):
269
270 - By default only the best match is downloaded, plus a downscaled review copy at `images/.review/<stem>.jpg` (the placed asset stays full-resolution).
271 - For exact subjects (landmarks, people, companies, products), use `--require-terms` or batch `required_terms` so visually plausible but wrong metadata is rejected before ranking. Example: `--require-terms Chongqing --require-terms "Jiefangbei|Liberation Monument"`. Keep proper-name / geography anchors; do not broaden to generic terms like `canyon`, `stone pillar`, or `ancient town` just to improve coverage.
272 - When the current Generate agent can inspect images, use `--save-candidates`. The tool saves only the first ranked page of review-eligible provider previews (**8 by default**), writes `candidates/<stem>/review_sheet.jpg`, and leaves the target image and `image_sources.json` untouched. Standalone CLI use remains best-only unless this flag is explicit.
273 - Compare the thumbnail set against the active Reference/Crop Policy. Only after one passes, run `--promote candidate_03.jpg --filename <name>.jpg`; this downloads and validates exactly that original. In batch mode, pass the same `--batch images/image_queries.json` so `Needs-Selection` becomes `Sourced`.
274 - If no thumbnail passes and `has_more_candidates` is true, fetch `--candidate-page 2` (or set the batch row's `candidate_page` to `next_candidate_page` and reset it to `Pending`). Candidate numbering continues at 9; no original is downloaded. Only after the pool is exhausted should you materially change the identity wording, viewpoint, translation, alias, or disambiguator and generate a fresh pool.
275 - Without multimodal inspection, omit `--save-candidates`. Best-only mode rejects visual-verification-required near matches, accepts only a strict metadata candidate, downloads one original, and records `selection_method: metadata-ranked`; if metadata cannot prove the entity or the active visual requirement, use `Needs-Manual` rather than claiming visual confirmation.
276 - `--from-url <url> --filename <name>.jpg` downloads a user-chosen image URL and replaces the target (recorded `license_tier: manual`) — the model-agnostic manual path; works even without a multimodal model.
277
278 Full review / escalation flow: [`image-searcher.md`](../../references/image-searcher.md) §5.
279
280 Output:
281
282 - `--save-candidates`: thumbnail-only `candidates/<stem>/candidates.json`, at most 8 provider previews by default, and `review_sheet.jpg`; no target image or provenance entry. `--candidate-page N` advances through the ranked pool; `--max-candidates 0` explicitly dumps all candidates for exceptional debugging
283 - Best-only / `--promote`: one original saved to the specified output directory (auto-converts webp → jpg via Pillow when the filename extension demands)
284 - Best-only / `--promote`: `image_sources.json` manifest with full provenance (provider, license, license_tier, author, source URL, dimensions, attribution_text)
285 - Manifest is idempotent on `filename` and written atomically; damaged existing provenance blocks replacement
286
287 Allowed licenses (default): CC0, Public Domain, Pexels License, Pixabay Content License, CC BY, CC BY-SA. Auto-rejected: CC BY-NC, CC BY-ND, CC BY-NC-SA, CC BY-NC-ND, all rights reserved, unknown.
288
289 The full role-level reference (intent → query translation, on-slide attribution contract) is in [`references/image-searcher.md`](../../references/image-searcher.md).
290
291 ## `gemini_watermark_remover.py`
292
293 Remove Gemini watermark assets after manual download.
294
295 ```bash
296 python3 scripts/gemini_watermark_remover.py <image_path>
297 python3 scripts/gemini_watermark_remover.py <image_path> -o output_path.png
298 python3 scripts/gemini_watermark_remover.py <image_path> -q
299 ```
300
301 Notes:
302 - Requires `scripts/assets/bg_48.png` and `scripts/assets/bg_96.png`
303 - Best used after downloading “full size” Gemini images
304
305 Dependencies:
306
307 ```bash
308 pip install Pillow numpy
309 ```
310
310 lines MARKDOWN