| |
|
| |
|
| |
|
| |
|
| |
|
| | import torch
|
| |
|
| |
|
| | def _clamp_index(index: int, batch_size: int) -> int:
|
| | """Clamp index into [0, batch_size-1]."""
|
| | if batch_size <= 0:
|
| | raise ValueError("Input batch is empty (batch_size <= 0).")
|
| | if index < 0 or index >= batch_size:
|
| | print(
|
| | f"[BatchRemoveIndex] index {index} out of range for batch_size {batch_size}; "
|
| | f"clamping to valid range."
|
| | )
|
| | index = max(0, min(index, batch_size - 1))
|
| | return index
|
| |
|
| |
|
| | class BatchRemoveImageAtIndex:
|
| | """
|
| | Takes an IMAGE batch and an integer index (0-based),
|
| | outputs the batch WITHOUT the image at that index.
|
| |
|
| | Example:
|
| | images = [img0,img1,img2,img3], index=2
|
| | output = [img0,img1,img3]
|
| | """
|
| |
|
| | @classmethod
|
| | def INPUT_TYPES(cls):
|
| | return {
|
| | "required": {
|
| | "images": ("IMAGE",),
|
| | "index": ("INT", {"default": 0, "min": 0, "max": 10**9}),
|
| | }
|
| | }
|
| |
|
| | RETURN_TYPES = ("IMAGE",)
|
| | RETURN_NAMES = ("images",)
|
| | FUNCTION = "remove"
|
| | CATEGORY = "Batch/Index"
|
| |
|
| | def remove(self, images, index):
|
| | if not torch.is_tensor(images):
|
| | raise TypeError("Expected 'images' to be a torch Tensor (ComfyUI IMAGE type).")
|
| | if images.ndim != 4:
|
| | raise ValueError(f"Expected 'images' with shape [B,H,W,C], got ndim={images.ndim}.")
|
| |
|
| | b = images.shape[0]
|
| | if b <= 1:
|
| |
|
| | raise ValueError(
|
| | f"Cannot remove an item from a batch of size {b} (would produce an empty batch)."
|
| | )
|
| |
|
| | idx = _clamp_index(int(index), b)
|
| |
|
| |
|
| | out = torch.cat([images[:idx], images[idx + 1 :]], dim=0)
|
| | return (out,)
|
| |
|
| |
|
| | NODE_CLASS_MAPPINGS = {
|
| | "BatchRemoveImageAtIndex": BatchRemoveImageAtIndex,
|
| | }
|
| |
|
| | NODE_DISPLAY_NAME_MAPPINGS = {
|
| | "BatchRemoveImageAtIndex": "Batch: Remove Image @ Index",
|
| | } |