dikdimon commited on
Commit
8ab31fe
·
verified ·
1 Parent(s): 8e5f1f5

Update custom-hires-fix-mod-for-automatic1111-2.9.4/scripts/custom_hires_fix.py

Browse files
custom-hires-fix-mod-for-automatic1111-2.9.4/scripts/custom_hires_fix.py CHANGED
@@ -17,6 +17,8 @@ from modules import images, devices, prompt_parser, sd_models, extra_networks
17
 
18
  from logging_utils import logger
19
 
 
 
20
  # Ensure we call the upscaler path when resizing (A1111 compat)
21
  # --- Compatibility notes ---
22
  # Recommended runtime:
@@ -1190,7 +1192,9 @@ class CustomHiresFix(scripts.Script):
1190
 
1191
  # Try detect ControlNet (best-effort; path may vary across installs)
1192
  ext_candidates = [
 
1193
  "extensions.sd-webui-controlnet.scripts.external_code",
 
1194
  ]
1195
  self._cn_ext = None
1196
  for mod in ext_candidates:
@@ -1715,7 +1719,11 @@ class CustomHiresFix(scripts.Script):
1715
  # ---- Helpers ----
1716
  def _maybe_mp_resize(self, base_w, base_h, target_mp: float):
1717
  """Compute size from megapixels while keeping aspect ratio; quantize to multiple of 8."""
1718
- aspect = base_w / base_h if base_h else 1.0
 
 
 
 
1719
  total_px = max(0.01, target_mp) * 1_000_000.0
1720
  w_float = math.sqrt(total_px * aspect)
1721
  h_float = w_float / aspect
@@ -1723,6 +1731,7 @@ class CustomHiresFix(scripts.Script):
1723
  h = max(8, int(round(h_float / 8) * 8))
1724
  return w, h
1725
 
 
1726
  def _compute_denoise(self, base_key: str) -> float:
1727
  """
1728
  Returns clamped denoising strength in [0,1] as (config[base_key] + denoise_offset).
@@ -1804,9 +1813,10 @@ class CustomHiresFix(scripts.Script):
1804
 
1805
  def _cond_key(self, width, height, steps_for_cond, prompt: str, negative: str, clip_skip: int):
1806
  h = hashlib.sha256()
1807
- h.update((prompt or "").encode("utf-8"))
 
1808
  h.update(b"::")
1809
- h.update((negative or "").encode("utf-8"))
1810
  # NEW: учитываем семейство модели (SDXL/SD3) в ключе кэша
1811
  xl_flag = int(bool(self.config.get("sdxl_mode", False)) or self.is_sdxl)
1812
  key = f"{self._model_hash_for_cache()}|xl={xl_flag}|{width}x{height}|{steps_for_cond}|cs={clip_skip}|{h.hexdigest()}"
@@ -2401,7 +2411,13 @@ class CustomHiresFix(scripts.Script):
2401
  steps = min(steps, sfirst)
2402
  # NEW: LRU-кэш шума для первой стадии
2403
  try:
2404
- key_seed = (self.p.seeds[0] if getattr(self.p, "seeds", None) else getattr(self.p, "seed", None))
 
 
 
 
 
 
2405
  except Exception as e:
2406
  logger.warning(e)
2407
  key_seed = None
@@ -2615,7 +2631,12 @@ class CustomHiresFix(scripts.Script):
2615
  else:
2616
  # NEW: если размеры не совпали — попробуем кэш
2617
  try:
2618
- key_seed = (self.p.seeds[0] if getattr(self.p, "seeds", None) else getattr(self.p, "seed", None))
 
 
 
 
 
2619
  except Exception as e:
2620
  logger.warning(e)
2621
  key_seed = None
@@ -2639,7 +2660,12 @@ class CustomHiresFix(scripts.Script):
2639
  else:
2640
  # NEW: обычный путь — используем LRU-кэш
2641
  try:
2642
- key_seed = (self.p.seeds[0] if getattr(self.p, "seeds", None) else getattr(self.p, "seed", None))
 
 
 
 
 
2643
  except Exception as e:
2644
  logger.warning(e)
2645
  key_seed = None
@@ -2969,19 +2995,24 @@ class CustomHiresFix(scripts.Script):
2969
  def parse_infotext(infotext, params):
2970
  try:
2971
  block = params.get("Custom Hires Fix")
2972
- if block is None: # <-- было: if not block
2973
  return
2974
- # поддержка нового формата "json64:<base64(json)>", а также обратная совместимость
2975
- if isinstance(block, str) and block.startswith("json64:"):
2976
- data = json.loads(base64.b64decode(block[7:]).decode("utf-8"))
 
2977
  elif isinstance(block, str):
2978
- try:
2979
- data = json.loads(block) # сначала пробуем валидный JSON
2980
- except json.JSONDecodeError:
2981
- # фолбэк для старых строк с одинарными кавычками
2982
- data = json.loads(block.translate(QUOTE_SINGLE_TO_DOUBLE))
 
 
 
2983
  else:
2984
- data = block
 
2985
  params["Custom Hires Fix"] = data
2986
  scale = data.get("scale", 0)
2987
  scale_str = str(scale).lower()
@@ -3116,4 +3147,4 @@ except NameError:
3116
  _INFOTEXT_HOOK_REGISTERED = False
3117
  if not _INFOTEXT_HOOK_REGISTERED:
3118
  script_callbacks.on_infotext_pasted(parse_infotext)
3119
- _INFOTEXT_HOOK_REGISTERED = True
 
17
 
18
  from logging_utils import logger
19
 
20
+ _INFOTEXT_HOOK_REGISTERED = False # Guard for callback registration
21
+
22
  # Ensure we call the upscaler path when resizing (A1111 compat)
23
  # --- Compatibility notes ---
24
  # Recommended runtime:
 
1192
 
1193
  # Try detect ControlNet (best-effort; path may vary across installs)
1194
  ext_candidates = [
1195
+ "extensions.sd_webui_controlnet.scripts.external_code",
1196
  "extensions.sd-webui-controlnet.scripts.external_code",
1197
+ "extensions-builtin.sd-webui-controlnet.scripts.external_code",
1198
  ]
1199
  self._cn_ext = None
1200
  for mod in ext_candidates:
 
1719
  # ---- Helpers ----
1720
  def _maybe_mp_resize(self, base_w, base_h, target_mp: float):
1721
  """Compute size from megapixels while keeping aspect ratio; quantize to multiple of 8."""
1722
+ if base_h <= 0 or base_w <= 0:
1723
+ logger.warning(f"Invalid base dimensions: {base_w}x{base_h}")
1724
+ return 512, 512 # Safe fallback
1725
+
1726
+ aspect = base_w / base_h
1727
  total_px = max(0.01, target_mp) * 1_000_000.0
1728
  w_float = math.sqrt(total_px * aspect)
1729
  h_float = w_float / aspect
 
1731
  h = max(8, int(round(h_float / 8) * 8))
1732
  return w, h
1733
 
1734
+
1735
  def _compute_denoise(self, base_key: str) -> float:
1736
  """
