Files
yolain-ComfyUI-Easy-Use/py/image.py
T

195 lines
5.1 KiB
Python

from PIL import Image
import numpy as np
from nodes import MAX_RESOLUTION
from .log import log_node_info
def get_new_bounds(width, height, left, right, top, bottom):
"""Returns the new bounds for an image with inset crop data."""
left = 0 + left
right = width - right
top = 0 + top
bottom = height - bottom
return (left, right, top, bottom)
# Tensor to PIL
def tensor2pil(image):
return Image.fromarray(np.clip(255. * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8))
# 图像裁切
class imageInsetCrop:
@classmethod
def INPUT_TYPES(cls): # pylint: disable = invalid-name, missing-function-docstring
return {
"required": {
"image": ("IMAGE",),
"measurement": (['Pixels', 'Percentage'],),
"left": ("INT", {
"default": 0,
"min": 0,
"max": MAX_RESOLUTION,
"step": 8
}),
"right": ("INT", {
"default": 0,
"min": 0,
"max": MAX_RESOLUTION,
"step": 8
}),
"top": ("INT", {
"default": 0,
"min": 0,
"max": MAX_RESOLUTION,
"step": 8
}),
"bottom": ("INT", {
"default": 0,
"min": 0,
"max": MAX_RESOLUTION,
"step": 8
}),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "crop"
CATEGORY = "EasyUse/Image"
# pylint: disable = too-many-arguments
def crop(self, measurement, left, right, top, bottom, image=None):
"""Does the crop."""
_, height, width, _ = image.shape
if measurement == 'Percentage':
left = int(width - (width * (100 - left) / 100))
right = int(width - (width * (100 - right) / 100))
top = int(height - (height * (100 - top) / 100))
bottom = int(height - (height * (100 - bottom) / 100))
# Snap to 8 pixels
left = left // 8 * 8
right = right // 8 * 8
top = top // 8 * 8
bottom = bottom // 8 * 8
if left == 0 and right == 0 and bottom == 0 and top == 0:
return (image,)
inset_left, inset_right, inset_top, inset_bottom = get_new_bounds(width, height, left, right,
top, bottom)
if inset_top > inset_bottom:
raise ValueError(
f"Invalid cropping dimensions top ({inset_top}) exceeds bottom ({inset_bottom})")
if inset_left > inset_right:
raise ValueError(
f"Invalid cropping dimensions left ({inset_left}) exceeds right ({inset_right})")
log_node_info("Image Inset Crop", f'Cropping image {width}x{height} width inset by {inset_left},{inset_right}, ' +
f'and height inset by {inset_top}, {inset_bottom}')
image = image[:, inset_top:inset_bottom, inset_left:inset_right, :]
return (image,)
# 图像尺寸
class imageSize:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"image": ("IMAGE",),
}
}
RETURN_TYPES = ("INT", "INT")
RETURN_NAMES = ("width_int", "height_int")
FUNCTION = "image_width_height"
CATEGORY = "EasyUse/Image"
def image_width_height(self, image):
image = tensor2pil(image)
if image.size:
result = (image.size[0], image.size[1])
else:
result = (0, 0)
return {"ui": {"text": "Width: "+str(result[0])+" , Height: "+str(result[1])}, "result": result}
# 图像尺寸(最长边)
class imageSizeBySide:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"image": ("IMAGE",),
"side": (["Longest", "Shortest"],)
}
}
RETURN_TYPES = ("INT",)
RETURN_NAMES = ("resolution",)
FUNCTION = "image_side"
CATEGORY = "EasyUse/Image"
def image_side(self, image, side):
image = tensor2pil(image)
if image.size:
if side == "Longest":
result = (image.size[0],) if image.size[0] > image.size[1] else (image.size[1],)
elif side == 'Shortest':
result = (image.size[0],) if image.size[0] < image.size[1] else (image.size[1],)
else:
result = (0,)
return {"ui": {"text": str(result[0])}, "result": result}
# 图像尺寸(最长边)
class imageSizeByLongerSide:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"image": ("IMAGE",),
}
}
RETURN_TYPES = ("INT",)
RETURN_NAMES = ("resolution",)
FUNCTION = "image_longer_side"
CATEGORY = "EasyUse/Image"
def image_longer_side(self, image):
image = tensor2pil(image)
if image.size:
if image.size[0] > image.size[1]:
result = (image.size[0],)
else:
result = (image.size[1],)
else:
result = (0,)
return {"ui": {"text": str(result[0])}, "result": result}
NODE_CLASS_MAPPINGS = {
"easy imageInsetCrop": imageInsetCrop,
"easy imageSize": imageSize,
"easy imageSizeBySide": imageSizeBySide,
"easy imageSizeByLongerSide": imageSizeByLongerSide
}
NODE_DISPLAY_NAME_MAPPINGS = {
"easy imageInsetCrop": "ImageInsetCrop",
"easy imageSize": "ImageSize",
"easy imageSizeBySide": "ImageSize (Side)",
"easy imageSizeByLongerSide": "ImageSize (LongerSide)"
}