| from PIL import Image, ImageDraw | |
| import gradio as gr | |
| 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 validata_mapping(data: list) -> bool: | |
| try: | |
| for [X, Y, W] in data: | |
| if not X.strip(): | |
| continue | |
| float(X.split(":")[0]) | |
| float(X.split(":")[1]) | |
| float(Y.split(":")[0]) | |
| float(Y.split(":")[1]) | |
| float(W) | |
| 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 | |
| def visualize_mapping(p_WIDTH: int, p_HEIGHT: int, data: list) -> Image: | |
| if not (validata_mapping(data)): | |
| return None | |
| COLORS = ("red", "orange", "yellow", "green", "blue", "violet", "purple", "white") | |
| matt = Image.new("RGB", (p_WIDTH, p_HEIGHT), "black") | |
| 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=2 | |
| ) | |
| return matt | |
| def couple_UI(script, title: str): | |
| with gr.Accordion(label=title, open=False): | |
| with gr.Row(): | |
| enable = gr.Checkbox(label="Enable", elem_id="fc_enable") | |
| mode = gr.Radio( | |
| ["Basic", "Advanced"], | |
| label="Region Assignment", | |
| value="Basic", | |
| ) | |
| separator = gr.Textbox( | |
| label="Couple Separator", | |
| lines=1, | |
| max_lines=1, | |
| placeholder="Leave empty to use newline", | |
| ) | |
| with gr.Group() as basic_settings: | |
| with gr.Row(): | |
| direction = gr.Radio( | |
| ["Horizontal", "Vertical"], | |
| label="Tile Direction", | |
| value="Horizontal", | |
| ) | |
| background = gr.Radio( | |
| ["None", "First Line", "Last Line"], | |
| label="Global Effect", | |
| value="None", | |
| ) | |
| with gr.Group(visible=False, elem_id="fc_adv") as adv_settings: | |
| mapping = gr.Dataframe( | |
| label="Mapping", | |
| headers=["x", "y", "weight"], | |
| datatype="str", | |
| row_count=(2, "dynamic"), | |
| col_count=(3, "fixed"), | |
| interactive=True, | |
| type="array", | |
| value=[["0:0.5", "0.0:1.0", "1.0"], ["0.5:1.0", "0.0:1.0", "1.0"]], | |
| ) | |
| preview_img = gr.Image( | |
| image_mode="RGB", | |
| label="Mapping Preview", | |
| type="pil", | |
| interactive=False, | |
| height=512, | |
| ) | |
| with gr.Row(): | |
| preview_width = gr.Number(value=1024, label="Width", precision=0) | |
| preview_height = gr.Number(value=1024, label="Height", precision=0) | |
| preview_btn = gr.Button("Preview Mapping", elem_id="fc_preview") | |
| preview_btn.click( | |
| visualize_mapping, | |
| [preview_width, preview_height, mapping], | |
| preview_img, | |
| ) | |
| def on_radio_change(choice): | |
| if choice == "Basic": | |
| return [ | |
| gr.Group.update(visible=True), | |
| gr.Group.update(visible=False), | |
| ] | |
| else: | |
| return [ | |
| gr.Group.update(visible=False), | |
| gr.Group.update(visible=True), | |
| ] | |
| mode.change(on_radio_change, mode, [basic_settings, adv_settings]) | |
| script.paste_field_names = [] | |
| script.infotext_fields = [ | |
| (enable, "forge_couple"), | |
| (direction, "forge_couple_direction"), | |
| (background, "forge_couple_background"), | |
| (separator, "forge_couple_separator"), | |
| (mode, "forge_couple_mode"), | |
| (mapping, "forge_couple_mapping"), | |
| ] | |
| for comp, name in script.infotext_fields: | |
| comp.do_not_save_to_config = True | |
| script.paste_field_names.append(name) | |
| return [enable, direction, background, separator, mode, mapping] | |