#!/usr/bin/env python3 """ Generate on-brand photography for the Charity Right Fidya/Kaffarah page using Gemini Nano Banana Pro (Gemini 3 Pro Image Preview). Brand style reference (from Ramadan homepage): - Documentary/photojournalistic style - Warm earth tones (sandy, ochre, warm brown palette) - Natural golden hour lighting - Shallow depth of field (subject sharp, background softly blurred) - Dignified portraits of people in need (children, elderly, families) - High quality, professional look - Wide aspect ratio (~16:9) """ import os import json import base64 import sys import time from pathlib import Path # Load from .env from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("GEMINI_API_KEY") MODEL = os.getenv("GEMINI_IMAGE_MODEL", "nano-banana-pro-preview") if not API_KEY: print("ERROR: GEMINI_API_KEY not set in .env") sys.exit(1) print(f"Using model: {MODEL}") print(f"API Key: {API_KEY[:10]}...") import requests OUTPUT_DIR = Path("screenshots/fidya-kaffarah") OUTPUT_DIR.mkdir(parents=True, exist_ok=True) # Image prompts designed to match the CR brand photography style for fidya/kaffarah context PROMPTS = [ { "name": "fidya-hero", "prompt": ( "Documentary photography, wide shot. An elderly South Asian grandmother " "sitting peacefully in a modest home, warm golden hour light streaming through " "a window, she has gentle wrinkles and wise eyes, wearing a simple white cotton " "dupatta over her head. A plate of simple food (rice and lentils) sits beside her. " "Warm earth tones, shallow depth of field, photojournalistic style, " "shot on 85mm lens, natural lighting. Dignified and compassionate mood. " "16:9 aspect ratio, high resolution professional photograph." ) }, { "name": "fidya-feeding", "prompt": ( "Documentary photography. A warm scene of food being served to people in need " "at a community feeding program in rural Bangladesh. Focus on hands gently " "placing a plate of rice and curry in front of a grateful elderly person. " "Golden warm lighting, earth tones, shallow depth of field with other people " "softly blurred in background. Photojournalistic style, authentic, dignified. " "Shot on 50mm lens, natural light. 16:9 aspect ratio, professional photograph." ) }, { "name": "kaffarah-community", "prompt": ( "Documentary photography. A community meal distribution scene in a rural village. " "Several children and elderly people receiving meals from volunteers. " "The scene is outdoors with dusty earth ground and simple structures in background. " "Warm golden hour sunlight, rich earth tones (ochre, sand, brown). " "Focus on a child holding a bowl of food, looking up with hopeful eyes. " "Shallow depth of field, photojournalistic authenticity. " "Shot on 35mm lens. 16:9 aspect ratio, professional photograph." ) }, { "name": "fidya-quran-elder", "prompt": ( "Documentary photography, intimate portrait. An elderly Muslim man with a white beard " "and simple prayer cap, sitting cross-legged on the floor in a humble room, " "holding prayer beads (tasbih). Soft warm natural light from a side window " "illuminating his weathered, peaceful face. Warm earth tone palette, " "shallow depth of field, background is a simple mud-colored wall. " "Dignified, contemplative, spiritual mood. Shot on 85mm lens. " "16:9 aspect ratio, high resolution professional photograph." ) }, { "name": "fidya-child-meal", "prompt": ( "Documentary photography. A young child in South Asia or East Africa, " "around 6-8 years old, sitting at a simple wooden table eating a plate of food " "(rice and vegetables). The child has a subtle, content smile. " "Warm golden natural light, earth tones (sandy, ochre), background is softly " "blurred showing a simple classroom or community center. " "Shallow depth of field, photojournalistic style. Dignified, hopeful. " "Shot on 50mm lens. 16:9 aspect ratio, professional photograph." ) }, ] def generate_image(prompt_data): """Generate an image using Gemini Nano Banana Pro.""" name = prompt_data["name"] prompt = prompt_data["prompt"] url = f"https://generativelanguage.googleapis.com/v1beta/models/{MODEL}:generateContent?key={API_KEY}" payload = { "contents": [ { "parts": [ {"text": prompt} ] } ], "generationConfig": { "responseModalities": ["TEXT", "IMAGE"], "temperature": 1.0, } } headers = {"Content-Type": "application/json"} print(f"\n[*] Generating: {name}") print(f" Prompt: {prompt[:80]}...") try: response = requests.post(url, json=payload, headers=headers, timeout=120) if response.status_code != 200: print(f" [ERR] Error {response.status_code}: {response.text[:300]}") return None data = response.json() # Extract image from response candidates = data.get("candidates", []) if not candidates: print(f" [ERR] No candidates in response") print(f" Response: {json.dumps(data, indent=2)[:500]}") return None parts = candidates[0].get("content", {}).get("parts", []) for part in parts: if "inlineData" in part: image_data = part["inlineData"] mime_type = image_data.get("mimeType", "image/png") b64_data = image_data["data"] # Determine extension ext = "png" if "png" in mime_type else "jpg" output_path = OUTPUT_DIR / f"{name}.{ext}" # Decode and save img_bytes = base64.b64decode(b64_data) output_path.write_bytes(img_bytes) size_kb = len(img_bytes) / 1024 print(f" [OK] Saved: {output_path} ({size_kb:.0f} KB)") return str(output_path) # If we get here, no image was found print(f" [ERR] No image in response parts") for part in parts: if "text" in part: print(f" Text response: {part['text'][:200]}") return None except Exception as e: print(f" [ERR] Exception: {e}") return None def main(): print("=" * 60) print("Charity Right — Fidya/Kaffarah Photography Generator") print(f"Model: {MODEL}") print("=" * 60) results = [] for i, prompt_data in enumerate(PROMPTS): result = generate_image(prompt_data) results.append((prompt_data["name"], result)) # Small delay between requests to avoid rate limiting if i < len(PROMPTS) - 1: print(" ... Waiting 3s before next generation...") time.sleep(3) print("\n" + "=" * 60) print("RESULTS SUMMARY") print("=" * 60) for name, path in results: status = f"[OK] {path}" if path else "[FAIL] Failed" print(f" {name}: {status}") successful = sum(1 for _, p in results if p) print(f"\n {successful}/{len(results)} images generated successfully") if __name__ == "__main__": main()