File size: 2,560 Bytes
c670567
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from __future__ import annotations

from pathlib import Path

from PIL import Image, ImageEnhance, ImageOps


ROOT = Path(__file__).resolve().parents[1]
SOURCE_DIR = ROOT.parent / "ai-native"
ASSET_DIR = ROOT / "src" / "mafia" / "ui" / "assets"
PORTRAITS = ASSET_DIR / "portraits"
REFERENCE = ASSET_DIR / "reference"


PORTRAIT_CROPS = {
    "p1-you": (642, 130, 822, 318),
    "p2-luna": (900, 160, 1096, 360),
    "p3-rook": (995, 336, 1190, 536),
    "p4-jett": (795, 486, 990, 690),
    "p5-vesper": (496, 492, 700, 700),
    "p6-dante": (316, 332, 514, 536),
    "p7-selene": (456, 138, 662, 338),
}


def save_portrait(source: Image.Image, name: str, crop: tuple[int, int, int, int]) -> None:
    image = source.crop(crop).resize((288, 288), Image.Resampling.LANCZOS).convert("RGBA")
    # Preserve the portrait, but mask it into a game-token circle.
    mask = Image.new("L", image.size, 0)
    mask = ImageOps.fit(mask, image.size)
    circle = Image.new("L", image.size, 0)
    from PIL import ImageDraw

    draw = ImageDraw.Draw(circle)
    draw.ellipse((4, 4, image.size[0] - 4, image.size[1] - 4), fill=255)
    image.putalpha(circle)
    # Slightly lift contrast for small in-game sizes.
    rgb = Image.new("RGBA", image.size, (0, 0, 0, 0))
    rgb.alpha_composite(image)
    enhanced = ImageEnhance.Contrast(rgb).enhance(1.08)
    enhanced.save(PORTRAITS / f"{name}.png")


def main() -> None:
    PORTRAITS.mkdir(parents=True, exist_ok=True)
    REFERENCE.mkdir(parents=True, exist_ok=True)
    ui1 = Image.open(SOURCE_DIR / "ui-1.png").convert("RGB")
    ui3 = Image.open(SOURCE_DIR / "ui-3.png").convert("RGB")
    ui4 = Image.open(SOURCE_DIR / "ui-4.png").convert("RGB")
    ui5 = Image.open(SOURCE_DIR / "ui-5.png").convert("RGB")

    for name, crop in PORTRAIT_CROPS.items():
        save_portrait(ui1, name, crop)

    # Background and panel references. These are not full screenshots; they are
    # cropped atmospheric surfaces used behind code-native controls.
    ui1.crop((270, 70, 1310, 830)).resize((1400, 900), Image.Resampling.LANCZOS).save(
        REFERENCE / "table-room.png"
    )
    ui4.crop((260, 60, 1320, 820)).resize((1400, 900), Image.Resampling.LANCZOS).save(
        REFERENCE / "hot-seat-room.png"
    )
    ui5.crop((330, 35, 1280, 820)).resize((1400, 900), Image.Resampling.LANCZOS).save(
        REFERENCE / "endgame-room.png"
    )
    ui3.crop((1090, 525, 1295, 790)).resize((420, 520), Image.Resampling.LANCZOS).save(
        REFERENCE / "assistant-panel.png"
    )


if __name__ == "__main__":
    main()