cleaned up defaults

vector nodes aligned for list output
vars complete
This commit is contained in:
Alexander G. Morano
2025-05-04 01:20:54 -04:00
parent 70ab1e942b
commit 558693fc8f
12 changed files with 262 additions and 214 deletions
+17 -17
View File
@@ -240,7 +240,7 @@ IMAGE and MASK will return a TRUE bit for any non-black pixel, as a stream of bi
return d
def run(self, **kw) -> tuple[List[int], List[bool]]:
value = parse_param(kw, "VALUE", EnumConvertType.ANY, [0])
value = parse_param(kw, "VALUE", EnumConvertType.ANY, 0)
bits = parse_param(kw, "BITS", EnumConvertType.INT, 8, 1, 64)
msb = parse_param(kw, "MSB", EnumConvertType.INT, False)
params = list(zip_longest_fill(value, bits))
@@ -312,11 +312,11 @@ Evaluates two inputs (A and B) with a specified comparison operators and optiona
return d
def run(self, **kw) -> tuple[Any, Any]:
A = parse_param(kw, "A", EnumConvertType.ANY, [0])
B = parse_param(kw, "B", EnumConvertType.ANY, [0])
A = parse_param(kw, "A", EnumConvertType.ANY, 0)
B = parse_param(kw, "B", EnumConvertType.ANY, 0)
size = max(len(A), len(B))
good = parse_param(kw, "PASS", EnumConvertType.ANY, [0])[:size]
fail = parse_param(kw, "FAIL", EnumConvertType.ANY, [0])[:size]
good = parse_param(kw, "PASS", EnumConvertType.ANY, 0)[:size]
fail = parse_param(kw, "FAIL", EnumConvertType.ANY, 0)[:size]
op = parse_param(kw, "COMPARE", EnumComparison, EnumComparison.EQUAL.name)[:size]
flip = parse_param(kw, "FLIP", EnumConvertType.BOOLEAN, False)[:size]
invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False)[:size]
@@ -453,11 +453,11 @@ Additionally, you can specify the easing function (EASE) and the desired output
return d
def run(self, **kw) -> tuple[Any, Any]:
A = parse_param(kw, "A", EnumConvertType.ANY, [0])
B = parse_param(kw, "B", EnumConvertType.ANY, [0])
a_xyzw = parse_param(kw, "AA", EnumConvertType.VEC4, [(0, 0, 0, 0)])
b_xyzw = parse_param(kw, "BB", EnumConvertType.VEC4, [(1, 1, 1, 1)])
alpha = parse_param(kw, "FLOAT",EnumConvertType.VEC4, [(0.5,0.5,0.5,0.5)], 0, 1)
A = parse_param(kw, "A", EnumConvertType.ANY, 0)
B = parse_param(kw, "B", EnumConvertType.ANY, 0)
a_xyzw = parse_param(kw, "AA", EnumConvertType.VEC4, (0, 0, 0, 0))
b_xyzw = parse_param(kw, "BB", EnumConvertType.VEC4, (1, 1, 1, 1))
alpha = parse_param(kw, "FLOAT",EnumConvertType.VEC4, (0.5,0.5,0.5,0.5), 0, 1)
op = parse_param(kw, "EASE", EnumEase, EnumEase.SIN_IN_OUT.name)
typ = parse_param(kw, "TYPE", EnumNumberType, EnumNumberType.FLOAT.name)
values = []
@@ -533,7 +533,7 @@ Perform single function operations like absolute value, mean, median, mode, magn
def run(self, **kw) -> tuple[bool]:
results = []
A = parse_param(kw, "A", EnumConvertType.ANY, [0])
A = parse_param(kw, "A", EnumConvertType.ANY, 0)
op = parse_param(kw, "FUNCTION", EnumUnaryOperation, EnumUnaryOperation.ABS.name)
params = list(zip_longest_fill(A, op))
pbar = ProgressBar(len(params))
@@ -658,8 +658,8 @@ Execute binary operations like addition, subtraction, multiplication, division,
results = []
A = parse_param(kw, "A", EnumConvertType.ANY, None)
B = parse_param(kw, "B", EnumConvertType.ANY, None)
a_xyzw = parse_param(kw, "AA", EnumConvertType.VEC4, [(0, 0, 0, 0)])
b_xyzw = parse_param(kw, "BB", EnumConvertType.VEC4, [(0, 0, 0, 0)])
a_xyzw = parse_param(kw, "AA", EnumConvertType.VEC4, (0, 0, 0, 0))
b_xyzw = parse_param(kw, "BB", EnumConvertType.VEC4, (0, 0, 0, 0))
op = parse_param(kw, "FUNCTION", EnumBinaryOperation, EnumBinaryOperation.ADD.name)
typ = parse_param(kw, "TYPE", EnumConvertType, EnumConvertType.FLOAT.name)
flip = parse_param(kw, "FLIP", EnumConvertType.BOOLEAN, False)
@@ -796,7 +796,7 @@ Manipulate strings through filtering
def run(self, **kw) -> tuple[TensorType, ...]:
# turn any all inputs into the
data_list = parse_dynamic(kw, "❔", EnumConvertType.ANY, [""])
data_list = parse_dynamic(kw, "❔", EnumConvertType.ANY, "")
if data_list is None:
logger.warn("no data for list")
return ([],)
@@ -806,7 +806,7 @@ Manipulate strings through filtering
op = parse_param(kw, "FUNCTION", EnumConvertString, EnumConvertString.SPLIT.name)[0]
key = parse_param(kw, "KEY", EnumConvertType.STRING, "")[0]
replace = parse_param(kw, "REPLACE", EnumConvertType.STRING, "")[0]
stenst = parse_param(kw, "RANGE", EnumConvertType.VEC3INT, [(0, -1, 1)])[0]
stenst = parse_param(kw, "RANGE", EnumConvertType.VEC3INT, (0, -1, 1))[0]
results = []
match op:
case EnumConvertString.SPLIT:
@@ -881,8 +881,8 @@ Swap components between two vectors based on specified swizzle patterns and valu
return d
def run(self, **kw) -> tuple[TensorType, ...]:
pA = parse_param(kw, "A", EnumConvertType.VEC4, [(0,0,0,0)])
pB = parse_param(kw, "B", EnumConvertType.VEC4, [(0,0,0,0)])
pA = parse_param(kw, "A", EnumConvertType.VEC4, (0,0,0,0))
pB = parse_param(kw, "B", EnumConvertType.VEC4, (0,0,0,0))
swap_x = parse_param(kw, "SWAP_X", EnumSwizzle, EnumSwizzle.A_X.name)
swap_y = parse_param(kw, "SWAP_Y", EnumSwizzle, EnumSwizzle.A_Y.name)
swap_z = parse_param(kw, "SWAP_Z", EnumSwizzle, EnumSwizzle.A_W.name)
+24 -15
View File
@@ -118,10 +118,10 @@ Adjust the color scheme of one image to match another with the Color Match Node.
d = super().INPUT_TYPES()
d = deep_merge(d, {
"optional": {
"IMAGE_A": (COZY_TYPE_IMAGE, {
"SOURCE": (COZY_TYPE_IMAGE, {
"tooltip": "Pixel Data (RGBA, RGB or Grayscale)"
}),
"IMAGE_B": (COZY_TYPE_IMAGE, {
"TARGET": (COZY_TYPE_IMAGE, {
"tooltip": "Pixel Data (RGBA, RGB or Grayscale)"
}),
"MODE": (EnumColorMatchMode._member_names_, {
@@ -136,25 +136,32 @@ Adjust the color scheme of one image to match another with the Color Match Node.
"default": EnumColorMap.HSV.name,
"tooltip": "One of two dozen CV2 Built-in Colormap LUT (Look Up Table) Presets"
}),
"VAL": ("INT", {"default": 255, "min": 0, "max": 255, "tooltip":"The number of colors to use from the LUT during the remap. Will quantize the LUT range."}),
"FLIP": ("BOOLEAN", {"default": False}),
"INVERT": ("BOOLEAN", {"default": False,
"tooltip": "Invert the color match output"}),
"MATTE": ("VEC4INT", {"default": (0, 0, 0, 255), "rgb": True}),
"VAL": ("INT", {
"default": 255, "min": 0, "max": 255,
"tooltip":"The number of colors to use from the LUT during the remap. Will quantize the LUT range."}),
"FLIP": ("BOOLEAN", {
"default": False,
"tooltip": "Flip the SOURCE and TARGET inputs"}),
"INVERT": ("BOOLEAN", {
"default": False,
"tooltip": "Invert the color match output"}),
"MATTE": ("VEC4", {
"default": (0, 0, 0, 255), "rgb": True,
"tooltip": "Background Color"}),
}
})
return d
def run(self, **kw) -> RGBAMaskType:
pA = parse_param(kw, "IMAGE_A", EnumConvertType.IMAGE, None)
pB = parse_param(kw, "IMAGE_B", EnumConvertType.IMAGE, None)
pA = parse_param(kw, "SOURCE", EnumConvertType.IMAGE, None)
pB = parse_param(kw, "TARGET", EnumConvertType.IMAGE, None)
colormatch_mode = parse_param(kw, "MODE", EnumColorMatchMode, EnumColorMatchMode.REINHARD.name)
colormatch_map = parse_param(kw, f"MAP", EnumColorMatchMap, EnumColorMatchMap.USER_MAP.name)
colormap = parse_param(kw, "COLORMAP", EnumColorMap, EnumColorMap.HSV.name)
num_colors = parse_param(kw, "VAL", EnumConvertType.INT, 255)
flip = parse_param(kw, "FLIP", EnumConvertType.BOOLEAN, False)
invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4, [(0, 0, 0, 255)], 0, 255)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4, (0, 0, 0, 255), 0, 255)
params = list(zip_longest_fill(pA, pB, colormap, colormatch_mode, colormatch_map, num_colors, flip, invert, matte))
images = []
pbar = ProgressBar(len(params))
@@ -244,7 +251,7 @@ The top-k colors ordered from most->least used as a strip, tonal palette and 3D
kcolors = parse_param(kw, "VAL", EnumConvertType.INT, 12, 1, 255)
lut_height = parse_param(kw, "SIZE", EnumConvertType.INT, 32, 1, 256)
nodes = parse_param(kw, "COUNT", EnumConvertType.INT, 33, 1, 255)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(256, 256)], IMAGE_SIZE_MIN)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (256, 256), IMAGE_SIZE_MIN)
params = list(zip_longest_fill(pA, kcolors, nodes, lut_height, wihi))
top_colors = []
@@ -302,7 +309,8 @@ Users can customize the angle of separation for color calculations, offering fle
"default": 45, "min": -90, "max": 90,
"tooltip": "Custom angle of separation to use when calculating colors"
}),
"INVERT": ("BOOLEAN", {"default": False})
"INVERT": ("BOOLEAN", {
"default": False})
}
})
return d
@@ -362,7 +370,8 @@ The gradient image will be translated into a single row lookup table.
"tooltip": "Sampling method for resizing images"
}),
"MATTE": ("VEC4", {
"default": (0, 0, 0, 255), "rgb": True
"default": (0, 0, 0, 255), "rgb": True,
"tooltip": "Background Color"
})
}
})
@@ -373,9 +382,9 @@ The gradient image will be translated into a single row lookup table.
gradient = parse_param(kw, "GRADIENT", EnumConvertType.IMAGE, None)
flip = parse_param(kw, "FLIP", EnumConvertType.BOOLEAN, False)
mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(512, 512)], IMAGE_SIZE_MIN)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)
sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)
images = []
params = list(zip_longest_fill(pA, gradient, flip, mode, sample, wihi, matte))
pbar = ProgressBar(len(params))
+31 -26
View File
@@ -91,7 +91,8 @@ Advanced options include pixelation, quantization, and morphological operations
"GAMMA": ("FLOAT", {
"default": 1, "min": 0.00001, "max": 1, "step": 0.01}),
"MATTE": ("VEC4", {
"default": (0, 0, 0, 255), "rgb": True}),
"default": (0, 0, 0, 255), "rgb": True,
"tooltip": "Background Color"}),
"INVERT": ("BOOLEAN", {
"default": False,
"tooltip": "Invert the mask input"})
@@ -105,12 +106,12 @@ Advanced options include pixelation, quantization, and morphological operations
op = parse_param(kw, "FUNCTION", EnumAdjustOP, EnumAdjustOP.BLUR.name)
radius = parse_param(kw, "RADIUS", EnumConvertType.INT, 3, 3)
val = parse_param(kw, "VAL", EnumConvertType.FLOAT, 0, 0)
lohi = parse_param(kw, "LoHi", EnumConvertType.VEC2, [(0, 1)], 0, 1)
lmh = parse_param(kw, "LMH", EnumConvertType.VEC3, [(0, 0.5, 1)], 0, 1)
hsv = parse_param(kw, "HSV", EnumConvertType.VEC3, [(0, 1, 1)], 0, 1)
lohi = parse_param(kw, "LoHi", EnumConvertType.VEC2, (0, 1), 0, 1)
lmh = parse_param(kw, "LMH", EnumConvertType.VEC3, (0, 0.5, 1), 0, 1)
hsv = parse_param(kw, "HSV", EnumConvertType.VEC3, (0, 1, 1), 0, 1)
contrast = parse_param(kw, "CONTRAST", EnumConvertType.FLOAT, 1, 0, 1)
gamma = parse_param(kw, "GAMMA", EnumConvertType.FLOAT, 1, 0, 1)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)
invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False)
params = list(zip_longest_fill(pA, mask, op, radius, val, lohi,
lmh, hsv, contrast, gamma, matte, invert))
@@ -253,7 +254,8 @@ Combine two input images using various blending modes, such as normal, screen, m
"default": EnumInterpolation.LANCZOS4.name,
"tooltip": "Sampling method for resizing images"}),
"MATTE": ("VEC4", {
"default": (0, 0, 0, 255), "rgb": True})
"default": (0, 0, 0, 255), "rgb": True,
"tooltip": "Background Color"})
}
})
return d
@@ -266,9 +268,9 @@ Combine two input images using various blending modes, such as normal, screen, m
alpha = parse_param(kw, "ALPHA", EnumConvertType.FLOAT, 1, 0, 1)
flip = parse_param(kw, "FLIP", EnumConvertType.BOOLEAN, False)
mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(512, 512)], IMAGE_SIZE_MIN)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)
sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)
invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False)
params = list(zip_longest_fill(pA, pB, mask, func, alpha, flip, mode, wihi, sample, matte, invert))
images = []
@@ -333,7 +335,7 @@ Create masks based on specific color ranges within an image. Specify the color r
d = super().INPUT_TYPES()
d = deep_merge(d, {
"optional": {
"IMAGE_A": (COZY_TYPE_IMAGE, {
"IMAGE": (COZY_TYPE_IMAGE, {
"tooltip": "Pixel Data (RGBA, RGB or Grayscale)"
}),
"START": ("VEC3", {
@@ -347,18 +349,19 @@ Create masks based on specific color ranges within an image. Specify the color r
"default": (0.5,0.5,0.5), "mij":0, "maj":1,
"tooltip": "the fuzziness use to extend the start and end range(s)"}),
"MATTE": ("VEC4", {
"default": (0, 0, 0, 255), "rgb": True}),
"default": (0, 0, 0, 255), "rgb": True,
"tooltip": "Background Color"}),
}
})
return d
def run(self, **kw) -> RGBAMaskType:
pA = parse_param(kw, "IMAGE_A", EnumConvertType.IMAGE, None)
start = parse_param(kw, "START", EnumConvertType.VEC3INT, [(128,128,128)], 0, 255)
use_range = parse_param(kw, "RANGE", EnumConvertType.VEC3, [(0,0,0)], 0, 255)
end = parse_param(kw, "END", EnumConvertType.VEC3INT, [(128,128,128)], 0, 255)
fuzz = parse_param(kw, "FUZZ", EnumConvertType.VEC3, [(0.5,0.5,0.5)], 0, 1)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)
pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None)
start = parse_param(kw, "START", EnumConvertType.VEC3INT, (128,128,128), 0, 255)
use_range = parse_param(kw, "RANGE", EnumConvertType.BOOLEAN, False, 0, 255)
end = parse_param(kw, "END", EnumConvertType.VEC3INT, (128,128,128), 0, 255)
fuzz = parse_param(kw, "FUZZ", EnumConvertType.VEC3, (0.5,0.5,0.5), 0, 1)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)
params = list(zip_longest_fill(pA, start, use_range, end, fuzz, matte))
images = []
pbar = ProgressBar(len(params))
@@ -413,7 +416,8 @@ Combines individual color channels (red, green, blue) along with an optional mas
"default": EnumInterpolation.LANCZOS4.name,
"tooltip": "Sampling method for resizing images"}),
"MATTE": ("VEC4", {
"default": (0, 0, 0, 255), "rgb": True}),
"default": (0, 0, 0, 255), "rgb": True,
"tooltip": "Background Color"}),
"FLIP": ("VEC4", {
"default": (0,0,0,0), "mij":0, "maj":1,
"tooltip": "Invert specific input prior to merging. R, G, B, A."}),
@@ -431,10 +435,10 @@ Combines individual color channels (red, green, blue) along with an optional mas
B = parse_param(kw, "🟦", EnumConvertType.MASK, None)
A = parse_param(kw, "⬜", EnumConvertType.MASK, None)
mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(512, 512)], IMAGE_SIZE_MIN)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)
sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)
flip = parse_param(kw, "FLIP", EnumConvertType.VEC4, [(0, 0, 0, 0)], 0., 1.)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)
flip = parse_param(kw, "FLIP", EnumConvertType.VEC4, (0, 0, 0, 0), 0., 1.)
invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False)
params = list(zip_longest_fill(rgba, R, G, B, A, mode, wihi, sample, matte, flip, invert))
images = []
@@ -543,7 +547,8 @@ Swap pixel values between two input images based on specified channel swizzle op
"default": EnumPixelSwizzle.ALPHA_A.name,
"tooltip": "Replace input Alpha channel with target channel or constant"}),
"MATTE": ("VEC4", {
"default": (0, 0, 0, 255), "rgb": True})
"default": (0, 0, 0, 255), "rgb": True,
"tooltip": "Background Color"})
}
})
return d
@@ -551,11 +556,11 @@ Swap pixel values between two input images based on specified channel swizzle op
def run(self, **kw) -> RGBAMaskType:
pA = parse_param(kw, "IMAGE_A", EnumConvertType.IMAGE, None)
pB = parse_param(kw, "IMAGE_B", EnumConvertType.IMAGE, None)
swap_r = parse_param(kw, Lexicon.SWAP_R, EnumPixelSwizzle, EnumPixelSwizzle.RED_A.name)
swap_g = parse_param(kw, Lexicon.SWAP_G, EnumPixelSwizzle, EnumPixelSwizzle.GREEN_A.name)
swap_b = parse_param(kw, Lexicon.SWAP_B, EnumPixelSwizzle, EnumPixelSwizzle.BLUE_A.name)
swap_a = parse_param(kw, Lexicon.SWAP_A, EnumPixelSwizzle, EnumPixelSwizzle.ALPHA_A.name)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)
swap_r = parse_param(kw, "SWAP_R", EnumPixelSwizzle, EnumPixelSwizzle.RED_A.name)
swap_g = parse_param(kw, "SWAP_G", EnumPixelSwizzle, EnumPixelSwizzle.GREEN_A.name)
swap_b = parse_param(kw, "SWAP_B", EnumPixelSwizzle, EnumPixelSwizzle.BLUE_A.name)
swap_a = parse_param(kw, "SWAP_A", EnumPixelSwizzle, EnumPixelSwizzle.ALPHA_A.name)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)
params = list(zip_longest_fill(pA, pB, swap_r, swap_g, swap_b, swap_a, matte))
images = []
pbar = ProgressBar(len(params))
+26 -22
View File
@@ -82,8 +82,8 @@ Generate a constant image or mask of a specified size and color. It can be used
def run(self, **kw) -> RGBAMaskType:
pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None)
mask = parse_param(kw, "MASK", EnumConvertType.IMAGE, None)
matte = parse_param(kw, "COLOR", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(512, 512)], IMAGE_SIZE_MIN)
matte = parse_param(kw, "COLOR", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)
mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name)
sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name)
images = []
@@ -91,21 +91,25 @@ Generate a constant image or mask of a specified size and color. It can be used
pbar = ProgressBar(len(params))
for idx, (pA, mask, matte, wihi, mode, sample) in enumerate(params):
width, height = wihi
if mask is not None:
mask = tensor_to_cv(mask)
if pA is None:
pA = channel_solid(width, height, matte, EnumImageType.BGRA)
if mask is not None:
pA = image_mask_add(pA, mask)
images.append(cv_to_tensor_full(pA))
pA = channel_solid(width, height, (0,0,0,255), EnumImageType.BGRA)
else:
pA = tensor_to_cv(pA)
pA = image_convert(pA, 4)
if mask is not None:
pA = image_mask_add(pA, mask)
if mode != EnumScaleMode.MATTE:
pA = image_scalefit(pA, width, height, mode, sample, matte)
images.append(cv_to_tensor_full(pA, matte))
pB = channel_solid(width, height, matte, EnumImageType.BGRA)
if mask is None:
mask = channel_solid(width, height, (255,255,255,255), EnumImageType.GRAYSCALE)
else:
mask = tensor_to_cv(mask)
pA = image_blend(pA, pB, mask)
if mode != EnumScaleMode.MATTE:
pA = image_scalefit(pA, width, height, mode, sample, matte)
images.append(cv_to_tensor_full(pA, matte))
pbar.update_absolute(idx)
return image_stack(images)
@@ -156,11 +160,11 @@ Create n-sided polygons. These shapes can be customized by adjusting parameters
sides = parse_param(kw, "SIDES", EnumConvertType.INT, 3, 3, 100)
angle = parse_param(kw, "ANGLE", EnumConvertType.FLOAT, 0)
edge = parse_param(kw, "EDGE", EnumEdge, EnumEdge.CLIP.name)
offset = parse_param(kw, "XY", EnumConvertType.VEC2, [(0, 0)])
size = parse_param(kw, "SIZE", EnumConvertType.VEC2, [(1, 1)], zero=0.001)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(256, 256)], IMAGE_SIZE_MIN)
color = parse_param(kw, "COLOR", EnumConvertType.VEC4INT, [(255, 255, 255, 255)], 0, 255)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)
offset = parse_param(kw, "XY", EnumConvertType.VEC2, (0, 0))
size = parse_param(kw, "SIZE", EnumConvertType.VEC2, (1, 1), zero=0.001)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (256, 256), IMAGE_SIZE_MIN)
color = parse_param(kw, "COLOR", EnumConvertType.VEC4INT, (255, 255, 255, 255), 0, 255)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)
blur = parse_param(kw, "BLUR", EnumConvertType.FLOAT, 0)
params = list(zip_longest_fill(shape, sides, offset, angle, edge, size, wihi, color, matte, blur))
images = []
@@ -272,16 +276,16 @@ Generates images containing text based on parameters such as font, size, alignme
font_idx = parse_param(kw, "FONT", EnumConvertType.STRING, self.FONT_NAMES[0])
autosize = parse_param(kw, "AUTOSIZE", EnumConvertType.BOOLEAN, False)
letter = parse_param(kw, "LETTER", EnumConvertType.BOOLEAN, False)
color = parse_param(kw, "COLOR", EnumConvertType.VEC4INT, [(255,255,255,255)], 0, 255)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0,0,0,255)], 0, 255)
color = parse_param(kw, "COLOR", EnumConvertType.VEC4INT, (255,255,255,255), 0, 255)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0,0,0,255), 0, 255)
columns = parse_param(kw, "COLS", EnumConvertType.INT, 0)
font_size = parse_param(kw, "SIZE", EnumConvertType.INT, 1)
align = parse_param(kw, "ALIGN", EnumAlignment, EnumAlignment.CENTER.name)
justify = parse_param(kw, "JUSTIFY", EnumJustify, EnumJustify.CENTER.name)
margin = parse_param(kw, "MARGIN", EnumConvertType.INT, 0)
line_spacing = parse_param(kw, "SPACING", EnumConvertType.INT, 0)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(512, 512)], IMAGE_SIZE_MIN)
pos = parse_param(kw, "XY", EnumConvertType.VEC2, [(0, 0)], -1, 1)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)
pos = parse_param(kw, "XY", EnumConvertType.VEC2, (0, 0), -1, 1)
angle = parse_param(kw, "ANGLE", EnumConvertType.INT, 0)
edge = parse_param(kw, "EDGE", EnumEdge, EnumEdge.CLIP.name)
invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False)
+25 -21
View File
@@ -92,7 +92,8 @@ Extract a portion of an input image or resize it. It supports various cropping m
"label": ["BOTTOM", "LEFT", "BOTTOM", "RIGHT"],
"tooltip": "Bottom Left - Bottom Right"}),
"MATTE": ("VEC4", {
"default": (0, 0, 0, 255), "rgb": True})
"default": (0, 0, 0, 255), "rgb": True,
"tooltip": "Background Color"})
}
})
return d
@@ -101,11 +102,11 @@ Extract a portion of an input image or resize it. It supports various cropping m
pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None)
func = parse_param(kw, "FUNCTION", EnumCropMode, EnumCropMode.CENTER.name)
# if less than 1 then use as scalar, over 1 = int(size)
xy = parse_param(kw, "XY", EnumConvertType.VEC2, [(0, 0,)], 0, 1)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(512, 512)], IMAGE_SIZE_MIN)
tltr = parse_param(kw, "TLTR", EnumConvertType.VEC4, [(0, 0, 0, 1,)], 0, 1)
blbr = parse_param(kw, "BLBR", EnumConvertType.VEC4, [(1, 0, 1, 1,)], 0, 1)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)
xy = parse_param(kw, "XY", EnumConvertType.VEC2, (0, 0,), 0, 1)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)
tltr = parse_param(kw, "TLTR", EnumConvertType.VEC4, (0, 0, 0, 1,), 0, 1)
blbr = parse_param(kw, "BLBR", EnumConvertType.VEC4, (1, 0, 1, 1,), 0, 1)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)
params = list(zip_longest_fill(pA, func, xy, wihi, tltr, blbr, matte))
images = []
pbar = ProgressBar(len(params))
@@ -160,7 +161,8 @@ Combine multiple input images into a single image by summing their pixel values.
"default": EnumInterpolation.LANCZOS4.name,
"tooltip": "Sampling method for resizing images"}),
"MATTE": ("VEC4", {
"default": (0, 0, 0, 255), "rgb": True})
"default": (0, 0, 0, 255), "rgb": True,
"tooltip": "Background Color"})
}
})
return d
@@ -174,9 +176,9 @@ Combine multiple input images into a single image by summing their pixel values.
# be less dumb when merging
pA = [tensor_to_cv(i) for i in imgs]
mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(512, 512)], IMAGE_SIZE_MIN)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)
sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)
images = []
params = list(zip_longest_fill(mode, sample, wihi, matte))
@@ -220,7 +222,8 @@ The axis parameter allows for horizontal, vertical, or grid stacking of images,
"default": EnumInterpolation.LANCZOS4.name,
"tooltip": "Sampling method for resizing images"}),
"MATTE": ("VEC4", {
"default": (0, 0, 0, 255), "rgb": True})
"default": (0, 0, 0, 255), "rgb": True,
"tooltip": "Background Color"})
}
})
return d
@@ -235,9 +238,9 @@ The axis parameter allows for horizontal, vertical, or grid stacking of images,
axis = parse_param(kw, "AXIS", EnumOrientation, EnumOrientation.GRID.name)[0]
stride = parse_param(kw, "STEP", EnumConvertType.INT, 1)[0]
mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name)[0]
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(512, 512)], IMAGE_SIZE_MIN)[0]
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)[0]
sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name)[0]
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)[0]
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)[0]
img = image_stacker(images, axis, stride) #, matte)
if mode != EnumScaleMode.MATTE:
w, h = wihi
@@ -304,7 +307,8 @@ Apply various geometric transformations to images, including translation, rotati
"default": EnumInterpolation.LANCZOS4.name,
"tooltip": "Sampling method for resizing images"}),
"MATTE": ("VEC4", {
"default": (0, 0, 0, 255), "rgb": True})
"default": (0, 0, 0, 255), "rgb": True,
"tooltip": "Background Color"})
}
})
return d
@@ -312,21 +316,21 @@ Apply various geometric transformations to images, including translation, rotati
def run(self, **kw) -> RGBAMaskType:
pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None)
mask = parse_param(kw, "MASK", EnumConvertType.IMAGE, None)
offset = parse_param(kw, "XY", EnumConvertType.VEC2, [(0., 0.)], -2.5, 2.5)
offset = parse_param(kw, "XY", EnumConvertType.VEC2, (0., 0.), -2.5, 2.5)
angle = parse_param(kw, "ANGLE", EnumConvertType.FLOAT, 0)
size = parse_param(kw, "SIZE", EnumConvertType.VEC2, [(1., 1.)], 0.001)
size = parse_param(kw, "SIZE", EnumConvertType.VEC2, (1., 1.), 0.001)
edge = parse_param(kw, "EDGE", EnumEdge, EnumEdge.CLIP.name)
mirror = parse_param(kw, "MIRROR", EnumMirrorMode, EnumMirrorMode.NONE.name)
mirror_pivot = parse_param(kw, "PIVOT", EnumConvertType.VEC2, [(0.5, 0.5)], 0, 1)
tile_xy = parse_param(kw, "TILE", EnumConvertType.VEC2, [(1., 1.)], 1)
mirror_pivot = parse_param(kw, "PIVOT", EnumConvertType.VEC2, (0.5, 0.5), 0, 1)
tile_xy = parse_param(kw, "TILE", EnumConvertType.VEC2, (1., 1.), 1)
proj = parse_param(kw, "PROJ", EnumProjection, EnumProjection.NORMAL.name)
tltr = parse_param(kw, "TLTR", EnumConvertType.VEC4, [(0., 0., 1., 0.)], 0, 1)
blbr = parse_param(kw, "BLBR", EnumConvertType.VEC4, [(0., 1., 1., 1.)], 0, 1)
tltr = parse_param(kw, "TLTR", EnumConvertType.VEC4, (0., 0., 1., 0.), 0, 1)
blbr = parse_param(kw, "BLBR", EnumConvertType.VEC4, (0., 1., 1., 1.), 0, 1)
strength = parse_param(kw, "STRENGTH", EnumConvertType.FLOAT, 1, 0, 1)
mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(512, 512)], IMAGE_SIZE_MIN)
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)
sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)
params = list(zip_longest_fill(pA, mask, offset, angle, size, edge, tile_xy, mirror, mirror_pivot, proj, strength, tltr, blbr, mode, wihi, sample, matte))
images = []
pbar = ProgressBar(len(params))
+24 -24
View File
@@ -69,10 +69,6 @@ class EnumBatchMode(Enum):
# === CLASS ===
# ==============================================================================
class ContainsAnyDict(dict):
def __contains__(self, key) -> Literal[True]:
return True
class ArrayNode(CozyBaseNode):
NAME = "ARRAY (JOV) 📚"
CATEGORY = JOV_CATEGORY
@@ -127,7 +123,7 @@ Processes a batch of data based on the selected mode. Merge, pick, slice, random
def run(self, **kw) -> tuple[int, list]:
data_list = parse_dynamic(kw, "❔", EnumConvertType.ANY, None)
mode = parse_param(kw, "MODE", EnumBatchMode, EnumBatchMode.MERGE.name)[0]
slice_range = parse_param(kw, "RANGE", EnumConvertType.VEC3INT, [(0, 0, 1)])[0]
slice_range = parse_param(kw, "RANGE", EnumConvertType.VEC3INT, (0, 0, 1))[0]
index = parse_param(kw, "INDEX", EnumConvertType.STRING, "")[0]
count = parse_param(kw, "COUNT", EnumConvertType.INT, 0, 0, sys.maxsize)[0]
reverse = parse_param(kw, "REVERSE", EnumConvertType.BOOLEAN, False)[0]
@@ -251,7 +247,7 @@ class QueueBaseNode(CozyBaseNode):
CATEGORY = JOV_CATEGORY
RETURN_TYPES = (COZY_TYPE_ANY, COZY_TYPE_ANY, "STRING", "INT", "INT", "BOOLEAN")
RETURN_NAMES = ("🦄", "QUEUE", "CURRENT", "INDEX", "TOTAL", "TRIGGER", )
OUTPUT_IS_LIST = (True, True, True, True, True, True,)
#OUTPUT_IS_LIST = (True, True, True, True, True, True,)
VIDEO_FORMATS = ['.wav', '.mp3', '.webm', '.mp4', '.avi', '.wmv', '.mkv', '.mov', '.mxf']
@classmethod
@@ -272,9 +268,9 @@ class QueueBaseNode(CozyBaseNode):
"BATCH": ("BOOLEAN", {
"default": False,
"tooltip":"Load all items, if they are loadable items, i.e. batch load images from the Queue's list."}),
"VALUE": ("INT", {
"SELECT": ("INT", {
"default": 0, "min": 0,
"tooltip": "The current index for the current queue item"}),
"tooltip": "What index to use for the current queue item. 0 will move to the next item each queue run"}),
"HOLD": ("BOOLEAN", {
"default": False,
"tooltip":"Hold the item at the current queue index"}),
@@ -371,13 +367,20 @@ class QueueBaseNode(CozyBaseNode):
self.__ident = ident
# should work headless as well
if (new_val := parse_param(kw, "SELECT", EnumConvertType.INT, 0)[0]) > 0:
self.__index = new_val - 1
reset = parse_reset(ident) > 0
if reset or parse_param(kw, "RESET", EnumConvertType.BOOLEAN, False)[0]:
self.__q = None
self.__index = 0
if (new_val := parse_param(kw, "VALUE", EnumConvertType.INT, 0)[0]) > 0:
self.__index = new_val - 1
mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name)[0]
sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name)[0]
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)[0]
w, h = wihi
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)[0]
if self.__q is None:
# process Q into ...
@@ -420,26 +423,21 @@ class QueueBaseNode(CozyBaseNode):
for idx in range(self.__len):
ret = self.process(self.__q[idx])
if isinstance(ret, (np.ndarray,)):
h, w, c = ret.shape
mw, mh, mc = max(mw, w), max(mh, h), max(mc, c)
h2, w2, c = ret.shape
mw, mh, mc = max(mw, w2), max(mh, h2), max(mc, c)
data.append(ret)
if mw != 0 or mh != 0 or mc != 0:
ret = []
mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name)[0]
sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name)[0]
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(512, 512)], IMAGE_SIZE_MIN)[0]
w2, h2 = wihi
matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255)[0]
matte = [matte[0], matte[1], matte[2], 0]
# matte = [matte[0], matte[1], matte[2], 0]
pbar = ProgressBar(self.__len)
for idx, d in enumerate(data):
d = image_convert(d, mc)
if mode != EnumScaleMode.MATTE:
d = image_scalefit(d, w2, h2, mode=mode, sample=sample)
d = image_scalefit(d, w, h, mode, sample, matte)
d = image_scalefit(d, w, h, EnumScaleMode.RESIZE_MATTE, sample, matte)
else:
d = image_matte(d, matte, width=mw, height=mh)
d = image_matte(d, matte, mw, mh)
ret.append(cv_to_tensor(d))
pbar.update_absolute(idx)
data = torch.stack(ret)
@@ -448,6 +446,8 @@ class QueueBaseNode(CozyBaseNode):
else:
data = self.process(self.__q[self.__index])
if isinstance(data, (np.ndarray,)):
if mode != EnumScaleMode.MATTE:
data = image_scalefit(data, w, h, mode, sample)
data = cv_to_tensor(data).unsqueeze(0)
self.__index += 1
@@ -455,7 +455,7 @@ class QueueBaseNode(CozyBaseNode):
comfy_api_post("jovi-queue-ping", ident, self.status)
if stop and batched:
interrupt_processing()
return data, self.__q, self.__current, self.__index, self.__len, self.__index == self.__index_last or batched
return data, self.__q, self.__current, self.__index, self.__len, self.__index == self.__len or batched
@property
def status(self) -> dict[str, Any]:
@@ -485,8 +485,8 @@ Manage a queue of items, such as file paths or data. Supports various formats in
class QueueTooNode(QueueBaseNode):
NAME = "QUEUE TOO (JOV) 🗃"
RETURN_TYPES = ("IMAGE", "IMAGE", "MASK", "STRING", "INT", "INT", "BOOLEAN")
RETURN_NAMES = ("IMAGE", "RGB", "MASK", "CURRENT", "INDEX", "TOTAL", "TRIGGER", )
OUTPUT_IS_LIST = (False, False, False, True, True, True, True,)
RETURN_NAMES = ("RGBA", "RGB", "MASK", "CURRENT", "INDEX", "TOTAL", "TRIGGER", )
#OUTPUT_IS_LIST = (False, False, False, True, True, True, True,)
OUTPUT_TOOLTIPS = (
"Full channel [RGBA] image. If there is an alpha, the image will be masked out with it when using this output",
"Three channel [RGB] image. There will be no alpha",
+3 -3
View File
@@ -180,7 +180,7 @@ Visualize a series of data points over time. It accepts a dynamic number of valu
def run(self, ident, **kw) -> tuple[TensorType]:
slice = parse_param(kw, "VAL", EnumConvertType.INT, 60)[0]
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, [(512, 512)], 1)[0]
wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), 1)[0]
if parse_reset(ident) > 0 or parse_param(kw, "RESET", EnumConvertType.BOOLEAN, False)[0]:
self.__history = []
longest_edge = 0
@@ -236,7 +236,7 @@ Exports and Displays immediate information about images.
d = super().INPUT_TYPES()
d = deep_merge(d, {
"optional": {
"IMAGE_A": (COZY_TYPE_IMAGE, {
"IMAGE": (COZY_TYPE_IMAGE, {
"default": None,
"tooltip":"The image to examine"})
}
@@ -244,6 +244,6 @@ Exports and Displays immediate information about images.
return d
def run(self, **kw) -> tuple[int, list]:
image = parse_param(kw, "IMAGE_A", EnumConvertType.IMAGE, None)
image = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None)
height, width, cc = image[0].shape
return (len(image), width, height, cc, (width, height), (width, height, cc))
+20 -16
View File
@@ -308,27 +308,31 @@ Save the output image along with its metadata to the specified path. Supports sa
d = super().INPUT_TYPES(True, True)
d = deep_merge(d, {
"optional": {
"image": ("IMAGE", {"default": None,
"tooltip":""}),
"path": ("STRING", {"default": "", "dynamicPrompts":False,
"tooltip":"Destination path to save the output"}),
"fname": ("STRING", {"default": "output", "dynamicPrompts":False,
"tooltip":"Filename of the output"}),
"metadata": ("JSON", {"default": None,
"tooltip":"Extra metadata to save in the file"}),
"usermeta": ("STRING", {"default": "", "multiline": True,
"dynamicPrompts":False,
"tooltip":"Custom user metadat to save with the file"}),
"IMAGE": ("IMAGE", {
"default": None,
"tooltip":""}),
"PATH": ("STRING", {
"default": "", "dynamicPrompts":False,
"tooltip":"Destination path to save the output"}),
"NAME": ("STRING", {
"default": "output", "dynamicPrompts":False,
"tooltip":"Filename of the output"}),
"META": ("JSON", {
"default": None,
"tooltip":"Extra metadata to save in the file"}),
"USER": ("STRING", {
"default": "", "multiline": True, "dynamicPrompts":False,
"tooltip":"Custom user metadat to save with the file"}),
}
})
return d
def run(self, **kw) -> dict[str, Any]:
image = parse_param(kw, 'image', EnumConvertType.IMAGE, None)
metadata = parse_param(kw, 'metadata', EnumConvertType.DICT, {})
usermeta = parse_param(kw, 'usermeta', EnumConvertType.DICT, {})
path = parse_param(kw, 'path', EnumConvertType.STRING, "")
fname = parse_param(kw, 'fname', EnumConvertType.STRING, "output")
image = parse_param(kw, 'IMAGE', EnumConvertType.IMAGE, None)
path = parse_param(kw, 'PATH', EnumConvertType.STRING, "")
fname = parse_param(kw, 'NAME', EnumConvertType.STRING, "output")
metadata = parse_param(kw, 'META', EnumConvertType.DICT, {})
usermeta = parse_param(kw, 'USER', EnumConvertType.DICT, {})
prompt = parse_param(kw, 'prompt', EnumConvertType.STRING, "")
pnginfo = parse_param(kw, 'extra_pnginfo', EnumConvertType.DICT, {})
params = list(zip_longest_fill(image, path, fname, metadata, usermeta, prompt, pnginfo))
+72 -45
View File
@@ -23,7 +23,7 @@ class ValueNode(CozyBaseNode):
NAME = "VALUE (JOV) 🧬"
CATEGORY = JOV_CATEGORY
RETURN_TYPES = (COZY_TYPE_ANY, COZY_TYPE_ANY, COZY_TYPE_ANY, COZY_TYPE_ANY, COZY_TYPE_ANY,)
RETURN_NAMES = ("🦄", "X", "Y", "Z", "W")
RETURN_NAMES = ("🦄", "X", "Y", "Z", "W",)
SORT = 5
DESCRIPTION = """
Supplies raw or default values for various data types, supporting vector input with components for X, Y, Z, and W. It also provides a string input option.
@@ -71,15 +71,15 @@ Supplies raw or default values for various data types, supporting vector input w
return d
def run(self, **kw) -> tuple[bool]:
raw = parse_param(kw, "A", EnumConvertType.ANY, [0])
raw = parse_param(kw, "A", EnumConvertType.ANY, 0)
r_x = parse_param(kw, "X", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
r_y = parse_param(kw, "Y", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
r_z = parse_param(kw, "Z", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
r_w = parse_param(kw, "W", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
typ = parse_param(kw, "TYPE", EnumConvertType, EnumConvertType.BOOLEAN.name)
xyzw = parse_param(kw, "AA", EnumConvertType.VEC4, [(0, 0, 0, 0)])
xyzw = parse_param(kw, "AA", EnumConvertType.VEC4, (0, 0, 0, 0))
seed = parse_param(kw, "SEED", EnumConvertType.INT, 0, 0)
yyzw = parse_param(kw, "BB", EnumConvertType.VEC4, [(1, 1, 1, 1)])
yyzw = parse_param(kw, "BB", EnumConvertType.VEC4, (1, 1, 1, 1))
x_str = parse_param(kw, "STRING", EnumConvertType.STRING, "")
params = list(zip_longest_fill(raw, r_x, r_y, r_z, r_w, typ, xyzw, seed, yyzw, x_str))
results = []
@@ -170,7 +170,6 @@ Outputs a VECTOR2.
def run(self, **kw) -> tuple[tuple[float, ...], tuple[int, ...]]:
x = parse_param(kw, "X", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
y = parse_param(kw, "Y", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
a = parse_param(kw, "A", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
b = parse_param(kw, "B", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
@@ -181,7 +180,6 @@ Outputs a VECTOR2.
x = round(a, 9) if x is None else round(x, 9)
y = round(b, 9) if y is None else round(y, 9)
result.append((x, y,))
#resultY.append((int(x), int(y)))
pbar.update_absolute(idx)
return result,
@@ -190,6 +188,7 @@ class Vector3Node(CozyBaseNode):
CATEGORY = JOV_CATEGORY
RETURN_TYPES = ("VEC3",)
RETURN_NAMES = ("VEC3",)
OUTPUT_IS_LIST = (True,)
OUTPUT_TOOLTIPS = (
"Vector3 with float values",
)
@@ -204,41 +203,53 @@ Outputs a VECTOR3.
d = deep_merge(d, {
"optional": {
"X": (COZY_TYPE_NUMBER, {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "1st channel value"}),
"min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "X channel value"}),
"Y": (COZY_TYPE_NUMBER, {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "2nd channel value"}),
"min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "Y channel value"}),
"Z": (COZY_TYPE_NUMBER, {
"min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "Z channel value"}),
"A": ("FLOAT", {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "3rd channel value"}),
"tooltip": "Default X channel value"}),
"B": ("FLOAT", {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "Default Y channel value"}),
"C": ("FLOAT", {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "Default Z channel value"}),
}
})
return d
def run(self, **kw) -> tuple[tuple[float, ...], tuple[int, ...]]:
x = parse_param(kw, "X", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
y = parse_param(kw, "Y", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
z = parse_param(kw, "Z", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
results = []
params = list(zip_longest_fill(x, y, z))
x = parse_param(kw, "X", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
y = parse_param(kw, "Y", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
z = parse_param(kw, "Z", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
a = parse_param(kw, "A", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
b = parse_param(kw, "B", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
c = parse_param(kw, "C", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
result = []
params = list(zip_longest_fill(x, y, z, a, b, c))
pbar = ProgressBar(len(params))
for idx, (x, y, z) in enumerate(params):
x = round(x, 6)
y = round(y, 6)
z = round(z, 6)
results.append([(x, y, z,), (int(x), int(y), int(z),)])
for idx, (x, y, z, a, b, c) in enumerate(params):
x = round(a, 9) if x is None else round(x, 9)
y = round(b, 9) if y is None else round(y, 9)
z = round(c, 9) if z is None else round(z, 9)
result.append((x, y, z,))
pbar.update_absolute(idx)
return *list(zip(*results)),
return result,
class Vector4Node(CozyBaseNode):
NAME = "VECTOR4 (JOV)"
CATEGORY = JOV_CATEGORY
RETURN_TYPES = ("VEC4", "VEC4INT", )
RETURN_NAMES = ("VEC4", "VEC4INT", )
RETURN_TYPES = ("VEC4",)
RETURN_NAMES = ("VEC4",)
OUTPUT_IS_LIST = (True,)
OUTPUT_TOOLTIPS = (
"Vector4 with float values",
"Vector4 with integer values",
)
SORT = 294
DESCRIPTION = """
@@ -251,37 +262,53 @@ Outputs a VEC4.
d = deep_merge(d, {
"optional": {
"X": (COZY_TYPE_NUMBER, {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "1st channel value"}),
"min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "X channel value"}),
"Y": (COZY_TYPE_NUMBER, {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "2nd channel value"}),
"min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "Y channel value"}),
"Z": (COZY_TYPE_NUMBER, {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "3rd channel value"}),
"min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "Z channel value"}),
"W": (COZY_TYPE_NUMBER, {
"min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "W channel value"}),
"A": ("FLOAT", {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "4th channel value"}),
"tooltip": "Default X channel value"}),
"B": ("FLOAT", {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "Default Y channel value"}),
"C": ("FLOAT", {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "Default Z channel value"}),
"D": ("FLOAT", {
"default": 0, "min": -sys.maxsize, "max": sys.maxsize,
"tooltip": "Default W channel value"}),
}
})
return d
def run(self, **kw) -> tuple[tuple[float, ...], tuple[int, ...]]:
x = parse_param(kw, "X", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
y = parse_param(kw, "Y", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
z = parse_param(kw, "Z", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
w = parse_param(kw, "W", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
results = []
params = list(zip_longest_fill(x, y, z, w))
x = parse_param(kw, "X", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
y = parse_param(kw, "Y", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
z = parse_param(kw, "Z", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
w = parse_param(kw, "W", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize)
a = parse_param(kw, "A", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
b = parse_param(kw, "B", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
c = parse_param(kw, "C", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
d = parse_param(kw, "D", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)
result = []
params = list(zip_longest_fill(x, y, z, w, a, b, c, d))
pbar = ProgressBar(len(params))
for idx, (x, y, z, w,) in enumerate(params):
x = round(x, 6)
y = round(y, 6)
z = round(z, 6)
w = round(w, 6)
results.append([(x, y, z, w,), (int(x), int(y), int(z), int(w),)])
for idx, (x, y, z, w, a, b, c, d) in enumerate(params):
x = round(a, 9) if x is None else round(x, 9)
y = round(b, 9) if y is None else round(y, 9)
z = round(c, 9) if z is None else round(z, 9)
w = round(d, 9) if w is None else round(w, 9)
result.append((x, y, z, w,))
pbar.update_absolute(idx)
return *list(zip(*results)),
return result,
'''
class ParameterNode(CozyBaseNode):
+9 -5
View File
@@ -16,7 +16,7 @@ from cozy_comfyui.image import \
from cozy_comfyui.image.convert import \
ImageType, \
image_matte, image_mask_add, image_convert, image_to_bgr, \
image_matte, image_mask, image_mask_add, image_convert, image_to_bgr, \
bgr_to_image, cv_to_tensor, tensor_to_cv
from cozy_comfyui.image.crop import \
@@ -382,11 +382,15 @@ def image_scalefit(image: ImageType, width: int, height:int,
case EnumScaleMode.RESIZE_MATTE:
h, w = image.shape[:2]
width = max(width, w)
height = max(height, h)
canvas = np.full((height, width, 4), matte, dtype=image.dtype)
image = image_matte(image, (0,0,0,0), width, height)
w2 = max(width, w)
h2 = max(height, h)
canvas = np.full((h2, w2, 4), matte, dtype=image.dtype)
mask = image_mask(image)
mask = image_matte(mask, (255, 255, 255, 255), w2, h2)
image = image_matte(image, (0,0,0,0), w2, h2)
image = image_blend(canvas, image)
image = image_mask_add(image, mask)
image = image_crop_center(image, width, height)
case EnumScaleMode.ASPECT:
h, w = image.shape[:2]
+10 -10
View File
@@ -120,19 +120,19 @@ def pixel_convert(color:PixelType, size:int=4, alpha:int=255) -> PixelType:
These are core functions that most of the support image libraries require.
"""
def image_blend(imageA: ImageType, imageB: ImageType, mask:Optional[ImageType]=None,
def image_blend(background: ImageType, foreground: ImageType, mask:Optional[ImageType]=None,
blendOp:BlendType=BlendType.NORMAL, alpha:float=1) -> ImageType:
"""Blending that will size to the largest input's background."""
# prep A
h, w = imageA.shape[:2]
imageA = image_convert(imageA, 4, w, h)
imageA = cv_to_pil(imageA)
h, w = background.shape[:2]
background = image_convert(background, 4, w, h)
background = cv_to_pil(background)
# prep B
cc = imageB.shape[2] if imageB.ndim > 2 else 1
imageB = image_convert(imageB, 4, w, h)
old_mask = image_mask(imageB, 0)
cc = foreground.shape[2] if foreground.ndim > 2 else 1
foreground = image_convert(foreground, 4, w, h)
old_mask = image_mask(foreground, 0)
if mask is None:
mask = old_mask
@@ -142,10 +142,10 @@ def image_blend(imageA: ImageType, imageB: ImageType, mask:Optional[ImageType]=N
if cc == 4:
mask = cv2.bitwise_and(mask, old_mask)
imageB[..., 3] = mask
imageB = cv_to_pil(imageB)
foreground[..., 3] = mask
foreground = cv_to_pil(foreground)
alpha = np.clip(alpha, 0, 1)
image = blendLayers(imageA, imageB, blendOp.value, alpha)
image = blendLayers(background, foreground, blendOp.value, alpha)
image = pil_to_cv(image)
if cc == 4:
image = image_mask_add(image, mask)
+1 -10
View File
@@ -36,12 +36,10 @@ export async function apiJovimetrix(id, cmd, data=null, route="message", ) {
} catch (error) {
console.error("API call to Jovimetrix failed:", error);
throw error; // or return { success: false, message: error.message }
throw error;
}
}
//export const widgetFind = (widgets, name) => widgets.find(w => w.name == name);
function widgetShowVector(widget, values={}, type) {
if (["FLOAT"].includes(type)) {
type = "VEC1";
@@ -86,7 +84,6 @@ function widgetShowVector(widget, values={}, type) {
widget.value = {};
for (let i = 0; i < size; i++) {
widget.value[i] = (widget.options.precision == 0) ? Number(values[i]) : parseFloat(values[i]).toFixed(widget.options.precision);
//widget.value[i] = !widget.type.endsWith('INT') ? Math.round(values[i]) : Number(values[i]);
}
} else {
widget.value = values[0] ? true : false;
@@ -155,7 +152,6 @@ export function widgetHookControl(node, control_key, target, matchFloatSize=fals
}
const data = {
//track_xyzw: target.options?.default, //initializeTrack(target),
track_xyzw: initializeTrack(target),
target,
combo
@@ -164,19 +160,14 @@ export function widgetHookControl(node, control_key, target, matchFloatSize=fals
const oldCallback = combo.callback;
combo.callback = () => {
const me = oldCallback?.apply(this, arguments);
//widgetHide(node, target, "-jov");
//if (["VEC2", "VEC2INT", "COORD2D", "VEC3", "VEC3INT", "VEC4", "VEC4INT", "BOOLEAN", "INT", "FLOAT"].includes(combo.value)) {
if (["VEC2", "VEC3", "VEC4", "BOOLEAN", "INT", "FLOAT"].includes(combo.value)) {
let type = combo.value;
if (matchFloatSize) {
type = "FLOAT";
// if (["VEC2", "VEC2INT", "COORD2D"].includes(combo.value)) {
if (["VEC2"].includes(combo.value)) {
type = "VEC2";
//} else if (["VEC3", "VEC3INT"].includes(combo.value)) {
} else if (["VEC3"].includes(combo.value)) {
type = "VEC3";
//} else if (["VEC4", "VEC4INT"].includes(combo.value)) {
} else if (["VEC4"].includes(combo.value)) {
type = "VEC4";
}