Memory-Quilt / scripts /generate_p5_assets.py
Abhishek
Fix HF_TOKEN injection during docker build by using BuildKit secrets mount
5394bd3
Raw
History Blame Contribute Delete
8.68 kB
from __future__ import annotations
from pathlib import Path
import json
import struct
import zlib
root = (Path(__file__).resolve().parent.parent / 'data' / 'demo_packs' / 'p5_memory_quilt')
photos_dir = root / 'photos'
photos_dir.mkdir(parents=True, exist_ok=True)
def png_chunk(tag: bytes, data: bytes) -> bytes:
return struct.pack('!I', len(data)) + tag + data + struct.pack('!I', zlib.crc32(tag + data) & 0xFFFFFFFF)
def write_png(path: Path, width: int, height: int, pixels):
raw = bytearray()
for y in range(height):
raw.append(0)
for x in range(width):
r, g, b, a = pixels[y * width + x]
raw.extend((r, g, b, a))
compressed = zlib.compress(bytes(raw), level=9)
header = b'\x89PNG\r\n\x1a\n'
ihdr = struct.pack('!IIBBBBB', width, height, 8, 6, 0, 0, 0)
path.write_bytes(header + png_chunk(b'IHDR', ihdr) + png_chunk(b'IDAT', compressed) + png_chunk(b'IEND', b''))
def lerp(a: int, b: int, t: float) -> int:
return int(round(a * (1 - t) + b * t))
def palette_interp(c1, c2, t):
return tuple(lerp(c1[i], c2[i], t) for i in range(3))
def draw_rect(pixels, w, h, x0, y0, x1, y1, color):
for y in range(max(0, y0), min(h, y1)):
row = y * w
for x in range(max(0, x0), min(w, x1)):
pixels[row + x] = (*color, 255)
def draw_circle(pixels, w, h, cx, cy, r, color):
r2 = r * r
for y in range(max(0, cy - r), min(h, cy + r + 1)):
row = y * w
dy2 = (y - cy) ** 2
for x in range(max(0, cx - r), min(w, cx + r + 1)):
if (x - cx) ** 2 + dy2 <= r2:
pixels[row + x] = (*color, 255)
def draw_line(pixels, w, h, x0, y0, x1, y1, color, thickness=1):
dx = abs(x1 - x0)
dy = -abs(y1 - y0)
sx = 1 if x0 < x1 else -1
sy = 1 if y0 < y1 else -1
err = dx + dy
x, y = x0, y0
while True:
for ty in range(-thickness // 2, thickness // 2 + 1):
for tx in range(-thickness // 2, thickness // 2 + 1):
xx, yy = x + tx, y + ty
if 0 <= xx < w and 0 <= yy < h:
pixels[yy * w + xx] = (*color, 255)
if x == x1 and y == y1:
break
e2 = 2 * err
if e2 >= dy:
err += dy
x += sx
if e2 <= dx:
err += dx
y += sy
def make_image(name, background, accent, soft, motif):
w = h = 256
pixels = []
for y in range(h):
t = y / (h - 1)
row_color = palette_interp(background, soft, t * 0.35)
pixels.extend([(*row_color, 255)] * w)
draw_rect(pixels, w, h, 0, 0, 128, 128, tuple(min(255, c + 16) for c in soft))
draw_rect(pixels, w, h, 128, 0, 256, 128, accent)
draw_rect(pixels, w, h, 0, 128, 128, 256, tuple(max(0, c - 12) for c in background))
draw_rect(pixels, w, h, 128, 128, 256, 256, tuple(max(0, c - 4) for c in soft))
if motif == 'house':
draw_line(pixels, w, h, 64, 122, 128, 62, (248, 240, 226), 4)
draw_line(pixels, w, h, 128, 62, 192, 122, (248, 240, 226), 4)
draw_rect(pixels, w, h, 88, 122, 168, 192, tuple(min(255, c + 24) for c in soft))
draw_rect(pixels, w, h, 108, 146, 148, 192, (250, 245, 238))
draw_rect(pixels, w, h, 74, 136, 96, 164, (250, 245, 238))
draw_rect(pixels, w, h, 160, 136, 182, 164, (250, 245, 238))
elif motif == 'cart':
draw_rect(pixels, w, h, 60, 144, 196, 170, (92, 64, 48))
draw_rect(pixels, w, h, 82, 108, 174, 146, accent)
draw_circle(pixels, w, h, 92, 176, 16, (48, 38, 32))
draw_circle(pixels, w, h, 164, 176, 16, (48, 38, 32))
draw_line(pixels, w, h, 90, 108, 72, 78, (248, 238, 221), 3)
draw_line(pixels, w, h, 176, 108, 194, 78, (248, 238, 221), 3)
elif motif == 'window':
draw_rect(pixels, w, h, 66, 58, 190, 188, tuple(min(255, c + 32) for c in accent))
draw_rect(pixels, w, h, 78, 70, 178, 176, (250, 244, 232))
draw_line(pixels, w, h, 128, 70, 128, 176, (88, 70, 58), 4)
draw_line(pixels, w, h, 78, 123, 178, 123, (88, 70, 58), 4)
elif motif == 'lights':
draw_line(pixels, w, h, 34, 64, 222, 64, (60, 48, 40), 3)
for i, x in enumerate(range(48, 208, 24)):
color = (255, 225 - i * 5, 150 + i * 8)
draw_circle(pixels, w, h, x, 64 + (i % 2) * 8, 8, color)
draw_rect(pixels, w, h, 58, 112, 198, 176, tuple(max(0, c - 24) for c in soft))
draw_circle(pixels, w, h, 128, 146, 26, (250, 240, 218))
elif motif == 'laundry':
draw_rect(pixels, w, h, 50, 88, 206, 188, (72, 92, 116))
draw_circle(pixels, w, h, 102, 138, 26, (240, 244, 248))
draw_circle(pixels, w, h, 154, 138, 26, (240, 244, 248))
draw_line(pixels, w, h, 70, 104, 186, 104, (240, 244, 248), 2)
draw_line(pixels, w, h, 70, 160, 186, 160, (240, 244, 248), 2)
elif motif == 'chalk':
draw_rect(pixels, w, h, 52, 80, 204, 204, tuple(max(0, c - 18) for c in background))
for i in range(4):
draw_rect(pixels, w, h, 72 + i * 26, 98 + (i % 2) * 24, 92 + i * 26, 118 + (i % 2) * 24, (255, 240 - i * 18, 230 - i * 10))
draw_line(pixels, w, h, 90, 190, 166, 120, (255, 225, 140), 4)
draw_line(pixels, w, h, 102, 122, 122, 102, (255, 160, 180), 3)
else:
raise ValueError(motif)
border = (250, 244, 232)
for x in range(6, w - 6, 16):
draw_rect(pixels, w, h, x, 4, x + 8, 8, border)
draw_rect(pixels, w, h, x, h - 8, x + 8, h - 4, border)
for y in range(6, h - 6, 16):
draw_rect(pixels, w, h, 4, y, 8, y + 8, border)
draw_rect(pixels, w, h, w - 8, y, w - 4, y + 8, border)
write_png(photos_dir / name, w, h, pixels)
images = [
('blue_house.png', (65, 94, 145), (120, 159, 196), (33, 52, 81), 'house'),
('tamale_cart.png', (171, 116, 78), (219, 163, 95), (104, 72, 52), 'cart'),
('winter_market.png', (72, 86, 110), (132, 158, 182), (38, 48, 64), 'lights'),
('kitchen_quilt.png', (145, 118, 94), (204, 168, 132), (92, 72, 58), 'window'),
('laundromat_dawn.png', (92, 106, 122), (153, 171, 186), (58, 66, 78), 'laundry'),
('chalk_hopscotch.png', (109, 146, 103), (168, 188, 136), (78, 110, 70), 'chalk'),
]
for name, background, accent, soft, motif in images:
make_image(name, background, accent, soft, motif)
manifest = {
'pack_id': 'p5_memory_quilt',
'description': 'Synthetic neighborhood memories for the FLUX memory quilt offline demo.',
'style': 'Fabric Quilt',
'photos': [name for name, *_ in images],
'memories': [f'memory-{i:02d}' for i in range(1, 7)],
'version': 1,
'source': 'repository-authored synthetic demo pack',
}
memories = [
{
'id': 'memory-01',
'text': 'Every Friday the tamale cart parked outside the blue house, and neighbors waved from the porch.',
'location': 'blue house',
'season': 'summer',
'tags': ['food', 'porch', 'neighbors'],
},
{
'id': 'memory-02',
'text': 'At dawn the laundromat windows glowed warm while my aunt folded towels and told the same story twice.',
'location': 'laundromat',
'season': 'spring',
'tags': ['laundry', 'family', 'dawn'],
},
{
'id': 'memory-03',
'text': 'Winter market lights spilled onto the wet sidewalk, and the whole block felt quieter and kinder.',
'location': 'winter market',
'season': 'winter',
'tags': ['market', 'lights', 'winter'],
},
{
'id': 'memory-04',
'text': 'On the kitchen table, a folded quilt held the smell of cedar, coffee, and Sunday conversation.',
'location': 'kitchen table',
'season': 'autumn',
'tags': ['quilt', 'kitchen', 'family'],
},
{
'id': 'memory-05',
'text': 'A bus stop mural turned gold at sunset, and we counted every passing car like it was a parade.',
'location': 'bus stop',
'season': 'summer',
'tags': ['bus stop', 'mural', 'sunset'],
},
{
'id': 'memory-06',
'text': 'Kids drew hopscotch chalk under the sycamore tree, then raced the shadow line before dinner.',
'location': 'sycamore tree',
'season': 'spring',
'tags': ['chalk', 'kids', 'street'],
},
]
(root / 'manifest.json').write_text(json.dumps(manifest, indent=2, ensure_ascii=False) + '\n', encoding='utf-8')
(root / 'memories.json').write_text(json.dumps(memories, indent=2, ensure_ascii=False) + '\n', encoding='utf-8')
print({'images': [name for name, *_ in images], 'manifest': str(root / 'manifest.json'), 'memories': str(root / 'memories.json')})