This commit introduces several new performance-oriented custom nodes and utilities: - Added LTXV Multi Concat and LTXV Multi Concat (beta) for faster frame injection using latent inpainting logic. - Refactored LTXV index resolution logic into ltxv_utils.py. - Updated ImageListSampler to anchor edge frames properly and support output index normalization scaling via target_frames. - Added metadata-based prompt extraction image loaders (LoadImageAndExtractPrompt, FolderImageAndExtractPrompt, and FolderImageMetadataByName). - Included animation tracking and camera switcher nodes.
66 lines
2.3 KiB
Python
66 lines
2.3 KiB
Python
import torch
|
|
from comfy_extras.nodes_mask import composite
|
|
import node_helpers
|
|
|
|
class AnotherImageCompositeMasked:
|
|
"""
|
|
AnotherImageCompositeMasked
|
|
A memory-safe, batch-aware version of the native ImageCompositeMasked node.
|
|
It loops through batch elements one by one to avoid massive memory spikes
|
|
(OOM 'not enough memory' allocated to DefaultCPUAllocator) when processing large image lists.
|
|
"""
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"destination": ("IMAGE",),
|
|
"source": ("IMAGE",),
|
|
"x": ("INT", {"default": 0, "min": 0, "max": 8192, "step": 1}),
|
|
"y": ("INT", {"default": 0, "min": 0, "max": 8192, "step": 1}),
|
|
"resize_source": ("BOOLEAN", {"default": False}),
|
|
},
|
|
"optional": {
|
|
"mask": ("MASK",),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "execute"
|
|
CATEGORY = "AnotherUtils/image_processing"
|
|
|
|
def execute(self, destination, source, x, y, resize_source, mask=None):
|
|
destination, source = node_helpers.image_alpha_fix(destination, source)
|
|
destination = destination.clone().movedim(-1, 1)
|
|
source = source.movedim(-1, 1)
|
|
|
|
batch_size = max(destination.shape[0], source.shape[0])
|
|
|
|
# Expand mask to batch size if needed
|
|
if mask is not None:
|
|
if mask.shape[0] < batch_size:
|
|
mask = mask.repeat(batch_size // mask.shape[0] + 1, 1, 1)[:batch_size]
|
|
|
|
# Prepare output tensor
|
|
out = []
|
|
|
|
# Iterate one frame at a time to prevent CPU OOM allocation spikes
|
|
for i in range(batch_size):
|
|
dest_frame = destination[i:i+1] # [1, C, H, W]
|
|
|
|
# handle loop/repeat around if lengths differ
|
|
src_frame = source[i % source.shape[0]:i % source.shape[0] + 1]
|
|
|
|
mask_frame = None
|
|
if mask is not None:
|
|
mask_frame = mask[i % mask.shape[0]:i % mask.shape[0] + 1]
|
|
|
|
# Use native comfy composite, but on a single element
|
|
res_frame = composite(dest_frame, src_frame, x, y, mask_frame, 1, resize_source)
|
|
out.append(res_frame)
|
|
|
|
# Re-stack and fix dimension order
|
|
output = torch.cat(out, dim=0).movedim(1, -1)
|
|
|
|
return (output,)
|