dikdimon's picture
Upload extensionsa using SD-Hub extension
7bed60d verified
from json.decoder import JSONDecodeError
from PIL import Image, ImageDraw
from json import loads
DEFAULT_MAPPING = [["0.00:0.50", "0.00:1.00", "1.0"], ["0.50:1.00", "0.00:1.00", "1.0"]]
COLORS = ("red", "orange", "yellow", "green", "blue", "indigo", "violet")
def parse_mapping(data: list) -> list:
mapping = []
for [X, Y, W] in data:
if not X.strip():
continue
mapping.append(
(
(float(X.split(":")[0]), float(X.split(":")[1])),
(float(Y.split(":")[0]), float(Y.split(":")[1])),
float(W),
)
)
return mapping
def validate_mapping(data: list) -> bool:
try:
for [X, Y, W] in data:
if not X.strip():
continue
assert len(X.split(":")) == 2
assert len(Y.split(":")) == 2
val = []
val.append(float(X.split(":")[0]))
val.append(float(X.split(":")[1]))
val.append(float(Y.split(":")[0]))
val.append(float(Y.split(":")[1]))
float(W)
for v in val:
if v < 0.0 or v > 1.0:
raise OverflowError
if val[1] < val[0] or val[3] < val[2]:
raise IndexError
return True
except AssertionError:
print("\n\n[Couple] Incorrect number of : in Mapping...\n\n")
return False
except ValueError:
print("\n\n[Couple] Non-Number in Mapping...\n\n")
return False
except OverflowError:
print("\n\n[Couple] Range must be between 0.0 and 1.0...\n\n")
return False
except IndexError:
print('\n\n[Couple] "to" value must be larger than "from" value...\n\n')
return False
def visualize_mapping(res: str, data: list) -> Image:
w, h = res.split("x")
p_WIDTH = int(w)
p_HEIGHT = int(h)
while p_WIDTH > 1024 or p_HEIGHT > 1024:
p_WIDTH //= 2
p_HEIGHT //= 2
while p_WIDTH < 512 and p_HEIGHT < 512:
p_WIDTH *= 2
p_HEIGHT *= 2
matt = Image.new("RGBA", (p_WIDTH, p_HEIGHT), (0, 0, 0, 64))
if not (validate_mapping(data)):
return matt
lnw = int(max(min(p_WIDTH, p_HEIGHT) / 128, 4.0))
draw = ImageDraw.Draw(matt)
mapping = parse_mapping(data)
# print("\nAdv. Preview:")
for tile_index in range(len(mapping)):
color_index = tile_index % len(COLORS)
(X, Y, W) = mapping[tile_index]
x_from = int(p_WIDTH * X[0])
x_to = int(p_WIDTH * X[1])
y_from = int(p_HEIGHT * Y[0])
y_to = int(p_HEIGHT * Y[1])
# weight = W
# print(f" [{y_from:4d}:{y_to:4d}, {x_from:4d}:{x_to:4d}] = {weight:.2f}")
draw.rectangle(
((x_from, y_from), (x_to, y_to)), outline=COLORS[color_index], width=lnw
)
return matt
def reset_mapping() -> list:
return DEFAULT_MAPPING
def add_row_above(data: list, index: int) -> list:
if index < 0:
return data
return data[:index] + [["0.00:1.00", "0.00:1.00", "1.0"]] + data[index:]
def add_row_below(data: list, index: int = None) -> list:
if index is None or index < 0:
return data + [["0.25:0.75", "0.25:0.75", "1.0"]]
return data[: index + 1] + [["0.25:0.75", "0.25:0.75", "1.0"]] + data[index + 1 :]
def del_row_select(data: list, index: int) -> list:
if index < 0:
return data
if len(data) == 1:
return [["0.0:1.0", "0.0:1.0", "1.0"]]
else:
del data[index]
return data
def on_paste(data: str) -> list:
try:
return loads(data)
except JSONDecodeError:
print("\n[Adv. Mapping] Pasting Old Infotext is not supported...\n")
return DEFAULT_MAPPING
def manual_entry(data: list, new: str, index: int) -> list:
if index < 0:
return data
v = [round(float(val), 2) for val in new.split(",")]
if v[1] < v[0]:
v[0], v[1] = v[1], v[0]
if v[3] < v[2]:
v[2], v[3] = v[3], v[2]
try:
data[index][0] = f"{v[0]:.2f}:{v[1]:.2f}"
data[index][1] = f"{v[2]:.2f}:{v[3]:.2f}"
except IndexError:
data.append([f"{v[0]:.2f}:{v[1]:.2f}", f"{v[2]:.2f}:{v[3]:.2f}", "1.0"])
return data