two-way image resize ui/kanvas

Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
Vladimir Mandic
2026-06-09 19:33:44 +02:00
parent 2313da729e
commit efe9a1f348
7 changed files with 37 additions and 5 deletions
+5 -1
View File
@@ -79,6 +79,9 @@ def ar_change(ar, width, height):
else:
return gr.update(), gr.update()
def ar_update(_ar, width, height):
return width, height
def create_resolution_inputs(tab, default_width=1024, default_height=1024):
width = gr.Slider(minimum=64, maximum=4096, step=8, label="Width", value=default_width, elem_id=f"{tab}_width")
@@ -403,7 +406,8 @@ def create_resize_inputs(tab, images, accordion=True, latent=False, non_zero=Tru
ar_list = ['AR'] + [x.strip() for x in shared.opts.aspect_ratios.split(',') if x.strip() != '']
ar_dropdown = gr.Dropdown(show_label=False, interactive=True, choices=ar_list, value=ar_list[0], elem_id=f"{tab}_resize_ar", elem_classes=["ar-dropdown"])
for c in [ar_dropdown, width, height]:
c.change(fn=ar_change, inputs=[ar_dropdown, width, height], outputs=[width, height], show_progress='hidden')
# c.change(fn=ar_change, inputs=[ar_dropdown, width, height], outputs=[width, height], show_progress='hidden')
c.change(fn=ar_update, _js='resolutionChange', inputs=[ar_dropdown, width, height], outputs=[width, height], show_progress='hidden')
res_switch_btn = ToolButton(value=ui_symbols.switch, elem_id=f"{tab}_resize_size_swap")
res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height], show_progress='hidden')
detect_image_size_btn = ToolButton(value=ui_symbols.detect, elem_id=f"{tab}_resize_detect_size")
+13
View File
@@ -11680,6 +11680,18 @@ async function toggleCompact(val, old) {
gradioApp().querySelectorAll(".small-accordion .label-wrap").forEach((el2) => el2.classList.remove("accordion-compact"));
}
}
function resolutionChange(ar, width, height) {
let desired = ar;
if (desired === "AR") desired = "1:1";
try {
const [w, h] = desired.split(":").map((x) => parseInt(x));
if (w > h) height = Math.round(width * h / w);
else if (h > w) width = Math.round(height * w / h);
} catch {
}
if (window.resizeStage) window.resizeStage(width, height);
return [ar, width, height];
}
async function reconnectUI() {
const t0 = performance.now();
const gallery = gradioApp().getElementById("txt2img_gallery");
@@ -11746,6 +11758,7 @@ window.recalculate_prompts_txt2img = recalculate_prompts_txt2img;
window.recalculate_prompts_img2img = recalculate_prompts_img2img;
window.recalculate_prompts_inpaint = recalculate_prompts_inpaint;
window.recalculate_prompts_control = recalculate_prompts_control;
window.resolutionChange = resolutionChange;
window.selectCheckpoint = selectCheckpoint;
window.selectVAE = selectVAE;
window.selectUNet = selectUNet;
+2 -2
View File
File diff suppressed because one or more lines are too long
+2
View File
@@ -74,6 +74,7 @@ declare global {
recalculate_prompts_img2img?: (...args: unknown[]) => unknown[]; // ui/ui.ts
recalculate_prompts_inpaint?: (...args: unknown[]) => unknown[]; // ui/ui.ts
recalculate_prompts_control?: (...args: unknown[]) => unknown[]; // ui/ui.ts
resolutionChange?: (ar: string, width: number, height: number) => [number, number]; // ui/ui.ts
consumeDesiredCheckpointName?: (...args: unknown[]) => unknown[]; // ui/ui.ts
create_submit_args?: (args: unknown[]) => unknown[]; // ui/ui.ts
selectCheckpoint?: (name: string) => void; // ui/ui.ts
@@ -165,6 +166,7 @@ declare global {
}; // extensions-builtin/sdnext-kanvas/src/Kanvas.ts
loadFromURL?: (url: string) => unknown; // external
getKanvasData?: () => { kanvas: true; image: string | null; mask: string | null } | null; // extensions-builtin/sdnext-kanvas/javascript/kanvas.mjs
resizeStage?: (width: number, height: number) => void; // extensions-builtin/sdnext-kanvas/javascript/kanvas.mjs
// browser api
showDirectoryPicker: () => Promise<FileSystemDirectoryHandle>;
+13
View File
@@ -765,6 +765,18 @@ async function browseFolder() {
return null;
}
export function resolutionChange(ar: string, width: number, height: number) {
let desired = ar;
if (desired === 'AR') desired = '1:1';
try {
const [w, h] = desired.split(':').map((x) => parseInt(x));
if (w > h) height = Math.round(width * h / w);
else if (h > w) width = Math.round(height * w / h);
} catch { /**/ }
if (window.resizeStage) window.resizeStage(width, height); // notify kanvas
return [ar, width, height];
}
export async function reconnectUI() {
const t0 = performance.now();
const gallery = gradioApp().getElementById('txt2img_gallery');
@@ -834,6 +846,7 @@ window.recalculate_prompts_txt2img = recalculate_prompts_txt2img;
window.recalculate_prompts_img2img = recalculate_prompts_img2img;
window.recalculate_prompts_inpaint = recalculate_prompts_inpaint;
window.recalculate_prompts_control = recalculate_prompts_control;
window.resolutionChange = resolutionChange;
window.selectCheckpoint = selectCheckpoint;
window.selectVAE = selectVAE;
window.selectUNet = selectUNet;