refactor: integrate sharpfin for high-quality image resize

Vendor sharpfin library (Apache 2.0) and add centralized wrapper
module (images_sharpfin.py) replacing torchvision tensor/PIL
conversion and resize operations throughout the codebase.

- Add modules/sharpfin/ vendored library with MKS2021, Lanczos3,
  Mitchell, Catmull-Rom kernels and optional Triton sparse acceleration
- Add modules/images_sharpfin.py wrapper with to_tensor(), to_pil(),
  pil_to_tensor(), normalize(), resize(), resize_tensor()
- Add resize_quality and resize_linearize_srgb settings
- Add MKS2021 and Lanczos3 upscaler entries
- Replace torchvision.transforms.functional imports across 18 files
- to_pil() auto-detects HWC/BHWC layout, adds .round() before uint8
- Sparse Triton path falls back to dense GPU on compilation failure
- Mixed-axis resize splits into two single-axis scale() calls
- Masks and non-sRGB data always use linearize=False
This commit is contained in:
CalamitousFelicitousness
2026-02-10 00:13:35 +00:00
committed by vladmandic
parent 2c4d0751d9
commit 76aa949a26
30 changed files with 2878 additions and 78 deletions
+7 -7
View File
@@ -14,7 +14,6 @@ from packaging import version
import PIL.Image
import numpy as np
import torch
import torchvision
from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTextModelWithProjection, CLIPTokenizer
from diffusers.image_processor import VaeImageProcessor
from diffusers.loaders import FromSingleFileMixin, LoraLoaderMixin, TextualInversionLoaderMixin
@@ -859,7 +858,8 @@ class StableDiffusionXLDiffImg2ImgPipeline(DiffusionPipeline, FromSingleFileMixi
# 4. Preprocess image
#image = self.image_processor.preprocess(image) #ideally we would have preprocess the image with diffusers, but for this POC we won't --- it throws a deprecated warning
map = torchvision.transforms.Resize(tuple(s // self.vae_scale_factor for s in original_image.shape[2:]),antialias=None)(map)
from modules import images_sharpfin
map = images_sharpfin.resize_tensor(map, tuple(s // self.vae_scale_factor for s in original_image.shape[2:]), linearize=False)
# 5. Prepare timesteps
def denoising_value_valid(dnv):
return type(denoising_end) == float and 0 < dnv < 1
@@ -1758,7 +1758,8 @@ class StableDiffusionDiffImg2ImgPipeline(DiffusionPipeline):
# 7. Prepare extra step kwargs.
extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)
map = torchvision.transforms.Resize(tuple(s // self.vae_scale_factor for s in image.shape[2:]),antialias=None)(map)
from modules import images_sharpfin
map = images_sharpfin.resize_tensor(map, tuple(s // self.vae_scale_factor for s in image.shape[2:]), linearize=False)
# 8. Denoising loop
num_warmup_steps = len(timesteps) - num_inference_steps * self.scheduler.order
@@ -1833,8 +1834,7 @@ class StableDiffusionDiffImg2ImgPipeline(DiffusionPipeline):
import gradio as gr
import diffusers
from PIL import Image, ImageEnhance, ImageOps # pylint: disable=reimported
from torchvision import transforms
from modules import errors, shared, devices, scripts_manager, processing, sd_models, images
from modules import errors, shared, devices, scripts_manager, processing, sd_models, images, images_sharpfin
detector = None
@@ -1888,9 +1888,9 @@ class Script(scripts_manager.Script):
else:
return None, None, None
image_mask = image_map.copy()
image_map = transforms.ToTensor()(image_map)
image_map = images_sharpfin.to_tensor(image_map)
image_map = image_map.to(devices.device)
image_init = 2 * transforms.ToTensor()(image_init) - 1
image_init = 2 * images_sharpfin.to_tensor(image_init) - 1
image_init = image_init.unsqueeze(0)
image_init = image_init.to(devices.device)
return image_init, image_map, image_mask