mirror of
https://github.com/vladmandic/automatic
synced 2026-09-18 16:54:33 +02:00
+5
-4
@@ -1,11 +1,11 @@
|
||||
# Change Log for SD.Next
|
||||
|
||||
## Update for 2025-07-27
|
||||
## Update for 2025-07-28
|
||||
|
||||
### Highlights for 2025-07-27
|
||||
### Highlights for 2025-07-28
|
||||
|
||||
Feature highlights include:
|
||||
- **ModernUI** layout redesign which should make it more user friendly and easier to navigate plus several new UI themes!
|
||||
- **ModernUI** has quite some redesign which should make it more user friendly and easier to navigate plus several new UI themes!
|
||||
- New models [WanAI Wan 2.1](https://wan.video/) for text-to-image workflows, [FreePix F-Lite](https://huggingface.co/Freepik/F-Lite), [Bria 3.2](https://huggingface.co/briaai/BRIA-3.2), [bigASP 2.5](https://civitai.com/models/1789765?modelVersionId=2025412)
|
||||
- Redesigned [LTXVideo](https://vladmandic.github.io/sdnext-docs/Video) interface with support for general video models plus optimized [FramePack](https://vladmandic.github.io/sdnext-docs/FramePack) and [LTXVideo](https://vladmandic.github.io/sdnext-docs/LTX) support
|
||||
- Fully integrated nudity detection and optional censorship with [NudeNet](https://vladmandic.github.io/sdnext-docs/NudeNet)
|
||||
@@ -29,7 +29,7 @@ For details, see [ChangeLog](https://github.com/vladmandic/automatic/blob/master
|
||||
|
||||
[ReadMe](https://github.com/vladmandic/automatic/blob/master/README.md) | [ChangeLog](https://github.com/vladmandic/automatic/blob/master/CHANGELOG.md) | [Docs](https://vladmandic.github.io/sdnext-docs/) | [WiKi](https://github.com/vladmandic/automatic/wiki) | [Discord](https://discord.com/invite/sd-next-federal-batch-inspectors-1101998836328697867)
|
||||
|
||||
### Details for 2025-07-27
|
||||
### Details for 2025-07-28
|
||||
|
||||
- **License**
|
||||
- SD.Next [license](https://github.com/vladmandic/sdnext/blob/dev/LICENSE.txt) switched from **aGPL-v3.0** to **Apache-v2.0**
|
||||
@@ -127,6 +127,7 @@ For details, see [ChangeLog](https://github.com/vladmandic/automatic/blob/master
|
||||
see [docs](https://vladmandic.github.io/sdnext-docs/Detailer/) for more information
|
||||
- **Detailer** add option to merge multiple results from each detailer model
|
||||
for example, hands model can result in two hands each being processed separately or both hands can be merged into one composite job
|
||||
- **Control** auto-update width/height on image upload
|
||||
- **SDNQ**
|
||||
- use inference context during quantization
|
||||
- use static compile
|
||||
|
||||
Submodule extensions-builtin/sdnext-modernui updated: 06a28bef26...157bdcac33
@@ -39,9 +39,10 @@ class GalleryFolder extends HTMLElement {
|
||||
const style = document.createElement('style'); // silly but necessasry since we're inside shadowdom
|
||||
if (window.opts.theme_type === 'Modern') {
|
||||
style.textContent = `
|
||||
.gallery-folder { cursor: pointer; padding: 8px 6px 8px 6px; background-color: var(--sd-button-normal-color); border-radius: var(--sd-border-radius); }
|
||||
.gallery-folder { cursor: pointer; padding: 8px 6px 8px 6px; background-color: var(--sd-button-normal-color); border-radius: var(--sd-border-radius); text-align: left; min-width: 12em;}
|
||||
.gallery-folder:hover { background-color: var(--button-primary-background-fill-hover); }
|
||||
.gallery-folder-selected { background-color: var(--sd-button-selected-color); color: var(--sd-button-selected-text-color); }
|
||||
.gallery-folder-icon { font-size: 1.2em; color: var(--sd-button-icon-color); margin-right: 1em; filter: drop-shadow(1px 1px 2px black); float: left; }
|
||||
`;
|
||||
} else {
|
||||
style.textContent = `
|
||||
@@ -53,7 +54,7 @@ class GalleryFolder extends HTMLElement {
|
||||
this.shadow.appendChild(style);
|
||||
const div = document.createElement('div');
|
||||
div.className = 'gallery-folder';
|
||||
div.textContent = `\uf44a ${this.name}`;
|
||||
div.innerHTML = `<span class="gallery-folder-icon">\uf03e</span> ${this.name}`;
|
||||
div.addEventListener('click', () => {
|
||||
for (const folder of el.folders.children) {
|
||||
if (folder.name === this.name) folder.shadow.children[1].classList.add('gallery-folder-selected');
|
||||
|
||||
@@ -420,9 +420,9 @@ class YoloRestorer(Detailer):
|
||||
with gr.Row():
|
||||
classes = gr.Textbox(label="Detailer classes", placeholder="Classes", elem_id=f"{tab}_detailer_classes")
|
||||
with gr.Row():
|
||||
prompt = gr.Textbox(label="Detailer prompt", value='', placeholder='Detailer prompt', lines=2, elem_id=f"{tab}_detailer_prompt")
|
||||
prompt = gr.Textbox(label="Detailer prompt", value='', placeholder='detailer prompt or leave empty to use main prompt', lines=2, elem_id=f"{tab}_detailer_prompt")
|
||||
with gr.Row():
|
||||
negative = gr.Textbox(label="Detailer negative prompt", value='', placeholder='Detailer negative prompt', lines=2, elem_id=f"{tab}_detailer_negative")
|
||||
negative = gr.Textbox(label="Detailer negative prompt", value='', placeholder='detailer prompt or leave empty to use main prompt', lines=2, elem_id=f"{tab}_detailer_negative")
|
||||
with gr.Row():
|
||||
steps = gr.Slider(label="Detailer steps", elem_id=f"{tab}_detailer_steps", value=10, minimum=0, maximum=99, step=1)
|
||||
strength = gr.Slider(label="Detailer strength", elem_id=f"{tab}_detailer_strength", value=0.3, minimum=0, maximum=1, step=0.01)
|
||||
|
||||
@@ -554,13 +554,11 @@ def create_ui(_blocks: gr.Blocks=None):
|
||||
btn_negative_counter.click(fn=call_queue.wrap_queued_call(ui_common.update_token_counter), inputs=[negative], outputs=[negative_counter])
|
||||
btn_interrogate.click(fn=helpers.interrogate, inputs=[], outputs=[prompt])
|
||||
|
||||
select_fields = [input_mode, input_image, init_image, input_type, input_resize, input_inpaint, input_video, input_batch, input_folder]
|
||||
select_output = [output_tabs, preview_process, result_txt]
|
||||
select_dict = dict(
|
||||
fn=helpers.select_input,
|
||||
_js="controlInputMode",
|
||||
inputs=select_fields,
|
||||
outputs=select_output,
|
||||
inputs=[input_mode, input_image, init_image, input_type, input_resize, input_inpaint, input_video, input_batch, input_folder],
|
||||
outputs=[output_tabs, preview_process, result_txt, width_before, height_before],
|
||||
show_progress=True,
|
||||
queue=False,
|
||||
)
|
||||
|
||||
@@ -91,11 +91,12 @@ def select_input(input_mode, input_image, init_image, init_type, input_resize, i
|
||||
selected_input = input_folder
|
||||
else:
|
||||
selected_input = None
|
||||
size = [gr.update(), gr.update()]
|
||||
if selected_input is None:
|
||||
input_source = None
|
||||
busy = False
|
||||
# debug('Control input: none')
|
||||
return [gr.Tabs.update(), None, '']
|
||||
return [gr.Tabs.update(), None, ''] + size
|
||||
input_type = type(selected_input)
|
||||
input_mask = None
|
||||
status = 'Control input | Unknown'
|
||||
@@ -108,6 +109,7 @@ def select_input(input_mode, input_image, init_image, init_type, input_resize, i
|
||||
input_source = [selected_input]
|
||||
input_type = 'PIL.Image'
|
||||
status = f'Control input | Image | Size {selected_input.width}x{selected_input.height} | Mode {selected_input.mode}'
|
||||
size = [gr.update(value=selected_input.width), gr.update(value=selected_input.height)]
|
||||
res = [gr.Tabs.update(selected='out-gallery'), input_mask, status]
|
||||
elif isinstance(selected_input, dict): # inpaint -> dict image+mask
|
||||
input_mask = selected_input['mask']
|
||||
@@ -145,7 +147,7 @@ def select_input(input_mode, input_image, init_image, init_type, input_resize, i
|
||||
input_init = [init_image]
|
||||
debug_log(f'Control select input: type={input_type} source={input_source} init={input_init} mask={input_mask} mode={input_mode}')
|
||||
busy = False
|
||||
return res
|
||||
return res + size
|
||||
|
||||
|
||||
def copy_input(mode_from, mode_to, input_image, input_resize, input_inpaint):
|
||||
|
||||
@@ -41,6 +41,8 @@ def create_ui():
|
||||
interrupt.click(fn=lambda: shared.state.interrupt(), inputs=[], outputs=[])
|
||||
skip = gr.Button('Skip', elem_id=f"{id_part}_skip", variant='secondary')
|
||||
skip.click(fn=lambda: shared.state.skip(), inputs=[], outputs=[])
|
||||
pause = gr.Button('Pause', elem_id=f"{id_part}_pause")
|
||||
pause.click(fn=lambda: shared.state.pause(), _js='checkPaused', inputs=[], outputs=[])
|
||||
result_images, generation_info, html_info, html_info_formatted, html_log = ui_common.create_output_panel("extras")
|
||||
gr.HTML('File metadata')
|
||||
exif_info = gr.HTML(elem_id="pnginfo_html_info")
|
||||
|
||||
@@ -323,15 +323,15 @@ def create_hires_inputs(tab):
|
||||
with gr.Row(elem_id=f"{tab}_refiner_row1"):
|
||||
refiner_start = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label='Refiner start', value=0.0, elem_id=f"{tab}_refiner_start")
|
||||
refiner_steps = gr.Slider(minimum=0, maximum=99, step=1, label="Refiner steps", elem_id=f"{tab}_refiner_steps", value=20)
|
||||
refiner_prompt = gr.Textbox(value='', lines=2, label='Refine prompt', elem_id=f"{tab}_refiner_prompt", elem_classes=["prompt"])
|
||||
refiner_negative = gr.Textbox(value='', lines=2, label='Refine negative prompt', elem_id=f"{tab}_refiner_neg_prompt", elem_classes=["prompt"])
|
||||
refiner_prompt = gr.Textbox(value='', lines=2, label='Refine prompt', elem_id=f"{tab}_refiner_prompt", elem_classes=["prompt"], placeholder="refine prompt or leave empty to use main prompt")
|
||||
refiner_negative = gr.Textbox(value='', lines=2, label='Refine negative prompt', elem_id=f"{tab}_refiner_neg_prompt", elem_classes=["prompt"], placeholder="refine negative prompt or leave empty to use main prompt")
|
||||
return enable_hr, hr_sampler_index, denoising_strength, hr_resize_mode, hr_resize_context, hr_upscaler, hr_force, hr_second_pass_steps, hr_scale, hr_resize_x, hr_resize_y, refiner_steps, refiner_start, refiner_prompt, refiner_negative
|
||||
|
||||
|
||||
def create_resize_inputs(tab, images, accordion=True, latent=False, non_zero=True, prefix=''):
|
||||
dummy_component = gr.Number(visible=False, value=0)
|
||||
if len(prefix) > 0 and not prefix.startswith(' '):
|
||||
prefix = f' {prefix}'
|
||||
prefix = f' {prefix}' if prefix != 'before' else ''
|
||||
with gr.Accordion(open=False, label="Resize", elem_classes=["small-accordion"], elem_id=f"{tab}_resize_group") if accordion else gr.Group():
|
||||
with gr.Row():
|
||||
available_upscalers = [x.name for x in shared.sd_upscalers]
|
||||
@@ -357,8 +357,8 @@ def create_resize_inputs(tab, images, accordion=True, latent=False, non_zero=Tru
|
||||
with gr.Row(elem_id=f"{tab}_resize_row_fixed"):
|
||||
with gr.Column(elem_id=f"{tab}_column_fixed1", scale=6):
|
||||
suffix = '_resize' if tab != 'img2img' else ''
|
||||
width = gr.Slider(minimum=64 if non_zero else 0, maximum=8192, step=8, label=f"Width {prefix}" if non_zero else "Resize width", value=1024 if non_zero else 0, elem_id=f"{tab}{suffix}_width")
|
||||
height = gr.Slider(minimum=64 if non_zero else 0, maximum=8192, step=8, label=f"Height {prefix}" if non_zero else "Resize height", value=1024 if non_zero else 0, elem_id=f"{tab}{suffix}_height")
|
||||
width = gr.Slider(minimum=64 if non_zero else 0, maximum=8192, step=8, label=f"Width{prefix}" if non_zero else "Resize width", value=1024 if non_zero else 0, elem_id=f"{tab}{suffix}_width")
|
||||
height = gr.Slider(minimum=64 if non_zero else 0, maximum=8192, step=8, label=f"Height{prefix}" if non_zero else "Resize height", value=1024 if non_zero else 0, elem_id=f"{tab}{suffix}_height")
|
||||
with gr.Column(elem_id=f"{tab}_column_fixed2", scale=1):
|
||||
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"])
|
||||
@@ -370,7 +370,7 @@ def create_resize_inputs(tab, images, accordion=True, latent=False, non_zero=Tru
|
||||
el = tab.split('_')[0]
|
||||
detect_image_size_btn.click(fn=lambda w, h, _: (w or gr.update(), h or gr.update()), _js=f'currentImageResolution{el}', inputs=[dummy_component, dummy_component, dummy_component], outputs=[width, height], show_progress=False)
|
||||
with gr.Tab(label="Scale", id=1, elem_id=f"{tab}_scale_tab_scale") as tab_scale_by:
|
||||
scale_by = gr.Slider(minimum=0.05, maximum=8.0, step=0.05, label=f"Scale {prefix}" if non_zero else "Resize scale", value=1.0, elem_id=f"{tab}_scale")
|
||||
scale_by = gr.Slider(minimum=0.05, maximum=8.0, step=0.05, label=f"Scale{prefix}" if non_zero else "Resize scale", value=1.0, elem_id=f"{tab}_scale")
|
||||
if images is not None:
|
||||
for component in images:
|
||||
component.change(fn=lambda: None, _js="updateImg2imgResizeToTextAfterChangingImage", inputs=[], outputs=[], show_progress=False)
|
||||
|
||||
Reference in New Issue
Block a user