{"id":"ai-image-generator","name":"ai-image-generator","summary":"GeminiやGPT APIを直接使ってAI画像を生成できます。","body":"# AI Image Generator\n\nGenerate images using AI APIs (Google Gemini and OpenAI GPT). This skill teaches the prompting patterns and API mechanics for producing professional images directly from Claude Code.\n\n> **Managed alternative**: If you don't want to manage API keys, [ImageBot](https://imagebot.au) provides a managed image generation service with album templates and brand kit support.\n\n## Model Selection\n\nChoose the right model for the job:\n\n| Need | Model | Why |\n|------|-------|-----|\n| **Photorealistic scenes / stock photos** | Gemini 3.1 Flash Image | Best depth, complexity, environmental context |\n| **Final client scenes (higher detail)** | Gemini 3 Pro Image | Higher detail, better style consistency |\n| **Text on images** (posters, OG with copy, infographics) | GPT Image 2 | Text rendering actually works — including multi-script |\n| **10-variation style exploration** | GPT Image 2 | Native batch — one prompt, 10 variants sharing composition + palette |\n| **Multi-reference compositing** (product + lifestyle) | GPT Image 2 | Handles lighting, scale, perspective across references |\n| **Transparent icons / logos** | GPT Image 1.5 | Native RGBA alpha — **GPT Image 2 cannot do transparency** |\n| **Quick drafts / iteration** | Gemini 2.5 Flash Image | Free tier (~500/day) |\n\n**Rule of thumb**: any image with readable text → GPT Image 2 (unless you need transparency, then GPT 1.5). Otherwise → Gemini.\n\n### Model IDs\n\n| Model | API ID | Provider |\n|-------|--------|----------|\n| Gemini 3.1 Flash Image | `gemini-3.1-flash-image-preview` | Google AI |\n| Gemini 3 Pro Image | `gemini-3-pro-image-preview` | Google AI |\n| Gemini 2.5 Flash Image | `gemini-2.5-flash-image` | Google AI |\n| GPT Image 2 (default) | `gpt-image-2` | OpenAI |\n| GPT Image 2 (ChatGPT-parity output) | `chatgpt-image-latest` | OpenAI |\n| GPT Image 1.5 (transparency-only) | `gpt-image-1.5` | OpenAI |\n\n**Verify model IDs before use** — they change frequently:\n```bash\ncurl -s \"https://generativelanguage.googleapis.com/v1beta/models?key=$GEMINI_API_KEY\" | python3 -c \"import sys,json; [print(m['name']) for m in json.load(sys.stdin)['models'] if 'image' in m['name'].lower()]\"\n```\n\n## GPT Image 2 Specifics\n\nReleased 2026-04-22. Three capabilities that change when you'd reach for it.\n\n### 1. Text rendering actually works\n\nPosters, OG images with headlines, infographics with labels, UI mockups, pricing cards. Text is rendered reliably, including non-Latin scripts (Japanese, Korean, Hindi, Bengali). Primary reason to switch from Gemini — Gemini doesn't render readable text at all.\n\n### 2. Multi-variation batching\n\nOne prompt, up to 10 images in a single call. Variants share composition and palette but differ in detail. Good for style exploration before committing, A/B options for a client, rapid ideation.\n\n### 3. Multi-reference compositing\n\nFeed reference images alongside your prompt — product shots, lifestyle scenes, logos. The model places the product into the scene with correct lighting, scale, perspective. Enables \"product in context\" workflows without multi-turn editing.\n\n### Modes\n\n- **Instant** (default, all plans) — generates without a planning pass. Fast, good enough for most cases.\n- **Thinking** (Plus/Pro/Business plans) — plans layout before drawing. Use when element counts matter (\"3 icons in a row\", \"5 feature bullets\") or text must land in specific regions. Fewer re-rolls on complex compositions.\n\n### Aspect ratios\n\n3:1 ultra-wide through 1:3 ultra-tall, plus 1:1, 3:2, 2:3, 16:9, 9:16. Wider range than other models — useful for website banners (ultra-wide hero) or mobile story formats (ultra-tall).\n\n### Resolution\n\nUp to 2K on the long edge standard. 4K in beta.\n\n### Generation time\n\n**Up to 2 minutes on complex prompts.** Build async UX — don't block on the response. Show progress or spin off and poll.\n\n### Constraints\n\n- **No transparent backgrounds.** Fall back to `gpt-image-1.5` when you need PNG transparency.\n- **API Org Verification may be required** before the endpoint fires — enable in your OpenAI account settings if you hit auth errors on first call.\n\n### Pricing (per 1024×1024 image)\n\n| Quality | Cost |\n|---------|------|\n| Low | $0.006 |\n| Medium | $0.053 |\n| High | $0.211 |\n\nToken pricing: $5/M text in, $10/M text out, $8/M image in, $30/M image out.\n\n## The 5-Part Prompting Framework\n\nBuild prompts in this order for consistent results:\n\n### 1. Image Type\nSet the genre: \"A photorealistic photograph\", \"An isometric illustration\", \"A flat vector icon\"\n\n### 2. Subject\nWho or what, with specific details: \"of a warm, approachable Australian woman in her early 30s, smiling naturally\"\n\n### 3. Environment\nSetting and spatial relationships: \"in a bright modern home with terracotta decor on wooden shelves behind her\"\n\n### 4. Technical Specs\nCamera and lighting: \"Shot at 85mm f/2.0, natural window light, head and shoulders framing\"\n\n### 5. Constraints\nWhat to exclude: \"Photorealistic, no text, no watermarks, no logos\"\n\n### Example (Good vs Bad)\n\n```\nBAD — keyword soup:\n\"professional woman, spa, warm lighting, high quality, 4K\"\n\nGOOD — narrative direction:\n\"A professional skin treatment scene in a warm clinical setting.\nA practitioner wearing blue medical gloves uses a microneedling pen\non the client's forehead. The client lies on a white treatment bed,\neyes closed, relaxed. Warm golden-hour light from a window to the\nleft. Terracotta-toned wall visible in the background. Shot at\n85mm f/2.0, shallow depth of field. No text, no watermarks.\"\n```\n\n## Workflow\n\n### 1. Determine Image Need\n\n| Purpose | Aspect Ratio | Model |\n|---------|-------------|-------|\n| Hero banner (no text) | 16:9 or 21:9 | Gemini |\n| Hero banner with headline copy | 16:9 or 3:1 ultra-wide | GPT Image 2 |\n| Service card | 4:3 or 3:4 | Gemini |\n| Profile / avatar | 1:1 | Gemini |\n| Icon / badge (transparent) | 1:1 | GPT Image 1.5 |\n| OG / social share (no text) | 1.91:1 | Gemini |\n| OG / social share with copy | 1.91:1 | GPT Image 2 |\n| Poster / infographic / pricing card / any typography-heavy | varies | GPT Image 2 |\n| Style exploration (10 variants of one concept) | any | GPT Image 2 (batch) |\n| Instagram post | 1:1 or 4:5 | Gemini |\n| Mobile hero | 9:16 | Gemini |\n\n### 2. Build the Prompt\n\nUse the 5-part framework. Refer to `references/prompting-guide.md` for detailed photography parameters.\n\n### 3. Generate via API\n\n#### Gemini (Python — handles shell escaping correctly)\n\n```python\npython3 << 'PYEOF'\nimport json, base64, urllib.request, os, sys\n\nGEMINI_API_KEY = os.environ.get(\"GEMINI_API_KEY\")\nif not GEMINI_API_KEY:\n    print(\"Set GEMINI_API_KEY environment variable\"); sys.exit(1)\n\nmodel = \"gemini-3.1-flash-image-preview\"\nurl = f\"https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key={GEMINI_API_KEY}\"\n\nprompt = \"\"\"A professional photograph of a modern co-working space in\nNewcastle, Australia. Natural light floods through floor-to-ceiling\nwindows. Three people collaborate at a standing desk — one pointing\nat a laptop screen. Exposed brick wall, potted fiddle-leaf fig,\ncoffee cups on the desk. Shot at 35mm f/4.0, environmental portrait\nstyle. No text, no watermarks, no logos.\"\"\"\n\npayload = json.dumps({\n    \"contents\": [{\"parts\": [{\"text\": prompt}]}],\n    \"generationConfig\": {\n        \"responseModalities\": [\"TEXT\", \"IMAGE\"],\n        \"temperature\": 0.8\n    }\n}).encode()\n\nreq = urllib.request.Request(url, data=payload, headers={\n    \"Content-Type\": \"application/json\",\n    \"User-Agent\": \"ImageGen/1.0\"\n})\n\nresp = urllib.request.urlopen(req, timeout=120)\nresult = json.loads(resp.read())\n\n# Extract image from response\nfor part in result[\"candidates\"][0][\"content\"][\"parts\"]:\n    if \"inlineData\" in part:\n        img_data = base64.b64decode(part[\"inlineData\"][\"data\"])\n        output_path = \"hero-image.png\"\n        with open(output_path, \"wb\") as f:\n            f.write(img_data)\n        print(f\"Saved: {output_path} ({len(img_data):,} bytes)\")\n        break\nPYEOF\n```\n\n#### GPT Image 1.5 — Transparent Icons\n\nUse `gpt-image-1.5` specifically for the transparent PNG case. GPT Image 2 cannot do transparency.\n\n```python\npython3 << 'PYEOF'\nimport json, base64, urllib.request, os, sys\n\nOPENAI_API_KEY = os.environ.get(\"OPENAI_API_KEY\")\nif not OPENAI_API_KEY:\n    print(\"Set OPENAI_API_KEY environment variable\"); sys.exit(1)\n\nurl = \"https://api.openai.com/v1/images/generations\"\n\npayload = json.dumps({\n    \"model\": \"gpt-image-1.5\",\n    \"prompt\": \"A minimal, clean plumbing wrench icon. Flat design, single consistent stroke weight, modern style. On a transparent background.\",\n    \"n\": 1,\n    \"size\": \"1024x1024\",\n    \"background\": \"transparent\",\n    \"output_format\": \"png\"\n}).encode()\n\nreq = urllib.request.Request(url, data=payload, headers={\n    \"Content-Type\": \"application/json\",\n    \"Authorization\": f\"Bearer {OPENAI_API_KEY}\"\n})\n\nresp = urllib.request.urlopen(req, timeout=120)\nresult = json.loads(resp.read())\n\nimg_data = base64.b64decode(result[\"data\"][0][\"b64_json\"])\nwith open(\"icon-wrench.png\", \"wb\") as f:\n    f.write(img_data)\nprint(f\"Saved: icon-wrench.png ({len(img_data):,} bytes)\")\nPYEOF\n```\n\n#### GPT Image 2 — Text-heavy or Batch Variations\n\nUse `gpt-image-2` when text has to render readably, or when you want 10 variants in one call. **No transparency** — if you need transparent bg, use 1.5 above.\n\n```python\npython3 << 'PYEOF'\nimport json, base64, urllib.request, os, sys, pathlib\n\nOPENAI_API_KEY = os.environ.get(\"OPENAI_API_KEY\")\nif not OPENAI_API_KEY:\n    print(\"Set OPENAI_API_KEY environment variable\"); sys.exit(1)\n\nurl = \"https://api.openai.com/v1/images/generations\"\n\n# 10-variation batch of a pricing card with rendered text\npayload = json.dumps({\n    \"model\": \"gpt-image-2\",\n    \"prompt\": (\n        \"A modern pricing card for a web hosting plan. \"\n        \"Headline 'Starter' in bold sans-serif. \"\n        \"Price '$29/month' directly below in large type. \"\n        \"Three feature lines: 'Unlimited bandwidth', 'SSD storage', 'Free SSL'. \"\n        \"Clean flat design, soft drop shadow, deep blue accent colour. \"\n        \"White card on light grey background.\"\n    ),\n    \"n\": 10,\n    \"size\": \"1024x1024\",\n    \"quality\": \"medium\",\n    \"output_format\": \"png\"\n}).encode()\n\nreq = urllib.request.Request(url, data=payload, headers={\n    \"Content-Type\": \"application/json\",\n    \"Authorization\": f\"Bearer {OPENAI_API_KEY}\"\n})\n\n# Timeout: up to 2 min for complex prompts\nresp = urllib.request.urlopen(req, timeout=180)\nresult = json.loads(resp.read())\n\npathlib.Path(\"variations\").mkdir(exist_ok=True)\nfor i, item in enumerate(result[\"data\"], 1):\n    img_data = base64.b64decode(item[\"b64_json\"])\n    path = f\"variations/pricing-card-{i:02d}.png\"\n    with open(path, \"wb\") as f:\n        f.write(img_data)\n    print(f\"Saved: {path} ({len(img_data):,} bytes)\")\n\nprint(f\"\\nGenerated {len(result['data'])} variants. Pick the best; delete the rest.\")\nPYEOF\n```\n\n**Batch workflow**: generate 10 → review them side-by-side → pick 1-2 → optionally regenerate with tighter prompt on the winning direction. Faster than single-shot + iterate.\n\n### 4. Save and Optimise\n\nSave generated images to `.jez/artifacts/` or the user's specified path.\n\nPost-processing (optional):\n```bash\n# Convert to WebP for web use\npython3 -c \"\nfrom PIL import Image\nimg = Image.open('hero-image.png')\nimg.save('hero-image.webp', 'WEBP', quality=85)\nprint(f'WebP: {img.size[0]}x{img.size[1]}')\n\"\n\n# Trim whitespace from transparent icons\npython3 -c \"\nfrom PIL import Image\nimg = Image.open('icon.png')\ntrimmed = img.crop(img.getbbox())\ntrimmed.save('icon-trimmed.png')\n\"\n```\n\n### 5. Quality Check (Optional)\n\nSend the generated image back to a vision model for QA:\n\n```python\n# Send to Gemini Flash for critique\ncritique_prompt = \"\"\"Review this image for:\n1. AI artifacts (extra fingers, floating objects, text errors)\n2. Technical accuracy (wrong equipment, unsafe positioning)\n3. Composition issues (awkward cropping, cluttered background)\n4. Style consistency with a professional stock photo\n\nList any issues found, or say 'PASS' if the image is production-ready.\"\"\"\n```\n\nIf issues are found, append them as negative guidance to the original prompt and regenerate.\n\n## Multi-Turn Editing\n\nGemini supports editing a generated image across conversation turns. The key requirement: **preserve thought signatures** from model responses.\n\n```python\n# Turn 1: Generate base image\ncontents = [{\"role\": \"user\", \"parts\": [{\"text\": \"Scene prompt...\"}]}]\n\n# The response includes thoughtSignature on parts — preserve them ALL\n\n# Turn 2: Edit the image\ncontents = [\n    {\"role\": \"user\", \"parts\": [{\"text\": \"Original prompt\"}]},\n    {\"role\": \"model\", \"parts\": response_parts_with_signatures},  # Keep intact\n    {\"role\": \"user\", \"parts\": [{\"text\": \"Edit: change the wall colour to blue. Keep everything else exactly the same.\"}]}\n]\n```\n\n**Edit prompt pattern**: Always specify what to KEEP unchanged, not just what to change. The model treats unlisted elements as free to modify.\n\n```\nGOOD: \"Edit this image: keep the people, desk, and window unchanged.\nOnly change: wall colour from terracotta to ocean blue.\"\n\nBAD: \"Now make the wall blue.\"\n(Model may change everything else too)\n```\n\n## API Key Setup\n\n| Provider | Get key at | Env variable |\n|----------|-----------|-------------|\n| Google Gemini | [aistudio.google.com](https://aistudio.google.com/apikey) | `GEMINI_API_KEY` |\n| OpenAI | [platform.openai.com](https://platform.openai.com/api-keys) | `OPENAI_API_KEY` |\n\n```bash\nexport GEMINI_API_KEY=\"your-key-here\"\nexport OPENAI_API_KEY=\"your-key-here\"\n```\n\n## Common Mistakes\n\n| Mistake | Fix |\n|---------|-----|\n| Using curl for Gemini prompts | Use Python — shell escaping breaks on apostrophes |\n| \"Beautiful, professional, high quality\" | Use concrete specs: \"85mm f/1.8, golden hour light\" |\n| Not specifying what to exclude | Always end with \"No text, no watermarks, no logos\" |\n| Requesting transparent PNG from Gemini | Gemini cannot do transparency — use GPT Image 1.5 with `background: \"transparent\"` |\n| Requesting transparent PNG from GPT Image 2 | GPT Image 2 **cannot do transparency** — fall back to `gpt-image-1.5` for this case only |\n| Using GPT Image 1.5 for text on images | GPT Image 1.5 text rendering is unreliable — use `gpt-image-2` for any readable text |\n| Blocking a request to GPT Image 2 | Generation can take up to 2 min on complex prompts — use 180s timeout, build async UX |\n| American defaults for AU businesses | Explicitly specify \"Australian\" + local architecture, vegetation |\n| Generic data for model ID | Verify current model IDs — they change frequently |","author":"@jezweb","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/jezweb/claude-skills/tree/main/plugins/design-assets/skills/ai-image-generator","license":"MIT","category":"writing","lang":"en","tokens":3761,"stars":0,"calls30d":1,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"references/prompting-guide.md","size":4548,"sha256":"a0606b809544dacdde37d108bc7e70b07567bf5fc35a3859f8f49d7975f6af79"}],"requires":{"mcp":[],"tools":["Read","Write","Bash","Glob","Grep"]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":["aistudio.google.com","api.openai.com","generativelanguage.googleapis.com","imagebot.au","platform.openai.com"]}}