mirror of
https://github.com/altoiddealer/--sd-webui-ar-plusplus.git
synced 2026-03-13 17:20:07 +00:00
Add JS based button titles
Add button titles on UI load. Use comments in aspect_ratios.txt and resolutions.txt to for user configured buttons, and hard-coded titles in sd-webui-ar.js for built-in buttons (i.e. for calculator).
This commit is contained in:
2
javascript/button_titles.js
Normal file
2
javascript/button_titles.js
Normal file
@@ -0,0 +1,2 @@
|
||||
// Do not put custom titles here. This file is overwritten each time the WebUI is started.
|
||||
ar_button_titles = {}
|
||||
20
javascript/sd-webui-ar.js
Normal file
20
javascript/sd-webui-ar.js
Normal file
@@ -0,0 +1,20 @@
|
||||
if ("undefined" === typeof ar_button_titles) {
|
||||
ar_button_titles = {};
|
||||
}
|
||||
|
||||
ar_button_titles["Calc"] = "Show or hide the aspect ratio calculator";
|
||||
ar_button_titles["\u{21c5}"] = "Swap width and height values";
|
||||
ar_button_titles["\u2B07\ufe0f"] = "Get dimensions from txt2img/img2img sliders";
|
||||
ar_button_titles["\u{1f5bc}"] = "Get dimensions from image on current img2img tab";
|
||||
ar_button_titles["Calculate Height"] = "Calculate new height based on source aspect ratio";
|
||||
ar_button_titles["Calculate Width"] = "Calculate new width based on source aspect ratio";
|
||||
ar_button_titles["Apply"] = "Apply calculated width and height to txt2img/img2img sliders";
|
||||
|
||||
onUiUpdate(function(){
|
||||
gradioApp().querySelectorAll('#txt2img_container_aspect_ratio button, #img2img_container_aspect_ratio button').forEach(function(elem){
|
||||
tooltip = ar_button_titles[elem.textContent];
|
||||
if(tooltip){
|
||||
elem.title = tooltip;
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -12,10 +12,9 @@ aspect_ratios_dir = scripts.basedir()
|
||||
|
||||
calculator_symbol = '\U0001F5A9'
|
||||
switch_values_symbol = '\U000021C5'
|
||||
get_dimensions_symbol = '\U00002B07'
|
||||
get_dimensions_symbol = '\u2B07\ufe0f'
|
||||
get_image_dimensions_symbol = '\U0001F5BC'
|
||||
|
||||
|
||||
class ResButton(ToolButton):
|
||||
def __init__(self, res=(512, 512), **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
@@ -110,10 +109,10 @@ def parse_resolutions_file(filename):
|
||||
# TODO: write a generic function handling both cases
|
||||
def write_aspect_ratios_file(filename):
|
||||
aspect_ratios = [
|
||||
"1:1, 1.0\n",
|
||||
"3:2, 3/2\n",
|
||||
"4:3, 4/3\n",
|
||||
"16:9, 16/9",
|
||||
"1:1, 1.0 # 1:1 ratio based on minimum dimension\n",
|
||||
"3:2, 3/2 # Set width based on 3:2 ratio to height\n",
|
||||
"4:3, 4/3 # Set width based on 4:3 ratio to height\n",
|
||||
"16:9, 16/9 # Set width based on 16:9 ratio to height",
|
||||
]
|
||||
with open(filename, "w", encoding="utf-8") as f:
|
||||
f.writelines(aspect_ratios)
|
||||
@@ -129,6 +128,20 @@ def write_resolutions_file(filename):
|
||||
f.writelines(resolutions)
|
||||
|
||||
|
||||
def write_js_titles_file(button_titles):
|
||||
filename = Path(aspect_ratios_dir + "\\javascript\\", "button_titles.js")
|
||||
content = ["// Do not put custom titles here. This file is overwritten each time the WebUI is started.\n"]
|
||||
content.append("ar_button_titles = {\n")
|
||||
counter = 0
|
||||
while counter < len(button_titles[0]):
|
||||
content.append(f" \"{button_titles[0][counter]}\" : \"{button_titles[1][counter]}\",\n")
|
||||
counter = counter + 1
|
||||
content.append("}")
|
||||
|
||||
with open(filename, "w", encoding="utf-8") as f:
|
||||
f.writelines(content)
|
||||
|
||||
|
||||
def get_reduced_ratio(n, d):
|
||||
n, d = list(map(int, (n, d)))
|
||||
|
||||
@@ -196,169 +209,175 @@ class AspectRatioScript(scripts.Script):
|
||||
return scripts.AlwaysVisible
|
||||
|
||||
def ui(self, is_img2img):
|
||||
self.read_aspect_ratios()
|
||||
with gr.Row(elem_id=f'{"img" if is_img2img else "txt"}2img_row_aspect_ratio'):
|
||||
# Toggle calculator display button
|
||||
arc_show_calculator = gr.Button(value="Calc", visible=True, variant="secondary", elem_id="arc_show_calculator_button")
|
||||
arc_hide_calculator = gr.Button(value="Calc", visible=False, variant="primary", elem_id="arc_hide_calculator_button")
|
||||
with gr.Column(elem_id=f'{"img" if is_img2img else "txt"}2img_container_aspect_ratio'):
|
||||
self.read_aspect_ratios()
|
||||
with gr.Row(elem_id=f'{"img" if is_img2img else "txt"}2img_row_aspect_ratio'):
|
||||
# Toggle calculator display button
|
||||
arc_show_calculator = gr.Button(value="Calc", visible=True, variant="secondary", elem_id="arc_show_calculator_button")
|
||||
arc_hide_calculator = gr.Button(value="Calc", visible=False, variant="primary", elem_id="arc_hide_calculator_button")
|
||||
|
||||
# Aspect Ratio buttons
|
||||
btns = [
|
||||
ARButton(ar=ar, value=label)
|
||||
for ar, label in zip(
|
||||
self.aspect_ratios,
|
||||
self.aspect_ratio_labels,
|
||||
)
|
||||
]
|
||||
|
||||
with contextlib.suppress(AttributeError):
|
||||
for b in btns:
|
||||
if is_img2img:
|
||||
resolution = [self.i2i_w, self.i2i_h]
|
||||
else:
|
||||
resolution = [self.t2i_w, self.t2i_h]
|
||||
|
||||
b.click(
|
||||
b.apply,
|
||||
inputs=resolution,
|
||||
outputs=resolution,
|
||||
# Aspect Ratio buttons
|
||||
btns = [
|
||||
ARButton(ar=ar, value=label)
|
||||
for ar, label in zip(
|
||||
self.aspect_ratios,
|
||||
self.aspect_ratio_labels,
|
||||
)
|
||||
]
|
||||
|
||||
self.read_resolutions()
|
||||
with gr.Row(elem_id=f'{"img" if is_img2img else "txt"}2img_row_resolutions'):
|
||||
btns = [
|
||||
ResButton(res=res, value=label)
|
||||
for res, label in zip(self.res, self.res_labels)
|
||||
]
|
||||
|
||||
with contextlib.suppress(AttributeError):
|
||||
for b in btns:
|
||||
if is_img2img:
|
||||
resolution = [self.i2i_w, self.i2i_h]
|
||||
else:
|
||||
resolution = [self.t2i_w, self.t2i_h]
|
||||
|
||||
b.click(
|
||||
b.reset,
|
||||
outputs=resolution,
|
||||
)
|
||||
|
||||
# dummy components needed for JS function
|
||||
dummy_text1 = gr.Text(visible=False)
|
||||
dummy_text2 = gr.Text(visible=False)
|
||||
dummy_text3 = gr.Text(visible=False)
|
||||
dummy_text4 = gr.Text(visible=False)
|
||||
|
||||
# Aspect Ratio Calculator
|
||||
with gr.Column(visible=False, variant="panel", elem_id="arc_panel") as arc_panel:
|
||||
arc_title_heading = gr.Markdown(value="#### Aspect Ratio Calculator")
|
||||
with gr.Row():
|
||||
with gr.Column(min_width=150):
|
||||
arc_width1 = gr.Number(label="Width 1")
|
||||
arc_height1 = gr.Number(label="Height 1")
|
||||
|
||||
with gr.Column(min_width=150):
|
||||
arc_desired_width = gr.Number(label="Width 2")
|
||||
arc_desired_height = gr.Number(label="Height 2")
|
||||
|
||||
with gr.Column(min_width=150):
|
||||
arc_ar_display = gr.Markdown(value="Aspect Ratio:")
|
||||
with gr.Row(elem_id=f'{"img" if is_img2img else "txt"}2img_arc_tool_buttons'):
|
||||
# Switch resolution values button
|
||||
arc_swap = ToolButton(value=switch_values_symbol)
|
||||
arc_swap.click(lambda w, h, w2, h2: (h, w, h2, w2), inputs=[arc_width1, arc_height1, arc_desired_width, arc_desired_height], outputs=[arc_width1, arc_height1, arc_desired_width, arc_desired_height])
|
||||
|
||||
with contextlib.suppress(AttributeError):
|
||||
# For img2img tab
|
||||
if is_img2img:
|
||||
# Get slider dimensions button
|
||||
resolution = [self.i2i_w, self.i2i_h]
|
||||
arc_get_img2img_dim = ToolButton(value=get_dimensions_symbol)
|
||||
arc_get_img2img_dim.click(
|
||||
lambda w, h: (w, h),
|
||||
inputs=resolution,
|
||||
outputs=[arc_width1, arc_height1],
|
||||
)
|
||||
|
||||
# Javascript function to select image element from current img2img tab
|
||||
current_tab_image = """
|
||||
function current_tab_image(...args) {
|
||||
const tab_index = get_img2img_tab_index();
|
||||
// Get current tab's image (on Batch tab, use image from img2img tab)
|
||||
if (tab_index == 5) {
|
||||
image = args[0];
|
||||
} else {
|
||||
image = args[tab_index];
|
||||
}
|
||||
// On Inpaint tab, select just the image and drop the mask
|
||||
if (tab_index == 2 && image !== null) {
|
||||
image = image["image"];
|
||||
}
|
||||
return [image, null, null, null, null];
|
||||
}
|
||||
|
||||
"""
|
||||
# Get image dimensions
|
||||
def get_dims(img: list, dummy_text1, dummy_text2, dummy_text3, dummy_text4):
|
||||
if img:
|
||||
width = img.size[0]
|
||||
height = img.size[1]
|
||||
return width, height
|
||||
else:
|
||||
return 0, 0
|
||||
|
||||
# Get image dimensions button
|
||||
arc_get_image_dim = ToolButton(value=get_image_dimensions_symbol)
|
||||
arc_get_image_dim.click(fn=get_dims,inputs=self.image,outputs=[arc_width1, arc_height1],_js=current_tab_image)
|
||||
|
||||
else:
|
||||
# For txt2img tab
|
||||
# Get slider dimensions button
|
||||
resolution = [self.t2i_w, self.t2i_h]
|
||||
arc_get_txt2img_dim = ToolButton(value=get_dimensions_symbol)
|
||||
arc_get_txt2img_dim.click(
|
||||
lambda w, h: (w, h),
|
||||
inputs=resolution,
|
||||
outputs=[arc_width1, arc_height1],
|
||||
)
|
||||
|
||||
# Update aspect ratio display on change
|
||||
arc_width1.change(lambda w, h: (f"Aspect Ratio: **{get_reduced_ratio(w,h)}**"), inputs=[arc_width1, arc_height1], outputs=[arc_ar_display])
|
||||
arc_height1.change(lambda w, h: (f"Aspect Ratio: **{get_reduced_ratio(w,h)}**"), inputs=[arc_width1, arc_height1], outputs=[arc_ar_display])
|
||||
|
||||
with gr.Row():
|
||||
# Calculate and Apply buttons
|
||||
arc_calc_height = gr.Button(value='Calculate Height').style(full_width=False)
|
||||
arc_calc_height.click(lambda w2, w1, h1: (solve_aspect_ratio(w2,0,w1,h1)), inputs=[arc_desired_width,arc_width1,arc_height1], outputs=[arc_desired_height])
|
||||
arc_calc_width = gr.Button(value='Calculate Width').style(full_width=False)
|
||||
arc_calc_width.click(lambda h2, w1, h1: (solve_aspect_ratio(0,h2,w1,h1)), inputs=[arc_desired_height,arc_width1,arc_height1], outputs=[arc_desired_width])
|
||||
arc_apply_params = gr.Button(value='Apply')
|
||||
with contextlib.suppress(AttributeError):
|
||||
if is_img2img:
|
||||
resolution = [self.i2i_w, self.i2i_h]
|
||||
else:
|
||||
resolution = [self.t2i_w, self.t2i_h]
|
||||
for b in btns:
|
||||
if is_img2img:
|
||||
resolution = [self.i2i_w, self.i2i_h]
|
||||
else:
|
||||
resolution = [self.t2i_w, self.t2i_h]
|
||||
|
||||
arc_apply_params.click(
|
||||
lambda w2, h2: (w2, h2),
|
||||
inputs=[arc_desired_width, arc_desired_height],
|
||||
outputs=resolution,
|
||||
)
|
||||
b.click(
|
||||
b.apply,
|
||||
inputs=resolution,
|
||||
outputs=resolution,
|
||||
)
|
||||
|
||||
self.read_resolutions()
|
||||
with gr.Row(elem_id=f'{"img" if is_img2img else "txt"}2img_row_resolutions'):
|
||||
btns = [
|
||||
ResButton(res=res, value=label)
|
||||
for res, label in zip(self.res, self.res_labels)
|
||||
]
|
||||
with contextlib.suppress(AttributeError):
|
||||
for b in btns:
|
||||
if is_img2img:
|
||||
resolution = [self.i2i_w, self.i2i_h]
|
||||
else:
|
||||
resolution = [self.t2i_w, self.t2i_h]
|
||||
|
||||
b.click(
|
||||
b.reset,
|
||||
outputs=resolution,
|
||||
)
|
||||
|
||||
# Write button_titles.js with labels and comments read from aspect ratios and resolutions files
|
||||
button_titles = [self.aspect_ratio_labels + self.res_labels]
|
||||
button_titles.append(self.aspect_ratio_comments + self.res_comments)
|
||||
write_js_titles_file(button_titles)
|
||||
|
||||
# dummy components needed for JS function
|
||||
dummy_text1 = gr.Text(visible=False)
|
||||
dummy_text2 = gr.Text(visible=False)
|
||||
dummy_text3 = gr.Text(visible=False)
|
||||
dummy_text4 = gr.Text(visible=False)
|
||||
|
||||
# Aspect Ratio Calculator
|
||||
with gr.Column(visible=False, variant="panel", elem_id="arc_panel") as arc_panel:
|
||||
arc_title_heading = gr.Markdown(value="#### Aspect Ratio Calculator")
|
||||
with gr.Row():
|
||||
with gr.Column(min_width=150):
|
||||
arc_width1 = gr.Number(label="Width 1")
|
||||
arc_height1 = gr.Number(label="Height 1")
|
||||
|
||||
with gr.Column(min_width=150):
|
||||
arc_desired_width = gr.Number(label="Width 2")
|
||||
arc_desired_height = gr.Number(label="Height 2")
|
||||
|
||||
with gr.Column(min_width=150):
|
||||
arc_ar_display = gr.Markdown(value="Aspect Ratio:")
|
||||
with gr.Row(elem_id=f'{"img" if is_img2img else "txt"}2img_arc_tool_buttons'):
|
||||
# Switch resolution values button
|
||||
arc_swap = ToolButton(value=switch_values_symbol)
|
||||
arc_swap.click(lambda w, h, w2, h2: (h, w, h2, w2), inputs=[arc_width1, arc_height1, arc_desired_width, arc_desired_height], outputs=[arc_width1, arc_height1, arc_desired_width, arc_desired_height])
|
||||
|
||||
with contextlib.suppress(AttributeError):
|
||||
# For img2img tab
|
||||
if is_img2img:
|
||||
# Get slider dimensions button
|
||||
resolution = [self.i2i_w, self.i2i_h]
|
||||
arc_get_img2img_dim = ToolButton(value=get_dimensions_symbol)
|
||||
arc_get_img2img_dim.click(
|
||||
lambda w, h: (w, h),
|
||||
inputs=resolution,
|
||||
outputs=[arc_width1, arc_height1],
|
||||
)
|
||||
|
||||
# Javascript function to select image element from current img2img tab
|
||||
current_tab_image = """
|
||||
function current_tab_image(...args) {
|
||||
const tab_index = get_img2img_tab_index();
|
||||
// Get current tab's image (on Batch tab, use image from img2img tab)
|
||||
if (tab_index == 5) {
|
||||
image = args[0];
|
||||
} else {
|
||||
image = args[tab_index];
|
||||
}
|
||||
// On Inpaint tab, select just the image and drop the mask
|
||||
if (tab_index == 2 && image !== null) {
|
||||
image = image["image"];
|
||||
}
|
||||
return [image, null, null, null, null];
|
||||
}
|
||||
|
||||
"""
|
||||
# Get image dimensions
|
||||
def get_dims(img: list, dummy_text1, dummy_text2, dummy_text3, dummy_text4):
|
||||
if img:
|
||||
width = img.size[0]
|
||||
height = img.size[1]
|
||||
return width, height
|
||||
else:
|
||||
return 0, 0
|
||||
|
||||
# Get image dimensions button
|
||||
arc_get_image_dim = ToolButton(value=get_image_dimensions_symbol)
|
||||
arc_get_image_dim.click(fn=get_dims,inputs=self.image,outputs=[arc_width1, arc_height1],_js=current_tab_image)
|
||||
|
||||
else:
|
||||
# For txt2img tab
|
||||
# Get slider dimensions button
|
||||
resolution = [self.t2i_w, self.t2i_h]
|
||||
arc_get_txt2img_dim = ToolButton(value=get_dimensions_symbol)
|
||||
arc_get_txt2img_dim.click(
|
||||
lambda w, h: (w, h),
|
||||
inputs=resolution,
|
||||
outputs=[arc_width1, arc_height1],
|
||||
)
|
||||
|
||||
# Update aspect ratio display on change
|
||||
arc_width1.change(lambda w, h: (f"Aspect Ratio: **{get_reduced_ratio(w,h)}**"), inputs=[arc_width1, arc_height1], outputs=[arc_ar_display])
|
||||
arc_height1.change(lambda w, h: (f"Aspect Ratio: **{get_reduced_ratio(w,h)}**"), inputs=[arc_width1, arc_height1], outputs=[arc_ar_display])
|
||||
|
||||
with gr.Row():
|
||||
# Calculate and Apply buttons
|
||||
arc_calc_height = gr.Button(value='Calculate Height').style(full_width=False)
|
||||
arc_calc_height.click(lambda w2, w1, h1: (solve_aspect_ratio(w2,0,w1,h1)), inputs=[arc_desired_width,arc_width1,arc_height1], outputs=[arc_desired_height])
|
||||
arc_calc_width = gr.Button(value='Calculate Width').style(full_width=False)
|
||||
arc_calc_width.click(lambda h2, w1, h1: (solve_aspect_ratio(0,h2,w1,h1)), inputs=[arc_desired_height,arc_width1,arc_height1], outputs=[arc_desired_width])
|
||||
arc_apply_params = gr.Button(value='Apply')
|
||||
with contextlib.suppress(AttributeError):
|
||||
if is_img2img:
|
||||
resolution = [self.i2i_w, self.i2i_h]
|
||||
else:
|
||||
resolution = [self.t2i_w, self.t2i_h]
|
||||
|
||||
arc_apply_params.click(
|
||||
lambda w2, h2: (w2, h2),
|
||||
inputs=[arc_desired_width, arc_desired_height],
|
||||
outputs=resolution,
|
||||
)
|
||||
|
||||
# Show calculator pane (and reset number input values)
|
||||
arc_show_calculator.click(
|
||||
lambda: [gr.update(visible=True), gr.update(visible=False), gr.update(visible=True),
|
||||
gr.update(value=512), gr.update(value=512), gr.update(value=0), gr.update(value=0),
|
||||
gr.update(value="Aspect Ratio: **1:1**")],
|
||||
None,
|
||||
[arc_panel, arc_show_calculator, arc_hide_calculator,
|
||||
arc_width1, arc_height1, arc_desired_width, arc_desired_height,
|
||||
arc_ar_display]
|
||||
)
|
||||
# Hide calculator pane
|
||||
arc_hide_calculator.click(
|
||||
lambda: [gr.update(visible=False), gr.update(visible=True), gr.update(visible=False)],
|
||||
None, [arc_panel, arc_show_calculator, arc_hide_calculator])
|
||||
|
||||
# Show calculator pane (and reset number input values)
|
||||
arc_show_calculator.click(
|
||||
lambda: [gr.update(visible=True), gr.update(visible=False), gr.update(visible=True),
|
||||
gr.update(value=512), gr.update(value=512), gr.update(value=0), gr.update(value=0),
|
||||
gr.update(value="Aspect Ratio: **1:1**")],
|
||||
None,
|
||||
[arc_panel, arc_show_calculator, arc_hide_calculator,
|
||||
arc_width1, arc_height1, arc_desired_width, arc_desired_height,
|
||||
arc_ar_display]
|
||||
)
|
||||
# Hide calculator pane
|
||||
arc_hide_calculator.click(
|
||||
lambda: [gr.update(visible=False), gr.update(visible=True), gr.update(visible=False)],
|
||||
None, [arc_panel, arc_show_calculator, arc_hide_calculator])
|
||||
|
||||
# https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/7456#issuecomment-1414465888
|
||||
def after_component(self, component, **kwargs):
|
||||
|
||||
Reference in New Issue
Block a user