Add manual-art generator (Gemini image API, key via env var)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
eed30a2ba5
commit
074126774c
76
tools/gen_manual_art.py
Normal file
76
tools/gen_manual_art.py
Normal file
@ -0,0 +1,76 @@
|
||||
"""Generate backnforth manual illustrations via Gemini image API (nano banana)."""
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
|
||||
# key from disk, never printed
|
||||
KEY = os.environ.get("GEMINI_API_KEY")
|
||||
if not KEY:
|
||||
sys.exit('set GEMINI_API_KEY in the environment first')
|
||||
|
||||
MODELS = ['gemini-2.5-flash-image', 'gemini-2.5-flash-image-preview',
|
||||
'gemini-2.0-flash-preview-image-generation']
|
||||
|
||||
STYLE = ("Flat vector cartoon illustration in a warm, friendly picture-book style. "
|
||||
"Soft rounded shapes, thick clean outlines, muted palette of deep teal, warm coral, "
|
||||
"cream and soft mustard yellow. Cozy, calm, reassuring mood. Simple, uncluttered "
|
||||
"composition on a plain cream background. Absolutely no text, no letters, no numbers, "
|
||||
"no words anywhere in the image. Landscape orientation. ")
|
||||
|
||||
SCENES = {
|
||||
'01-cover': "A friendly therapist and a relaxed patient sitting in comfy armchairs in a cozy "
|
||||
"counselling room with a potted plant and a soft floor lamp. On a low table between "
|
||||
"them, an open laptop shows a dark screen with a single glowing green dot.",
|
||||
'02-open': "Close-up of gentle hands opening a slightly-worn laptop on a wooden table. The screen "
|
||||
"shows a simple dark page with one large round green play button and a small green dot.",
|
||||
'03-link': "One hand passing an old smartphone to another person's open hand. The phone screen "
|
||||
"glows dark with a single bright green dot. In the soft-focus background, a laptop "
|
||||
"shows the same green dot, suggesting the two screens are connected by a dotted arc.",
|
||||
'04-follow': "Side profile of a calm person's face with a serene expression, eyes looking to one "
|
||||
"side, following a small glowing green dot that trails a gentle curved motion path "
|
||||
"from the left side of the image to the right.",
|
||||
'05-adjust': "A hand with one finger adjusting a single very large horizontal slider on a dark "
|
||||
"tablet screen. At the left end of the slider sits a tiny cute cartoon turtle, at "
|
||||
"the right end a tiny cute cartoon rabbit.",
|
||||
'06-care': "A therapist leaning forward attentively with a kind expression, offering a glass of "
|
||||
"water to a patient who looks calm and relieved. The laptop on the side table is "
|
||||
"closed. Warm afternoon light through a window.",
|
||||
}
|
||||
|
||||
OUT = os.path.expanduser('~/Documents/backnforth/img/manual')
|
||||
os.makedirs(OUT, exist_ok=True)
|
||||
|
||||
|
||||
def generate(prompt):
|
||||
body = json.dumps({'contents': [{'parts': [{'text': prompt}]}]}).encode()
|
||||
last = None
|
||||
for model in MODELS:
|
||||
url = ('https://generativelanguage.googleapis.com/v1beta/models/'
|
||||
'%s:generateContent?key=%s' % (model, KEY))
|
||||
req = urllib.request.Request(url, data=body,
|
||||
headers={'Content-Type': 'application/json'})
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=120) as r:
|
||||
data = json.load(r)
|
||||
for part in data['candidates'][0]['content']['parts']:
|
||||
if 'inlineData' in part:
|
||||
return base64.b64decode(part['inlineData']['data']), model
|
||||
last = 'no image part in response from %s' % model
|
||||
except Exception as e:
|
||||
last = '%s: %s' % (model, e)
|
||||
raise RuntimeError(last)
|
||||
|
||||
|
||||
for name, scene in SCENES.items():
|
||||
path = os.path.join(OUT, name + '.png')
|
||||
if os.path.exists(path):
|
||||
print(name, 'exists, skipping')
|
||||
continue
|
||||
img, model = generate(STYLE + scene)
|
||||
open(path, 'wb').write(img)
|
||||
print('%s: %d KB via %s' % (name, len(img) // 1024, model))
|
||||
time.sleep(2)
|
||||
print('done')
|
||||
Loading…
Reference in New Issue
Block a user