fix(processing): round init images to a pipeline-declared multiple

The init-image snap rounds to the VAE factor, but the LLaDA pipeline needs
16 for its transformer patch and 32 when editing, since the source image is
halved for the semantic encoder. The pipeline now declares patch_size for
the shared rounding and init_image_multiple for input images, and
get_vae_scale_factor honours the latter when an init image is present.
check_inputs reads the same attributes.
This commit is contained in:
CalamitousFelicitousness
2026-09-08 02:32:47 +01:00
parent 51320d0289
commit fa7243b239
5 changed files with 12 additions and 7 deletions
+1 -1
View File
@@ -444,7 +444,7 @@ def set_pipeline_args(p, model, prompts:list, negative_prompts:list, prompts_2:l
# handle missing resolution
if args.get('image', None) is not None and ('width' not in args or 'height' not in args):
if 'width' in possible and 'height' in possible:
vae_scale_factor = sd_vae.get_vae_scale_factor(model)
vae_scale_factor = sd_vae.get_vae_scale_factor(model, init_image=True)
if isinstance(args['image'], torch.Tensor) or isinstance(args['image'], np.ndarray):
if args['image'].shape[-1] == 3: # nhwc
args['width'] = args['image'].shape[-2]
+1 -1
View File
@@ -738,7 +738,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing):
def init(self, all_prompts=None, all_seeds=None, all_subseeds=None):
if self.init_images is not None and len(self.init_images) > 0:
vae_scale_factor = sd_vae.get_vae_scale_factor()
vae_scale_factor = sd_vae.get_vae_scale_factor(init_image=True)
if self.width is None or self.width == 0:
self.width = int(vae_scale_factor * (self.init_images[0].width * self.scale_by // vae_scale_factor))
if self.height is None or self.height == 0:
+1 -1
View File
@@ -395,7 +395,7 @@ def resize_init_images(p):
p.init_images = [p.image]
if getattr(p, 'init_images', None) is not None and len(p.init_images) > 0:
p.init_images = decode_images(p.init_images)
vae_scale_factor = sd_vae.get_vae_scale_factor()
vae_scale_factor = sd_vae.get_vae_scale_factor(init_image=True)
tgt_width = vae_scale_factor * math.ceil(p.init_images[0].width / vae_scale_factor)
tgt_height = vae_scale_factor * math.ceil(p.init_images[0].height / vae_scale_factor)
if p.init_images[0].size != (tgt_width, tgt_height):
+6 -3
View File
@@ -28,7 +28,7 @@ vae_scale_override = {
}
def get_vae_scale_factor(model: DiffusionPipeline | None = None):
def get_vae_scale_factor(model: DiffusionPipeline | None = None, init_image: bool = False):
if not shared.sd_loaded:
vae_scale_factor = 8
return vae_scale_factor
@@ -58,9 +58,12 @@ def get_vae_scale_factor(model: DiffusionPipeline | None = None):
patch_size = model.patch_size
if isinstance(patch_size, (tuple, list)): # 3d patch sizes are (t, h, w); spatial term is last
patch_size = patch_size[-1]
multiple = vae_scale_factor * patch_size
if init_image and model is not None and hasattr(model, 'init_image_multiple'): # a pipeline that downsamples its source image needs a larger multiple than its output
multiple = max(multiple, int(model.init_image_multiple))
if debug:
log.trace(f'VAE: cls={model.__class__.__name__ if model else "None"} scale={vae_scale_factor} patch={patch_size}')
return vae_scale_factor * patch_size
log.trace(f'VAE: cls={model.__class__.__name__ if model else "None"} scale={vae_scale_factor} patch={patch_size} multiple={multiple}')
return multiple
def load_vae_dict(filename: str):
+3 -1
View File
@@ -90,6 +90,8 @@ class LLaDAImagePipeline(DiffusionPipeline):
self.vae_scale_factor = 2 ** (len(self.vae.config.block_out_channels) - 1) if self.vae is not None else 8
self.latent_scale_factor = self.vae_scale_factor * 2
self.patch_size = 2 # transformer patch size, read by the host to round sizes to the latent multiple
self.init_image_multiple = self.latent_scale_factor * 2 # editing feeds a half-resolution copy of the source image to the semantic encoder
self.image_processor = VaeImageProcessor(vae_scale_factor=self.latent_scale_factor)
@classmethod
@@ -383,7 +385,7 @@ class LLaDAImagePipeline(DiffusionPipeline):
if generation_mode == "vq" and (height % 16 != 0 or width % 16 != 0):
raise ValueError("`height` and `width` must be divisible by 16 in VQ mode.")
required_multiple = self.latent_scale_factor * (2 if generation_mode == "editing" else 1)
required_multiple = self.init_image_multiple if generation_mode == "editing" else self.latent_scale_factor
if height <= 0 or width <= 0 or height % required_multiple != 0 or width % required_multiple != 0:
raise ValueError(f"`height` and `width` must be divisible by {required_multiple}.")
if num_inference_steps < 1: