-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmoonlight_window.py
98 lines (77 loc) · 3.37 KB
/
moonlight_window.py
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
from PIL import Image, ImageDraw, ImageFont
import numpy as np
import os
# config
pix_per_char = 300
font_support_dict = {
"simhei": "simhei.ttf",
"Deng": "Deng.ttf",
"simsun": "simsun.ttc",
"simkai": "simkai.ttf",
}
bg_color = (255, 255, 255) # white
ans_color = (0, 0, 0) # black
char_color = (0, 0, 255) # blue
split_color = (127, 127, 127) # gray
os.makedirs("output", exist_ok=True)
# while True:
def moonlight_window(chars: str, font: str):
if len(chars) >= 10:
return f"Fail! {chars} is too long!"
# default font: simhei
font = ImageFont.truetype(font_support_dict.get(
font,
font_support_dict["simhei"]
), pix_per_char) # Font type
char_num = len(chars)
width, height = char_num * pix_per_char, pix_per_char
image = Image.new('RGB', (width, height), ans_color)
draw = ImageDraw.Draw(image)
# get answer image step 1: write characters on answer color
for idx, char in enumerate(chars):
position = (idx * pix_per_char, 0)
draw.text(position, char, font=font, fill=char_color)
# get answer image step 2: make the characters bi-valued (preperation for flood)
img_arr = np.array(image)
mask = (img_arr==char_color).astype(np.uint8).sum(axis=-1)==3
mask3 = np.dstack([mask.astype(np.uint8)]*3)
img_arr_dyed = np.array(char_color).astype(np.uint8).reshape((1, 1, 3)) * mask3
image = Image.fromarray(img_arr_dyed)
draw = ImageDraw.Draw(image)
# get answer image step 3: dye background with flood
ImageDraw.floodfill(image, (0, 0), value=bg_color)
# get answer image step 4: split characters from each other
for idx in range(1, char_num):
xy = (idx * pix_per_char, 0, idx * pix_per_char, pix_per_char)
draw.line(xy, fill=split_color)
# get answer image step 5: draw four sides of the image
for xy in [
(0, 0, 0, height - 1),
(width - 1, 0, width - 1, height - 1),
(0, 0, width - 1, 0 ),
(0, height - 1, width - 1, height - 1),
]:
draw.line(xy, fill=split_color)
image.save(f"output/{chars}_A.png")
# get question image step 1: dye background
img_arr = np.array(image)
mask = (img_arr!=ans_color).astype(np.uint8).sum(axis=-1)!=0
mask3 = np.dstack([mask.astype(np.uint8)]*3)
img_arr_dyed = np.array(bg_color).astype(np.uint8).reshape((1, 1, 3)) * mask3
image = Image.fromarray(img_arr_dyed)
draw = ImageDraw.Draw(image)
# get question image step 2: split characters from each other
for idx in range(1, char_num):
xy = (idx * pix_per_char, 0, idx * pix_per_char, pix_per_char)
draw.line(xy, fill=split_color)
# get question image step 3: draw four sides of the image
for xy in [
(0, 0, 0, height - 1),
(width - 1, 0, width - 1, height - 1),
(0, 0, width - 1, 0 ),
(0, height - 1, width - 1, height - 1),
]:
draw.line(xy, fill=split_color)
image.save(f"output/{chars}_Q.png")
return "Success!"
# return f"Success! Please refer to output/{chars}_Q.png and output/{chars}_A.png"