Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
UncertainProd
GitHub Repository: UncertainProd/FnF-Spritesheet-and-XML-Maker
Path: blob/master/src/engine/icongridutils.py
254 views
1
from PIL import Image
2
3
def _icongrid_add_row(icongrid, iconsize=150):
4
icongrid_cpy = icongrid.copy()
5
new_icongrid = Image.new('RGBA', (icongrid_cpy.size[0], icongrid_cpy.size[1]+iconsize), (0, 0, 0, 0))
6
new_icongrid.paste(icongrid_cpy)
7
icongrid_cpy.close()
8
return new_icongrid
9
10
def _get_last_row_and_col(icongrid, iconsize=150):
11
_box = icongrid.getbbox()
12
pix_to_index = lambda pixels: pixels//iconsize
13
14
if _box:
15
# finding last row index
16
_, _, _, lastrow_y = _box
17
last_row_index = pix_to_index(lastrow_y)
18
19
# finding last col index
20
_last_row_img = icongrid.crop((0, last_row_index*iconsize, icongrid.width, last_row_index*iconsize + iconsize))
21
22
_box = _last_row_img.getbbox()
23
if _box:
24
_, _, lastcol_x, _ = _box
25
else:
26
print("ERROR: error in trying to find last column, setting to 0")
27
lastcol_x = 0
28
last_col_index = pix_to_index(lastcol_x)
29
else:
30
print("ERROR: icongrid is empty, cannot find bbox")
31
last_row_index = 0
32
last_col_index = 0
33
34
return last_row_index, last_col_index
35
36
ICON_PERFECT_FIT = 0
37
ICON_BIGGER_THAN_AREA = 1
38
ICON_SMALLER_THAN_AREA = 2
39
40
def _check_icon_size(icon, check_width=150, check_height=150):
41
# 0 = icon is 150x150
42
# 1 = icon is too wide/tall
43
# 2 = icon is smaller than 150x150 area
44
if icon.width == check_width and icon.height == check_height:
45
return ICON_PERFECT_FIT
46
elif icon.width > 150 or icon.height > 150:
47
return ICON_BIGGER_THAN_AREA
48
else:
49
return ICON_SMALLER_THAN_AREA
50
51
def _center_icon(icon):
52
w, h = icon.size
53
final_icon = Image.new('RGBA', (150, 150), (0, 0, 0, 0))
54
dx = (150 - w) // 2
55
dy = (150 - h) // 2
56
final_icon.paste(icon, (dx, dy))
57
return final_icon
58
59
def appendIconToGrid(icongrid_path, iconpaths, iconsize=150):
60
print("Icongrid from: {} \nIcons: {}".format(icongrid_path, len(iconpaths)))
61
62
return_status = 0
63
indices = []
64
problem_icon = None
65
exception_msg = None
66
67
IMAGES_PER_COLUMN = 10
68
69
try:
70
# icongrid = Image.open(icongrid_path)
71
with Image.open(icongrid_path).convert('RGBA') as icongrid:
72
# icongrid = icongrid.convert('RGBA')
73
for iconpath in iconpaths:
74
# icon_img = Image.open(iconpath)
75
with Image.open(iconpath).convert('RGBA') as icon_img:
76
# check if icon_img is 150x150
77
can_fit = _check_icon_size(icon_img)
78
if can_fit == ICON_BIGGER_THAN_AREA:
79
# if the icon is too big, ignore it (for now)
80
return_status = 2
81
problem_icon = iconpath
82
continue
83
elif can_fit == ICON_SMALLER_THAN_AREA:
84
print(f"Icon: {iconpath} is smaller than 150x150, centering it....")
85
icon_img = _center_icon(icon_img)
86
87
# get location to paste it
88
last_row_idx, last_col_idx = _get_last_row_and_col(icongrid)
89
90
new_index = last_row_idx*IMAGES_PER_COLUMN + last_col_idx + 1
91
indices.append(new_index)
92
new_row_idx = new_index // IMAGES_PER_COLUMN
93
new_col_idx = new_index % IMAGES_PER_COLUMN
94
95
if new_row_idx * iconsize >= icongrid.height:
96
print("Icongrid is full. Expanding it....")
97
icongrid = _icongrid_add_row(icongrid)
98
99
icongrid.paste(icon_img, (new_col_idx*iconsize, new_row_idx*iconsize))
100
icongrid.save(icongrid_path)
101
except Exception as e:
102
return_status = -1
103
exception_msg = f"{e.__class__.__name__} : {str(e)}"
104
105
106
return return_status, indices, problem_icon, exception_msg
107
108
def makePsychEngineIconGrid(iconpaths, savepath, img_size=150):
109
# this function works for any number of icons that you provide, even though psych engine uses 2 icons for a character
110
status = 0
111
problemimg = None
112
exception_msg = None
113
114
good_icons = []
115
for iconpath in iconpaths:
116
try:
117
icon = Image.open(iconpath).convert('RGBA')
118
except Exception as e:
119
exception_msg = f"{e.__class__.__name__} : {str(e)}"
120
continue
121
fit_status = _check_icon_size(icon)
122
if fit_status == ICON_BIGGER_THAN_AREA:
123
problemimg = iconpath
124
status = 1
125
icon.close()
126
continue
127
elif fit_status == ICON_SMALLER_THAN_AREA:
128
print(f"Icon: {iconpath} is smaller than 150x150, centering it....")
129
icon = _center_icon(icon)
130
good_icons.append(icon)
131
132
if len(good_icons) == 0:
133
return 1, problemimg, exception_msg
134
135
final_icongrid = Image.new('RGBA', (img_size*len(good_icons), img_size), (0, 0, 0, 0))
136
for i, icon in enumerate(good_icons):
137
final_icongrid.paste(icon, (i*img_size, 0))
138
icon.close()
139
140
final_icongrid.save(savepath)
141
final_icongrid.close()
142
143
return status, problemimg, exception_msg
144