Example ComfyUI custom nodes demonstrating how to use the ImageProcessingNode and TextProcessingNode base classes from comfy_extras.nodes_dataset.
This extension provides example nodes showcasing both single-item processing and group processing patterns using the ComfyUI V3 API.
-
Rotate Images - Single-item processing example
- Rotates each image independently by a specified angle
- Options: angle (degrees), expand canvas
-
Convert to Grayscale - Single-item processing example
- Converts images to grayscale independently
- Options: keep RGB format or single channel
-
Batch Statistics Normalization - Group processing example
- Computes statistics across entire batch of images
- Normalizes using batch mean/std or min/max
- Options: standardize, min_max, or none (stats only)
-
Capitalize Text - Single-item processing example
- Capitalizes text independently
- Options: first letter, each word, or all caps
-
Reverse Text - Single-item processing example
- Reverses text by characters or words
- Options: characters or words
-
Text Word Statistics - Group processing example
- Analyzes word statistics across all texts
- Filters texts by minimum word count
- Reports total words, average, and unique words
- Clone or copy this directory to
ComfyUI/custom_nodes/dataset_nodes_example - Restart ComfyUI
- Nodes will appear in the "Add Node" menu
These nodes automatically process each item independently. The backend calls the node multiple times (once per item):
class ImageRotateNode(ImageProcessingNode):
# Auto-detected as single-item processing (overrides _process)
# is_input_list = False (auto)
# is_output_list = False (auto - each call outputs single item)
@classmethod
def _process(cls, image, angle, expand):
# Process ONE image at a time
# Backend automatically calls this for each image
img = tensor_to_pil(image)
img_rotated = img.rotate(angle, expand=expand_bool)
return pil_to_tensor(img_rotated)
# Returns: single tensor
# Backend collects all results into list automaticallyBehavior:
- Input: List of 5 images → Backend calls
_process()5 times - Each call receives: 1 image
- Each call returns: 1 image
- Final output: List of 5 images (auto-collected by backend)
These nodes receive the entire list and process it as a batch:
class ImageBatchStatisticsNode(ImageProcessingNode):
is_group_process = True # Explicit group processing
# is_input_list = True (from is_group_process)
# is_output_list = True (auto - defaults to True for group nodes)
@classmethod
def _group_process(cls, images, method):
# Process ALL images together
stats = compute_image_statistics(images)
# Normalize based on batch statistics
return [(img - stats['mean']) / stats['std'] for img in images]
# Returns: list of tensorsBehavior:
- Input: List of 5 images → Backend calls
_group_process()1 time - Call receives: List of 5 images
- Call returns: List of 5 normalized images
- Final output: List of 5 images
For nodes that combine multiple inputs into a single output:
class ImageGridNode(ImageProcessingNode):
is_group_process = True # Requires full list
is_output_list = False # Outputs single image (must be explicit!)
@classmethod
def _group_process(cls, images, columns, padding):
# Arrange all images into a grid
grid = create_image_grid(images, columns, padding)
return grid # Returns single image tensorBehavior:
- Input: List of 5 images → Backend calls
_group_process()1 time - Call receives: List of 5 images
- Call returns: 1 grid image
- Final output: Single image (not a list)
__init__.py- Extension entry point withcomfy_entrypoint()nodes/- Node implementationsimage_nodes.py- Image processing examplestext_nodes.py- Text processing examplesutils.py- Shared utility functions
The base classes automatically detect processing mode by checking which method you override:
Processing Mode (is_group_process):
- Override
_process()→ Single-item processingis_input_list = False(backend calls node N times)
- Override
_group_process()→ Group processingis_input_list = True(node receives full list)
Output Mode (is_output_list):
- Single-item processing: Defaults to
False(each item processed independently)- Backend auto-collects results into list when multiple inputs exist
- Group processing: Defaults to
True(outputs list)- Can be set to
Falsefor nodes that combine inputs into single output
- Can be set to
You can explicitly set the processing and output modes:
class MyNode(ImageProcessingNode):
is_group_process = True # Force group processing (optional if _group_process is implemented)
is_output_list = False # Output single item instead of list (required for list→single)| Mode | Override | is_input_list | is_output_list (default) | Example |
|---|---|---|---|---|
| Single | _process |
False | False (auto) | Rotate, Grayscale |
| Group (list→list) | _group_process |
True | True (auto) | Batch normalize, Shuffle |
| Group (list→single) | _group_process |
True | False* | Image grid, Collage |
*Must be explicitly set to False (default for group is True)
- ComfyUI with V3 API support
- Base classes from
comfy_extras.nodes_dataset
Apache License 2.0
This is an example project. Feel free to use it as a template for your own custom nodes!
For questions about the base classes or V3 API, refer to the ComfyUI documentation.