Skip to content

Commit 7f3ce06

Browse files
Merge pull request #15293 from light-and-ray/extras_upscaler_limit_target_resolution
Extras upscaler: option limit target resolution
2 parents 8bebfde + 203afa3 commit 7f3ce06

File tree

3 files changed

+48
-15
lines changed

3 files changed

+48
-15
lines changed

modules/postprocessing.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,14 @@ def run_postprocessing_webui(id_task, *args, **kwargs):
131131
return run_postprocessing(*args, **kwargs)
132132

133133

134-
def run_extras(extras_mode, resize_mode, image, image_folder, input_dir, output_dir, show_extras_results, gfpgan_visibility, codeformer_visibility, codeformer_weight, upscaling_resize, upscaling_resize_w, upscaling_resize_h, upscaling_crop, extras_upscaler_1, extras_upscaler_2, extras_upscaler_2_visibility, upscale_first: bool, save_output: bool = True):
134+
def run_extras(extras_mode, resize_mode, image, image_folder, input_dir, output_dir, show_extras_results, gfpgan_visibility, codeformer_visibility, codeformer_weight, upscaling_resize, upscaling_resize_w, upscaling_resize_h, upscaling_crop, extras_upscaler_1, extras_upscaler_2, extras_upscaler_2_visibility, upscale_first: bool, save_output: bool = True, limit_target_resolution = 0):
135135
"""old handler for API"""
136136

137137
args = scripts.scripts_postproc.create_args_for_run({
138138
"Upscale": {
139139
"upscale_mode": resize_mode,
140140
"upscale_by": upscaling_resize,
141+
"limit_target_resolution": limit_target_resolution,
141142
"upscale_to_width": upscaling_resize_w,
142143
"upscale_to_height": upscaling_resize_h,
143144
"upscale_crop": upscaling_crop,

modules/shared_options.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
"DAT_tile_overlap": OptionInfo(8, "Tile overlap for DAT upscalers.", gr.Slider, {"minimum": 0, "maximum": 48, "step": 1}).info("Low values = visible seam"),
103103
"upscaler_for_img2img": OptionInfo(None, "Upscaler for img2img", gr.Dropdown, lambda: {"choices": [x.name for x in shared.sd_upscalers]}),
104104
"set_scale_by_when_changing_upscaler": OptionInfo(False, "Automatically set the Scale by factor based on the name of the selected Upscaler."),
105+
"show_limit_target_resolution_in_extras_upscale": OptionInfo(False, 'Show "Limit target resolution" slider in "Upscale" extras script. Useful for batches where can be big images.').needs_reload_ui(),
105106
}))
106107

