- Shorten quote 03 from 'Can I split it across a few months?' to 'Can I pay monthly?' for column symmetry - Add nbsp between 'money' and 'arriving' to prevent orphan line break
145 lines
6.9 KiB
Python
145 lines
6.9 KiB
Python
"""
|
|
Generate 3 on-brand kaffarah-community.jpg replacements.
|
|
Uses anti-AI prompting strategy from cr-brand-style.json.
|
|
"""
|
|
import sys, io, os, time, json
|
|
sys.stdout.reconfigure(encoding='utf-8')
|
|
|
|
from google import genai
|
|
from google.genai import types
|
|
from PIL import Image
|
|
|
|
API_KEY = "AIzaSyCHnesXLjPw-UgeZaQotut66bgjFdvy12E"
|
|
MODEL = "gemini-3-pro-image-preview"
|
|
OUT = "screenshots/kaffarah-replacements"
|
|
os.makedirs(OUT, exist_ok=True)
|
|
|
|
client = genai.Client(api_key=API_KEY)
|
|
|
|
# ── ANTI-AI STYLE BLOCK ──
|
|
# No camera names, no "golden hour", no emotion words, no "bokeh".
|
|
# Describe PHYSICS of light, SPECIFIC objects, ACTIONS not feelings.
|
|
|
|
STYLE = (
|
|
"Raw documentary photograph with visible film grain and slight color noise in the shadows. "
|
|
"The color is MUTED — pulled-back saturation, faded dusty quality, blacks slightly lifted, "
|
|
"NOT warm amber or orange-tinted. Highlights have a faint yellow-green cast. "
|
|
"Shadows lean cool and neutral. "
|
|
"Single hard directional light source creating deep shadows on one side. "
|
|
"Unlit areas stay DARK, not filled in. "
|
|
"The framing is IMPERFECT — a partial figure or object intrudes at one edge of the frame. "
|
|
"The subject is slightly off-center. There is foreground obstruction. "
|
|
"Skin has visible pores, uneven tone, slight dust. Hair is uncombed. "
|
|
"Clothing is thin worn cotton, faded, creased, with visible stitching. "
|
|
"The environment is CLUTTERED with real objects at multiple depth planes. "
|
|
"NO smooth skin. NO perfect composition. NO warm glow. NO clean backgrounds. "
|
|
"Aspect ratio: exactly 2:1 wide landscape. "
|
|
)
|
|
|
|
PROMPTS = {
|
|
"kaffarah-v1.jpg": (
|
|
STYLE +
|
|
"Three children sit on a swept-dirt floor against a crumbling plastered wall eating from "
|
|
"shared metal thali plates. A boy around 8 is mid-chew, mouth slightly open, looking "
|
|
"sideways at something outside the frame. His faded blue cotton kurta has a torn collar. "
|
|
"Next to him a younger girl scoops rice with her right hand, not looking up. Her hair is "
|
|
"tangled and hasn't been brushed. Behind them, a wooden charpai with sagging rope webbing, "
|
|
"a plastic water jug, and a torn calendar hanging crooked on the wall. Afternoon sun comes "
|
|
"through a doorway on the left, casting a hard beam across the floor — the far wall stays "
|
|
"in deep shadow. Someone's bare foot and ankle are visible at the bottom-right edge of the "
|
|
"frame, cropped off. Dust motes visible in the light beam. The floor has a cracked cement "
|
|
"patch and a worn woven mat. Muted desaturated color with visible grain."
|
|
),
|
|
|
|
"kaffarah-v2.jpg": (
|
|
STYLE +
|
|
"A boy around 6 sits at a rough wooden bench eating rice and dal from a dented steel plate. "
|
|
"His hand is in the food, fingers pressing rice together. He is looking down at his plate, "
|
|
"not at the camera. His dark hair sticks up on one side where he slept on it. He wears a "
|
|
"faded brown cotton shirt buttoned wrong — one side hangs lower than the other. His "
|
|
"fingernails have dirt under them. The bench has deep scratches and a water ring stain. "
|
|
"Behind him, a plastered wall with a long crack running diagonally, a nail with nothing "
|
|
"on it, and a small high window letting in a hard shaft of light from the right. Two "
|
|
"other children are visible in the mid-ground, slightly out of focus, also eating. "
|
|
"An adult's elbow and forearm in a grey cotton sleeve intrudes into the left edge of "
|
|
"frame. On the bench next to the boy: a scratched steel cup with water. The light "
|
|
"illuminates only the right side of his face. The left side falls into shadow. "
|
|
"Muted color, visible grain, slight chromatic aberration at contrast edges."
|
|
),
|
|
|
|
"kaffarah-v3.jpg": (
|
|
STYLE +
|
|
"Seen from slightly behind and to the side of a woman in a faded cream dupatta who is "
|
|
"setting down a metal plate of food in front of a small child seated on a woven mat. "
|
|
"We see the woman's hands and forearms — veins visible, a thin glass bangle on one wrist. "
|
|
"The child, about 5, reaches for the plate with both small hands. The child's face is in "
|
|
"three-quarter profile, slightly blurred because the focus is on the hands and the plate. "
|
|
"The food is simple — a mound of rice, yellow dal, a piece of flatbread folded on the side. "
|
|
"The mat has fraying edges and a cigarette burn mark. Against the wall behind them: a "
|
|
"stacked row of steel plates, a plastic bag hanging on a nail, peeling turquoise paint "
|
|
"revealing brown plaster underneath. Hard afternoon light from a window on the right. "
|
|
"Another child sits further back, eating, almost lost in the dim background. A power "
|
|
"cable runs along the top of the wall. Muted, slightly desaturated, dusty color. "
|
|
"Fine grain throughout. This is a REAL moment, not posed."
|
|
),
|
|
}
|
|
|
|
|
|
def generate_and_save(filename, prompt, max_retries=3):
|
|
for attempt in range(max_retries):
|
|
try:
|
|
t0 = time.time()
|
|
print(f" [{attempt+1}/{max_retries}] {filename}...")
|
|
|
|
resp = client.models.generate_content(
|
|
model=MODEL,
|
|
contents=prompt,
|
|
config=types.GenerateContentConfig(
|
|
response_modalities=["IMAGE", "TEXT"],
|
|
temperature=1.0,
|
|
),
|
|
)
|
|
|
|
for part in resp.candidates[0].content.parts:
|
|
if part.inline_data and part.inline_data.mime_type.startswith("image/"):
|
|
img = Image.open(io.BytesIO(part.inline_data.data))
|
|
if img.mode != "RGB":
|
|
img = img.convert("RGB")
|
|
|
|
path = os.path.join(OUT, filename)
|
|
|
|
# Compress to stay under 2 MB
|
|
for q in [88, 82, 75, 65]:
|
|
img.save(path, "JPEG", quality=q, optimize=True, progressive=True)
|
|
if os.path.getsize(path) < 2_000_000:
|
|
break
|
|
|
|
sz = os.path.getsize(path)
|
|
print(f" [OK] {filename} -- {img.width}x{img.height}, {sz//1024} KB, {time.time()-t0:.1f}s")
|
|
return True
|
|
|
|
print(f" [WARN] no image in response")
|
|
|
|
except Exception as e:
|
|
print(f" [ERR] {str(e)[:200]}")
|
|
if attempt < max_retries - 1:
|
|
time.sleep(5 * (attempt + 1))
|
|
|
|
print(f" [FAIL] {filename}")
|
|
return False
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print(f"Generating {len(PROMPTS)} kaffarah replacements -> {os.path.abspath(OUT)}\n")
|
|
|
|
ok = 0
|
|
for fn, prompt in PROMPTS.items():
|
|
if generate_and_save(fn, prompt):
|
|
ok += 1
|
|
time.sleep(2)
|
|
|
|
print(f"\nDone: {ok}/{len(PROMPTS)}")
|
|
for f in sorted(os.listdir(OUT)):
|
|
sz = os.path.getsize(os.path.join(OUT, f))
|
|
print(f" {f} -- {sz//1024} KB")
|