diff --git a/modules/api/docs.py b/modules/api/docs.py index f61042e26..f384a1328 100644 --- a/modules/api/docs.py +++ b/modules/api/docs.py @@ -90,7 +90,3 @@ def create_redocs(app: FastAPI): redoc_favicon_url='/file=html/favicon.svg', ) return res - -""" -https://github.com/Amoenus/SwaggerDark/blob/master/SwaggerDark.css -""" \ No newline at end of file diff --git a/modules/api/helpers.py b/modules/api/helpers.py index 1678a851e..f13047b9b 100644 --- a/modules/api/helpers.py +++ b/modules/api/helpers.py @@ -14,7 +14,7 @@ def validate_sampler_name(name): return name -def decode_base64_to_image(encoding): +def decode_base64_to_image(encoding, quiet=False): if encoding.startswith("data:image/"): encoding = encoding.split(";")[1].split(",")[1] try: @@ -22,7 +22,10 @@ def decode_base64_to_image(encoding): return image except Exception as e: shared.log.warning(f'API cannot decode image: {e}') - raise HTTPException(status_code=500, detail="Invalid encoded image") from e + if not quiet: + raise HTTPException(status_code=500, detail="Invalid encoded image") from e + else: + return None def encode_pil_to_base64(image): diff --git a/modules/api/models.py b/modules/api/models.py index f5b89c2a9..4f01f47d5 100644 --- a/modules/api/models.py +++ b/modules/api/models.py @@ -194,8 +194,10 @@ ReqTxt2Img = PydanticModelGenerator( "StableDiffusionProcessingTxt2Img", StableDiffusionProcessingTxt2Img, [ - {"key": "sampler_index", "type": str, "default": "UniPC"}, - {"key": "script_name", "type": str, "default": None}, + {"key": "sampler_index", "type": int, "default": 0}, + {"key": "sampler_name", "type": str, "default": "UniPC"}, + {"key": "hr_sampler_name", "type": str, "default": "Same as primary"}, + {"key": "script_name", "type": str, "default": "none"}, {"key": "script_args", "type": list, "default": []}, {"key": "send_images", "type": bool, "default": True}, {"key": "save_images", "type": bool, "default": False}, @@ -216,7 +218,11 @@ ReqImg2Img = PydanticModelGenerator( "StableDiffusionProcessingImg2Img", StableDiffusionProcessingImg2Img, [ - {"key": "sampler_index", "type": str, "default": "UniPC"}, + {"key": "sampler_index", "type": int, "default": 0}, + {"key": "sampler_name", "type": str, "default": "UniPC"}, + {"key": "hr_sampler_name", "type": str, "default": "Same as primary"}, + {"key": "script_name", "type": str, "default": "none"}, + {"key": "script_args", "type": list, "default": []}, {"key": "init_images", "type": list, "default": None}, {"key": "denoising_strength", "type": float, "default": 0.5}, {"key": "mask", "type": str, "default": None}, diff --git a/modules/api/script.py b/modules/api/script.py index cae59791e..6ccaa161e 100644 --- a/modules/api/script.py +++ b/modules/api/script.py @@ -3,18 +3,25 @@ from fastapi.exceptions import HTTPException import gradio as gr from modules.api import models from modules import scripts +from modules.errors import log def script_name_to_index(name, scripts_list): + if name is None or len(name) == 0: + return None try: return [script.title().lower() for script in scripts_list].index(name.lower()) - except Exception as e: - raise HTTPException(status_code=422, detail=f"Script '{name}' not found") from e + except Exception: + log.error(f'API: script={name} not found') + return None + # raise HTTPException(status_code=422, detail=f"Script '{name}' not found") from e def get_selectable_script(script_name, script_runner): if script_name is None or script_name == "": return None, None script_idx = script_name_to_index(script_name, script_runner.selectable_scripts) + if script_idx is None: + return None, None script = script_runner.selectable_scripts[script_idx] return script, script_idx @@ -36,6 +43,8 @@ def get_script(script_name, script_runner): if script_name is None or script_name == "": return None, None script_idx = script_name_to_index(script_name, script_runner.scripts) + if script_idx is None: + return None return script_runner.scripts[script_idx] def init_default_script_args(script_runner): diff --git a/modules/processing_args.py b/modules/processing_args.py index 5b320f9ea..0a066ec6e 100644 --- a/modules/processing_args.py +++ b/modules/processing_args.py @@ -6,9 +6,11 @@ import time import inspect import torch import numpy as np +from PIL import Image from modules import shared, errors, sd_models, processing, processing_vae, processing_helpers, sd_hijack_hypertile, prompt_parser_diffusers, timer from modules.processing_callbacks import diffusers_callback_legacy, diffusers_callback, set_callbacks_p from modules.processing_helpers import resize_hires, fix_prompts, calculate_base_steps, calculate_hires_steps, calculate_refiner_steps, get_generator, set_latents, apply_circular # pylint: disable=unused-import +from modules.api import helpers debug = shared.log.trace if os.environ.get('SD_DIFFUSERS_DEBUG', None) is not None else lambda *args, **kwargs: None @@ -18,7 +20,8 @@ def task_specific_kwargs(p, model): task_args = {} is_img2img_model = bool('Zero123' in shared.sd_model.__class__.__name__) if len(getattr(p, 'init_images', [])) > 0: - p.init_images = [p.convert('RGB') for p in p.init_images] + p.init_images = [helpers.decode_base64_to_image(i, quiet=True) for i in p.init_images if isinstance(i, str)] + p.init_images = [i.convert('RGB') for i in p.init_images if isinstance(i, Image.Image)] if sd_models.get_diffusers_task(model) == sd_models.DiffusersTaskType.TEXT_2_IMAGE or len(getattr(p, 'init_images', [])) == 0 and not is_img2img_model: p.ops.append('txt2img') if hasattr(p, 'width') and hasattr(p, 'height'): diff --git a/modules/processing_class.py b/modules/processing_class.py index 9a5bc088c..c61fd7e8e 100644 --- a/modules/processing_class.py +++ b/modules/processing_class.py @@ -21,7 +21,7 @@ class StableDiffusionProcessing: sd_model=None, # pylint: disable=unused-argument # local instance of sd_model # base params prompt: str = "", - negative_prompt: str = None, + negative_prompt: str = "", seed: int = -1, subseed: int = -1, subseed_strength: float = 0, diff --git a/modules/processing_helpers.py b/modules/processing_helpers.py index ef83834e5..ec7fbf048 100644 --- a/modules/processing_helpers.py +++ b/modules/processing_helpers.py @@ -47,16 +47,23 @@ def apply_overlay(image: Image, paste_loc, index, overlays): return image debug(f'Apply overlay: image={image} loc={paste_loc} index={index} overlays={overlays}') overlay = overlays[index] - if paste_loc is not None: - x, y, w, h = paste_loc - if image.width != w or image.height != h or x != 0 or y != 0: - base_image = Image.new('RGBA', (overlay.width, overlay.height)) - image = images.resize_image(2, image, w, h) - base_image.paste(image, (x, y)) - image = base_image - image = image.convert('RGBA') - image.alpha_composite(overlay) - image = image.convert('RGB') + if not isinstance(image, Image.Image) or not isinstance(overlay, Image.Image): + return image + try: + if paste_loc is not None and (isinstance(paste_loc, tuple) or isinstance(paste_loc, list)): + x, y, w, h = paste_loc + if x is None or y is None or w is None or h is None: + return image + if image.width != w or image.height != h or x != 0 or y != 0: + base_image = Image.new('RGBA', (overlay.width, overlay.height)) + image = images.resize_image(2, image, w, h) + base_image.paste(image, (x, y)) + image = base_image + image = image.convert('RGBA') + image.alpha_composite(overlay) + image = image.convert('RGB') + except Exception as e: + shared.log.error(f'Apply overlay: {e}') return image