diff --git a/pics/cover-blank.png b/pics/cover-blank.png new file mode 100644 index 0000000..4e1225d Binary files /dev/null and b/pics/cover-blank.png differ diff --git a/tools/make_cover.py b/tools/make_cover.py new file mode 100644 index 0000000..29af2f1 --- /dev/null +++ b/tools/make_cover.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +"""Finish the landing-page cover pair from the flux base image. + +Stamps the title (so the band name is spelled by us, not by a diffusion +model) and derives the risograph hover variant (two-ink duotone, offset +plates, paper grain). python3 tools/make_cover.py OUT_DIR +""" + +import os +import random +import sys + +from PIL import Image, ImageDraw, ImageEnhance, ImageFont, ImageOps + +HERE = os.path.dirname(__file__) +BASE = os.path.join(HERE, "..", "pics", "cover-blank.png") + +FONTS = [ + "/System/Library/Fonts/Supplemental/Impact.ttf", + "/System/Library/Fonts/Supplemental/Arial Black.ttf", + "/System/Library/Fonts/Helvetica.ttc", +] + + +def font(size): + for f in FONTS: + if os.path.exists(f): + try: + return ImageFont.truetype(f, size) + except OSError: + continue + return ImageFont.load_default() + + +def stamp_title(img): + d = ImageDraw.Draw(img) + w = img.width + + def line(text, y, size, fill): + f = font(size) + tw = d.textlength(text, font=f) + x = (w - tw) / 2 + # fat xerox outline: many offset passes + for dx in range(-4, 5, 2): + for dy in range(-4, 5, 2): + d.text((x + dx, y + dy), text, font=f, fill=(12, 10, 8)) + d.text((x, y), text, font=f, fill=fill) + + line("NOMEANSNO", 26, 118, (238, 232, 220)) + line("QUEST", 148, 96, (208, 40, 32)) + return img + + +def riso(img): + paper = Image.new("RGB", img.size, (240, 233, 216)) + g = ImageOps.autocontrast(img.convert("L")) + # ink plates from tone bands + dark = g.point(lambda v: 255 if v < 90 else 0) + mid = g.point(lambda v: 255 if 90 <= v < 175 else 0) + blue = Image.new("RGB", img.size, (36, 62, 168)) + red = Image.new("RGB", img.size, (222, 60, 44)) + out = paper.copy() + # misregistered plates, like a real duplicator on a deadline + out.paste(red, (3, 2), mid) + out.paste(blue, (0, 0), dark) + # grain + rng = random.Random(41) + px = out.load() + for _ in range(img.width * img.height // 14): + x = rng.randrange(img.width) + y = rng.randrange(img.height) + r, gr, b = px[x, y] + n = rng.randint(-18, 18) + px[x, y] = (max(0, min(255, r + n)), max(0, min(255, gr + n)), max(0, min(255, b + n))) + return out + + +def main(): + out_dir = sys.argv[1] if len(sys.argv) > 1 else os.path.join(HERE, "..", "covers") + os.makedirs(out_dir, exist_ok=True) + base = Image.open(BASE).convert("RGB") + base = ImageEnhance.Contrast(base).enhance(1.08) + titled = stamp_title(base.copy()) + + cover = ImageOps.fit(titled, (311, 400), Image.LANCZOS) + cover.save(os.path.join(out_dir, "nomeansnoquest.jpg"), quality=88) + + riso_img = ImageOps.fit(riso(stamp_title(base.copy())), (311, 400), Image.LANCZOS) + riso_img.save(os.path.join(out_dir, "nomeansnoquest_riso.jpg"), quality=88) + print("covers written:", out_dir) + + +if __name__ == "__main__": + main() diff --git a/tools/mb_background.py b/tools/mb_background.py index 073a348..8b8682a 100755 --- a/tools/mb_background.py +++ b/tools/mb_background.py @@ -56,7 +56,9 @@ def api(path, data=None, raw=False): def main(): name, prompt = sys.argv[1], sys.argv[2] - job = api("/api/jobs", {"operator": "flux_local", "params": {"prompt": prompt, "width": 1024, "height": 608}}) + w = int(os.environ.get("MBW", "1024")) + h = int(os.environ.get("MBH", "608")) + job = api("/api/jobs", {"operator": "flux_local", "params": {"prompt": prompt, "width": w, "height": h}}) jid = job.get("id") or job.get("job_id") print(f"submitted flux_local job {jid}") for _ in range(120):