1737
  Returns clamped denoising strength in [0,1] as (config[base_key] + denoise_offset).
 
1813
 
1814
  def _cond_key(self, width, height, steps_for_cond, prompt: str, negative: str, clip_skip: int):
1815
  h = hashlib.sha256()
1816
+ # Безопасная обработка None
1817
+ h.update((prompt or "").encode("utf-8", errors="replace"))
1818
  h.update(b"::")
1819
+ h.update((negative or "").encode("utf-8", errors="replace"))
1820
  # NEW: учитываем семейство модели (SDXL/SD3) в ключе кэша
1821
  xl_flag = int(bool(self.config.get("sdxl_mode", False)) or self.is_sdxl)
1822
  key = f"{self._model_hash_for_cache()}|xl={xl_flag}|{width}x{height}|{steps_for_cond}|cs={clip_skip}|{h.hexdigest()}"
 
2411
  steps = min(steps, sfirst)
2412
  # NEW: LRU-кэш шума для первой стадии
2413
  try:
2414
+ try:
2415
+ seeds = getattr(self.p, "seeds", None)
2416
+ key_seed = seeds[0] if (seeds and len(seeds) > 0) else getattr(self.p, "seed", None)
2417
+ except (IndexError, TypeError, AttributeError) as e:
2418
+ logger.warning(f"Seed extraction warning: {e}")
2419
+ key_seed = None
2420
+
2421
  except Exception as e:
2422
  logger.warning(e)
2423
  key_seed = None
 
2631
  else:
2632
  # NEW: если размеры не совпали — попробуем кэш
2633
  try:
2634
+ try:
2635
+ seeds = getattr(self.p, "seeds", None)
2636
+ key_seed = seeds[0] if (seeds and len(seeds) > 0) else getattr(self.p, "seed", None)
2637
+ except (IndexError, TypeError, AttributeError) as e:
2638
+ logger.warning(f"Seed extraction warning: {e}")
2639
+ key_seed = None
2640
  except Exception as e:
2641
  logger.warning(e)
2642
  key_seed = None
 
2660
  else:
2661
  # NEW: обычный путь — используем LRU-кэш
2662
  try:
2663
+ try:
2664
+ seeds = getattr(self.p, "seeds", None)
2665
+ key_seed = seeds[0] if (seeds and len(seeds) > 0) else getattr(self.p, "seed", None)
2666
+ except (IndexError, TypeError, AttributeError) as e:
2667
+ logger.warning(f"Seed extraction warning: {e}")
2668
+ key_seed = None
2669
  except Exception as e:
2670
  logger.warning(e)
2671
  key_seed = None
 
2995
  def parse_infotext(infotext, params):
2996
  try:
2997
  block = params.get("Custom Hires Fix")
2998
+ if block is None:
2999
  return
3000
+
3001
+ # Парсинг с явной обработкой форматов
3002
+ if isinstance(block, dict):
3003
+ data = block
3004
  elif isinstance(block, str):
3005
+ if block.startswith("json64:"):
3006
+ data = json.loads(base64.b64decode(block[7:]).decode("utf-8"))
3007
+ else:
3008
+ try:
3009
+ data = json.loads(block)
3010
+ except json.JSONDecodeError:
3011
+ # Fallback для старых строк с одинарными кавычками
3012
+ data = json.loads(block.translate(QUOTE_SINGLE_TO_DOUBLE))
3013
  else:
3014
+ logger.warning(f"Unexpected infotext type: {type(block)}")
3015
+ return
3016
  params["Custom Hires Fix"] = data
3017
  scale = data.get("scale", 0)
3018
  scale_str = str(scale).lower()
 
3147
  _INFOTEXT_HOOK_REGISTERED = False
3148
  if not _INFOTEXT_HOOK_REGISTERED:
3149
  script_callbacks.on_infotext_pasted(parse_infotext)
3150
+ _INFOTEXT_HOOK_REGISTERED = True