107108
options_templates.update(options_section(('face-restoration', "Face restoration", "postprocessing"), {

scripts/postprocessing_upscale.py

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@
1212
upscale_cache = {}
1313

1414

15+
def limitSizeByOneDemention(size: tuple, limit: int):
16+
w, h = size
17+
if h > w:
18+
if h > limit:
19+
w = limit / h * w
20+
h = limit
21+
else:
22+
if w > limit:
23+
h = limit / w * h
24+
w = limit
25+
return (int(w), int(h))
26+
27+
1528
class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
1629
name = "Upscale"
1730
order = 1000
@@ -31,6 +44,11 @@ def ui(self):
3144
with gr.Tabs(elem_id="extras_resize_mode"):
3245
with gr.TabItem('Scale by', elem_id="extras_scale_by_tab") as tab_scale_by:
3346
upscaling_resize = gr.Slider(minimum=1.0, maximum=8.0, step=0.05, label="Resize", value=4, elem_id="extras_upscaling_resize")
47+
if shared.opts.show_limit_target_resolution_in_extras_upscale:
48+
limit_target_resolution = gr.Slider(minimum=0, maximum=10000, step=8, label="Limit target resolution", value=8000, elem_id="extras_upscale_limit_target_resolution",
49+
tooltip="0 = no limit. Limit maximal target resolution by the biggest demension. Useful for batches where can be big images.")
50+
else:
51+
limit_target_resolution = gr.Number(0, visible=False)
3452

3553
with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to:
3654
with FormRow():
@@ -61,6 +79,7 @@ def on_selected_upscale_method(upscale_method):
6179
"upscale_enabled": upscale_enabled,
6280
"upscale_mode": selected_tab,
6381
"upscale_by": upscaling_resize,
82+
"limit_target_resolution": limit_target_resolution,
6483
"upscale_to_width": upscaling_resize_w,
6584
"upscale_to_height": upscaling_resize_h,
6685
"upscale_crop": upscaling_crop,
@@ -69,12 +88,18 @@ def on_selected_upscale_method(upscale_method):
6988
"upscaler_2_visibility": extras_upscaler_2_visibility,
7089
}
7190

72-
def upscale(self, image, info, upscaler, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop):
91+
def upscale(self, image, info, upscaler, upscale_mode, upscale_by, limit_target_resolution, upscale_to_width, upscale_to_height, upscale_crop):
7392
if upscale_mode == 1:
7493
upscale_by = max(upscale_to_width/image.width, upscale_to_height/image.height)
7594
info["Postprocess upscale to"] = f"{upscale_to_width}x{upscale_to_height}"
7695
else:
7796
info["Postprocess upscale by"] = upscale_by
97+
if limit_target_resolution != 0 and max(*image.size)*upscale_by > limit_target_resolution:
98+
upscale_mode = 1
99+
upscale_crop = False
100+
upscale_to_width, upscale_to_height = limitSizeByOneDemention((image.width*upscale_by, image.height*upscale_by), limit_target_resolution)
101+
upscale_by = max(upscale_to_width/image.width, upscale_to_height/image.height)
102+
info["Limit target resolution"] = limit_target_resolution
78103

79104
cache_key = (hash(np.array(image.getdata()).tobytes()), upscaler.name, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
80105
cached_image = upscale_cache.pop(cache_key, None)
@@ -96,18 +121,21 @@ def upscale(self, image, info, upscaler, upscale_mode, upscale_by, upscale_to_w
96121

97122
return image
98123

99-
def process_firstpass(self, pp: scripts_postprocessing.PostprocessedImage, upscale_enabled=True, upscale_mode=1, upscale_by=2.0, upscale_to_width=None, upscale_to_height=None, upscale_crop=False, upscaler_1_name=None, upscaler_2_name=None, upscaler_2_visibility=0.0):
100-
if upscale_mode == 1:
101-
pp.shared.target_width = upscale_to_width
102-
pp.shared.target_height = upscale_to_height
124+
def process_firstpass(self, pp: scripts_postprocessing.PostprocessedImage, **args):
125+
if args['upscale_mode'] == 1:
126+
pp.shared.target_width = args['upscale_to_width']
127+
pp.shared.target_height = args['upscale_to_height']
103128
else:
104-
pp.shared.target_width = int(pp.image.width * upscale_by)
105-
pp.shared.target_height = int(pp.image.height * upscale_by)
129+
pp.shared.target_width = int(pp.image.width * args['upscale_by'])
130+
pp.shared.target_height = int(pp.image.height * args['upscale_by'])
131+
if args['limit_target_resolution'] != 0:
132+
pp.shared.target_width, pp.shared.target_height = limitSizeByOneDemention((pp.shared.target_width, pp.shared.target_height), args['limit_target_resolution'])
106133

107-
def process(self, pp: scripts_postprocessing.PostprocessedImage, upscale_enabled=True, upscale_mode=1, upscale_by=2.0, upscale_to_width=None, upscale_to_height=None, upscale_crop=False, upscaler_1_name=None, upscaler_2_name=None, upscaler_2_visibility=0.0):
108-
if not upscale_enabled:
134+
def process(self, pp: scripts_postprocessing.PostprocessedImage, **args):
135+
if not args['upscale_enabled']:
109136
return
110137

138+
upscaler_1_name = args['upscaler_1_name']
111139
if upscaler_1_name == "None":
112140
upscaler_1_name = None
113141

@@ -117,18 +145,21 @@ def process(self, pp: scripts_postprocessing.PostprocessedImage, upscale_enabled
117145
if not upscaler1:
118146
return
119147

148+
upscaler_2_name = args['upscaler_2_name']
120149
if upscaler_2_name == "None":
121150
upscaler_2_name = None
122151

123152
upscaler2 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_2_name and x.name != "None"]), None)
124153
assert upscaler2 or (upscaler_2_name is None), f'could not find upscaler named {upscaler_2_name}'
125154

126-
upscaled_image = self.upscale(pp.image, pp.info, upscaler1, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
155+
upscaled_image = self.upscale(pp.image, pp.info, upscaler1, args['upscale_mode'], args['upscale_by'], args['limit_target_resolution'], args['upscale_to_width'],
156+
args['upscale_to_height'], args['upscale_crop'])
127157
pp.info["Postprocess upscaler"] = upscaler1.name
128158

129-
if upscaler2 and upscaler_2_visibility > 0:
130-
second_upscale = self.upscale(pp.image, pp.info, upscaler2, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop)
131-
upscaled_image = Image.blend(upscaled_image, second_upscale, upscaler_2_visibility)
159+
if upscaler2 and args['upscaler_2_visibility'] > 0:
160+
second_upscale = self.upscale(pp.image, pp.info, upscaler2, args['upscale_mode'], args['upscale_by'], args['upscale_to_width'],
161+
args['upscale_to_height'], args['upscale_crop'])
162+
upscaled_image = Image.blend(upscaled_image, second_upscale, args['upscaler_2_visibility'])
132163

133164
pp.info["Postprocess upscaler 2"] = upscaler2.name
134165

@@ -163,5 +194,5 @@ def process(self, pp: scripts_postprocessing.PostprocessedImage, upscale_by=2.0,
163194
upscaler1 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_name]), None)
164195
assert upscaler1, f'could not find upscaler named {upscaler_name}'
165196

166-
pp.image = self.upscale(pp.image, pp.info, upscaler1, 0, upscale_by, 0, 0, False)
197+
pp.image = self.upscale(pp.image, pp.info, upscaler1, 0, upscale_by, 0, 0, 0, False)
167198
pp.info["Postprocess upscaler"] = upscaler1.name

0 commit comments

Comments
 (0)