hero.py

2.0 kB · python · 80 lines

1import math23import lib  # noqa: F40145import numpy as np6from PIL import Image7from mrlypy.core.colors import black, gradient, ink, white8from mrlypy.core.enums import Mode9from mrlypy.core.state import seed10from mrlypy.six import FILL, GRID, VOID11from mrlypy.six.designs import carpet_cut12from mrlypy.six.renderer import draw1314from lib.canvas import H3, quantize15from lib.paths import HERO, ensure, show1617NUMBER = 518LEVEL = 219MARGIN = 020WIDTH = 192021ASPECT = 16 / 922SEED = 2623STEPS = 24024COLORS = 25625HUES = ["red", "orange", "yellow", "green", "mint", "cyan", "blue", "indigo", "purple", "pink", "red"]2627# FRAME2829def widen(cell):30    types = cell.types31    h, w = types.shape32    rows = h + 2 * MARGIN33    cols = math.ceil(2 * ASPECT * rows * H3 - 1)34    side = max(0, math.ceil((cols - w) / 2))35    side += side % 236    grid = np.full((rows, w + 2 * side), GRID, dtype=np.uint8)37    grid[MARGIN:MARGIN + h, side:side + w] = types38    cell.types = grid39    return cell4041# PAINT4243def rainbow(cell):44    palette = {45        VOID: [white],46        FILL: [black],47        GRID: gradient([ink(name) for name in HUES], STEPS),48    }49    seed(SEED)50    return cell.paint(palette, Mode.RANDOM)5152# CROP5354def crop(image):55    w, h = image.size56    box = round(w / ASPECT)57    if box <= h:58        top = (h - box) // 259        image = image.crop((0, top, w, top + box))60    else:61        box = round(h * ASPECT)62        left = (w - box) // 263        image = image.crop((left, 0, left + box, h))64    return image.convert("RGB").resize((WIDTH, round(WIDTH / ASPECT)), Image.LANCZOS)6566# RUN6768def main():69    ensure()70    cell = rainbow(widen(carpet_cut(NUMBER, LEVEL)))71    scale = math.ceil(2 * WIDTH / (cell.width + 1))72    image = draw(cell, scale=scale, start=cell.start)73    w, h = image.size74    image = crop(image.resize((w, round(h * H3)), Image.LANCZOS))75    image = quantize(image, COLORS)76    image.save(HERO, optimize=True)77    print("wrote %s %dx%d %.2f MB" % (show(HERO), *image.size, HERO.stat().st_size / 1e6))7879if __name__ == "__main__":80    main()