LayerUtility: ImageScaleRestore V2¶
Documentation¶
- Class name:
LayerUtility: ImageScaleRestore V2
- Category:
😺dzNodes/LayerUtility
- Output node:
False
This node is designed to adjust the scale of images and optionally their masks to a specified size or scale, using various interpolation methods. It can handle multiple images in a batch, ensuring that each image is resized according to the given parameters, including the option to scale by the longest side for uniformity across varying image dimensions. The node emphasizes flexibility in image processing tasks, allowing for detailed control over the resizing process.
Input types¶
Required¶
image
- The input image or images to be scaled. This parameter is crucial for defining the source images that will undergo resizing operations.
- Comfy dtype:
IMAGE
- Python dtype:
torch.Tensor or List[torch.Tensor]
scale
- The scale factor to apply to the image dimensions. It determines how much the image size should be increased or decreased.
- Comfy dtype:
FLOAT
- Python dtype:
float
method
- Specifies the interpolation method to use for resizing the images. This affects the quality and characteristics of the output image.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
scale_by
- Determines the criterion for scaling the image, such as by its longest side, shortest side, width, height, or total pixel count.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
scale_by_length
- Specifies the target length for the chosen scaling criterion, applicable when scaling by dimensions or total pixel count.
- Comfy dtype:
INT
- Python dtype:
int
Optional¶
mask
- An optional mask or masks associated with the image(s), which will be resized in tandem with the image.
- Comfy dtype:
MASK
- Python dtype:
torch.Tensor or List[torch.Tensor]
original_size
- An optional parameter specifying the target dimensions to resize the image to, overriding the scale factor.
- Comfy dtype:
BOX
- Python dtype:
Tuple[int, int]
Output types¶
image
- Comfy dtype:
IMAGE
- The resized images, adjusted according to the specified scale, dimensions, or method.
- Python dtype:
torch.Tensor
- Comfy dtype:
mask
- Comfy dtype:
MASK
- The resized masks corresponding to the input images, if masks were provided.
- Python dtype:
torch.Tensor
- Comfy dtype:
original_size
- Comfy dtype:
BOX
- The original dimensions of the input images before resizing.
- Python dtype:
Tuple[int, int]
- Comfy dtype:
width
- Comfy dtype:
INT
- The target width of the resized images.
- Python dtype:
int
- Comfy dtype:
height
- Comfy dtype:
INT
- The target height of the resized images.
- Python dtype:
int
- Comfy dtype:
Usage tips¶
- Infra type:
GPU
- Common nodes: unknown
Source code¶
class ImageScaleRestoreV2:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(self):
method_mode = ['lanczos', 'bicubic', 'hamming', 'bilinear', 'box', 'nearest']
scale_by_list = ['by_scale', 'longest', 'shortest', 'width', 'height', 'total_pixel(kilo pixel)']
return {
"required": {
"image": ("IMAGE", ), #
"scale": ("FLOAT", {"default": 1, "min": 0.01, "max": 100, "step": 0.01}),
"method": (method_mode,),
"scale_by": (scale_by_list,), # 是否按长边缩放
"scale_by_length": ("INT", {"default": 1024, "min": 4, "max": 99999999, "step": 1}),
},
"optional": {
"mask": ("MASK",), #
"original_size": ("BOX",),
}
}
RETURN_TYPES = ("IMAGE", "MASK", "BOX", "INT", "INT")
RETURN_NAMES = ("image", "mask", "original_size", "width", "height",)
FUNCTION = 'image_scale_restore'
CATEGORY = '😺dzNodes/LayerUtility'
def image_scale_restore(self, image, scale, method,
scale_by, scale_by_length,
mask = None, original_size = None
):
l_images = []
l_masks = []
ret_images = []
ret_masks = []
for l in image:
l_images.append(torch.unsqueeze(l, 0))
m = tensor2pil(l)
if m.mode == 'RGBA':
l_masks.append(m.split()[-1])
if mask is not None:
if mask.dim() == 2:
mask = torch.unsqueeze(mask, 0)
l_masks = []
for m in mask:
l_masks.append(tensor2pil(torch.unsqueeze(m, 0)).convert('L'))
max_batch = max(len(l_images), len(l_masks))
orig_width, orig_height = tensor2pil(l_images[0]).size
if original_size is not None:
target_width = original_size[0]
target_height = original_size[1]
else:
target_width = int(orig_width * scale)
target_height = int(orig_height * scale)
if scale_by == 'longest':
if orig_width > orig_height:
target_width = scale_by_length
target_height = int(target_width * orig_height / orig_width)
else:
target_height = scale_by_length
target_width = int(target_height * orig_width / orig_height)
if scale_by == 'shortest':
if orig_width < orig_height:
target_width = scale_by_length
target_height = int(target_width * orig_height / orig_width)
else:
target_height = scale_by_length
target_width = int(target_height * orig_width / orig_height)
if scale_by == 'width':
target_width = scale_by_length
target_height = int(target_width * orig_height / orig_width)
if scale_by == 'height':
target_height = scale_by_length
target_width = int(target_height * orig_width / orig_height)
if scale_by == 'total_pixel(kilo pixel)':
r = orig_width / orig_height
target_width = math.sqrt(r * scale_by_length * 1000)
target_height = target_width / r
target_width = int(target_width)
target_height = int(target_height)
if target_width < 4:
target_width = 4
if target_height < 4:
target_height = 4
resize_sampler = Image.LANCZOS
if method == "bicubic":
resize_sampler = Image.BICUBIC
elif method == "hamming":
resize_sampler = Image.HAMMING
elif method == "bilinear":
resize_sampler = Image.BILINEAR
elif method == "box":
resize_sampler = Image.BOX
elif method == "nearest":
resize_sampler = Image.NEAREST
for i in range(max_batch):
_image = l_images[i] if i < len(l_images) else l_images[-1]
_canvas = tensor2pil(_image).convert('RGB')
ret_image = _canvas.resize((target_width, target_height), resize_sampler)
ret_mask = Image.new('L', size=ret_image.size, color='white')
if mask is not None:
_mask = l_masks[i] if i < len(l_masks) else l_masks[-1]
ret_mask = _mask.resize((target_width, target_height), resize_sampler)
ret_images.append(pil2tensor(ret_image))
ret_masks.append(image2mask(ret_mask))
log(f"{NODE_NAME} Processed {len(ret_images)} image(s).", message_type='finish')
return (torch.cat(ret_images, dim=0), torch.cat(ret_masks, dim=0), [orig_width, orig_height], target_width, target_height,)