Prepare Image Plus (JPS)¶
Documentation¶
- Class name:
Prepare Image Plus (JPS)
- Category:
JPS Nodes/Image
- Output node:
False
The Prepare Image Plus node is designed to configure and apply a set of image preparation settings, including resizing, cropping, padding, interpolation, sharpening, and flipping. It allows for detailed customization of how an image is processed before being used in further operations, ensuring that images are optimally prepared for tasks such as machine learning model input or visual presentation.
Input types¶
Required¶
image
- The primary image input for processing. This parameter is essential as it specifies the image to which all preparation settings will be applied.
- Comfy dtype:
IMAGE
- Python dtype:
torch.Tensor
target_w
- Specifies the target width for the image after resizing, affecting the final dimensions of the processed image.
- Comfy dtype:
INT
- Python dtype:
int
target_h
- Specifies the target height for the image after resizing, impacting the final dimensions of the processed image.
- Comfy dtype:
INT
- Python dtype:
int
offset_w
- Determines the horizontal offset applied to the image, which can adjust the image's position or alignment.
- Comfy dtype:
INT
- Python dtype:
int
offset_h
- Determines the vertical offset applied to the image, impacting the image's position or alignment vertically.
- Comfy dtype:
INT
- Python dtype:
int
crop_left
- Specifies the amount of cropping from the left side of the image, useful for removing unwanted edges or framing the subject.
- Comfy dtype:
INT
- Python dtype:
int
crop_right
- Specifies the amount of cropping from the right side of the image, aiding in framing the subject or removing extraneous parts.
- Comfy dtype:
INT
- Python dtype:
int
crop_top
- Determines the amount of cropping from the top of the image, which can help in adjusting the framing or focusing on specific parts of the image.
- Comfy dtype:
INT
- Python dtype:
int
crop_bottom
- Determines the amount of cropping from the bottom of the image, useful for framing or removing unnecessary parts.
- Comfy dtype:
INT
- Python dtype:
int
padding_left
- Specifies the amount of padding added to the left side of the image, which can be used for alignment or aesthetic purposes.
- Comfy dtype:
INT
- Python dtype:
int
padding_right
- Specifies the amount of padding added to the right side of the image, aiding in alignment or visual design.
- Comfy dtype:
INT
- Python dtype:
int
padding_top
- Determines the amount of padding added to the top of the image, which can be used for alignment or to achieve a specific visual effect.
- Comfy dtype:
INT
- Python dtype:
int
padding_bottom
- Determines the amount of padding added to the bottom of the image, useful for alignment or achieving a desired visual layout.
- Comfy dtype:
INT
- Python dtype:
int
interpolation
- Defines the method used for resizing the image, impacting the quality and appearance of the resized image.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
sharpening
- Specifies the level of sharpening applied to the image, enhancing edge definition and detail.
- Comfy dtype:
FLOAT
- Python dtype:
float
resize_type
- Determines the method of resizing applied to the image, such as stretching or cropping to fit the specified dimensions.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
flip
- Indicates whether the image should be flipped horizontally, vertically, or not at all, affecting the image's orientation.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
Output types¶
IMAGE
- Comfy dtype:
IMAGE
- The output is the image after applying the specified preparation settings, including resizing, cropping, padding, interpolation, sharpening, and flipping.
- Python dtype:
torch.Tensor
- Comfy dtype:
Usage tips¶
- Infra type:
CPU
- Common nodes: unknown
Source code¶
class Prepare_Image_Plus:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"image": ("IMAGE",),
"target_w": ("INT", { "default": 1024 , "min": 0, "step": 8, "display": "number" }),
"target_h": ("INT", { "default": 1024 , "min": 0, "step": 8, "display": "number" }),
"offset_w": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
"offset_h": ("INT", { "default": 0, "min": -99, "max": 99, "step": 1, "display": "number" }),
"crop_left": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
"crop_right": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
"crop_top": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
"crop_bottom": ("INT", { "default": 0, "min": 0, "max": 90, "step": 1, "display": "number" }),
"padding_left": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
"padding_right": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
"padding_top": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
"padding_bottom": ("INT", { "default": 0, "min": 0, "max": 500, "step": 1, "display": "number" }),
"interpolation": (["lanczos", "nearest", "bilinear", "bicubic", "area", "nearest-exact"],),
"sharpening": ("FLOAT", {"default": 0.0, "min": 0, "max": 1, "step": 0.05}),
"resize_type": (["Crop", "Stretch"],),
"flip": (["No", "X-Axis", "Y-Axis"],),
}
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("IMAGE",)
FUNCTION = "prepare_image"
CATEGORY = "JPS Nodes/Image"
def prepare_image(self, image, target_w, target_h, offset_w, offset_h, crop_left, crop_right, crop_top, crop_bottom, padding_left, padding_right, padding_top, padding_bottom,interpolation, sharpening,resize_type,flip):
_, input_h, input_w, _ = image.shape
dim = ()
if flip == "X-Axis":
dim += (2,)
image = torch.flip(image, dim)
if flip == "Y-Axis":
dim += (2,)
image = torch.flip(image, dim)
if crop_left + crop_right > 90:
crop_left = 90 / (crop_left + crop_right) * crop_left
crop_right = 90 / (crop_left + crop_right) * crop_right
if crop_top + crop_bottom > 90:
crop_top = 90 / (crop_top + crop_bottom) * crop_top
crop_bottom = 90 / (crop_top + crop_bottom) * crop_bottom
left = int(input_w-(input_w * (100-crop_left) / 100))
right = int(input_w-(input_w * (100-crop_right) / 100))
top = int(input_h-(input_h * (100-crop_top) / 100))
bottom = int(input_h-(input_h * (100-crop_bottom) / 100))
image = image[:, 0+top:input_h-bottom, 0+left:input_w-right, :]
input_h = input_h - top - bottom
input_w = input_w - left - right
left = int(((input_w * (100+padding_left) / 100) - input_w))
right = int(((input_w * (100+padding_right) / 100) - input_w))
top = int(((input_h * (100+padding_top) / 100) - input_h))
bottom = int(((input_h * (100+padding_bottom) / 100) - input_h))
pil_image = Image.fromarray(np.clip(255. * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8))
padded_image = Image.new("RGB", (pil_image.width + left + right, pil_image.height + top + bottom), color="black")
padded_image.paste(pil_image, (left, top))
image = torch.from_numpy(np.array(padded_image).astype(np.float32) / 255.0).unsqueeze(0)
input_h = input_h + top + bottom
input_w = input_w + left + right
if resize_type != "Stretch":
resize_needed_w = target_w / input_w
resize_needed_h = target_h / input_h
if resize_needed_w >= resize_needed_h:
min_zoom_factor = resize_needed_w
else:
min_zoom_factor = resize_needed_h
zoom_factor = min_zoom_factor
zoomed_w = round(input_w * zoom_factor)
zoomed_h = round(input_h * zoom_factor)
offset_w = int(zoomed_w / 100 * offset_w / 2)
offset_h = int(zoomed_h / 100 * offset_h / 2)
resized_image = image.permute([0,3,1,2])
if interpolation == "lanczos":
resized_image = comfy.utils.lanczos(resized_image, zoomed_w, zoomed_h)
else:
resized_image = F.interpolate(resized_image, size=(zoomed_h, zoomed_w), mode=interpolation)
resized_image = resized_image.permute([0,2,3,1])
x0 = round((zoomed_w - target_w) / 2)
x1 = round(x0 + target_w)
y0 = round((zoomed_h - target_h) / 2)
y1 = round(y0 + target_h)
if x0 + offset_w + target_w < zoomed_w and offset_w > 0:
x0 = x0 + offset_w
x1 = x0 + target_w
elif x0 + offset_w + target_w >= zoomed_w and offset_w > 0:
x0 = zoomed_w - target_w
x1 = zoomed_w
elif x0 + offset_w > 0 and offset_w < 0:
x0 = x0 + offset_w
x1 = x0 + target_w
elif x0 + offset_w <= 0 and offset_w < 0:
x0 = 0
x1 = target_w
if y0 + offset_h + target_h < zoomed_h and offset_h > 0:
y0 = y0 + offset_h
y1 = y0 + target_h
elif y0 + offset_h + target_h >= zoomed_h and offset_h > 0:
y0 = zoomed_h - target_h
y1 = zoomed_h
elif y0 + offset_h > 0 and offset_h < 0:
y0 = y0 + offset_h
y1 = y0 + target_h
elif y0 + offset_h <= 0 and offset_h < 0:
y0 = 0
y1 = target_h
output_image = resized_image
output_image = output_image[:, y0:y1, x0:x1, :]
else:
resized_image = image.permute([0,3,1,2])
if interpolation == "lanczos":
resized_image = comfy.utils.lanczos(resized_image, target_w, target_h)
else:
resized_image = F.interpolate(resized_image, size=(target_h, target_w), mode=interpolation)
resized_image = resized_image.permute([0,2,3,1])
output_image = resized_image
if sharpening > 0:
output_image = contrast_adaptive_sharpening(output_image, sharpening)
return(output_image,)