Tutorial 4 ‐ Hello World Overlay Text - Suzie1/ComfyUI_Guide_To_Making_Custom_Nodes GitHub Wiki
In this tutorial, we are going to build the Hello World node below
The node overlays text onto a color background and outputs an image.
Steps
nodes.py
file in Notepad++ or an IDE
1. Open the - Windows Notepad is not recommended.
2. Choose the inputs and outputs that you want on the node
Inputs:
image_width, image_height, text, font_size, font_color, background_color
Outputs:
image
3. Setup the class structure
class HelloWorldOverlayText:
@classmethod
def INPUT_TYPES(cls):
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("IMAGE",)
FUNCTION = "draw_overlay_text"
CATEGORY = "Tutorial Nodes"
def draw_overlay_text(self, image_width, image_height, text,
font_size, font_color, background_color):
return (image_out)
RETURN_TYPES
defines the output typesRETURN_NAMES
defines the output labels. In this case the output labels are the same as the output types.FUNCTION
is used to specify the main functionCATEGORY
specifies where the node will be included in the ComfyUI node menu- The first parameter in the main function should always be
self
- The return statement is used to specify the objects that are passed to the node outputs
4. Add the import parameters into the class structure
- The parameters must match the parameters in the
draw_overlay_text
function - Each
INT
parameter should include arguments defining the default value and the min and max values - The
STRING
parameter should include multiline = true or false. If true the text input will display as an input box. If false the text input will display as a widget. - The two color inputs are of type COMBO. The input is defined using an array
["white", "black", ...]
return {"required": {
"image_width": ("INT", {"default": 512, "min": 64, "max": 2048}),
"image_height": ("INT", {"default": 512, "min": 64, "max": 2048}),
"text": ("STRING", {"multiline": True, "default": "Hello World"}),
"font_size": ("INT", {"default": 50, "min": 1, "max": 1024}),
"font_color": (["white", "black", "red", "green", "blue", "yellow"],),
"background_color": (["white", "black", "red", "green", "blue", "yellow"],),
}
}
5. Make a draft for the main function using ChatGPT
Try the following prompt
write a python function to draw centered text on a colored background using the PIL library
use the following input parameters
image_width, image_height, text, font_size, font_color, background_color
6. Edit the main function to clean-up any issues, or add missing code
7. Add the main function into the class structure
- Python is fussy about indents. Take care to use precise indentation.
- The image is created using the PIL.Image function
- The font is defined using the PIL.ImageFont function
# Create a new PIL image
new_img = Image.new("RGBA", (image_width, image_height), background_color)
draw = ImageDraw.Draw(new_img)
# Define font
font = ImageFont.truetype("arial.ttf", size=font_size)
# Get the image center
image_center_x = image_width/2
image_center_y = image_height/2
# Draw the text, mm = text center
draw.text((image_center_x, image_center_y), text, fill=font_color, font=font, anchor="mm")
# Convert the PIL image to a torch tensor
image_out = pil2tensor(new_img)
8. Add a function for converting from a PIL image to a tensor image
def pil2tensor(image):
return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)
9. Add the import statement at the top of the file
import numpy as np
import torch
from PIL import Image, ImageDraw, ImageFont
- These will import libraries referenced in the functions
- Numpy and Torch are needed for the
pil2tensor
function above - The three PIL functions are needed for the main function
10. Check the completed node
It should look like this:
import numpy as np
import torch
from PIL import Image, ImageDraw, ImageFont
def pil2tensor(image):
return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)
# based on https://stackoverflow.com/questions/1970807/center-middle-align-text-with-pil
class HelloWorldOverlayText:
@classmethod
def INPUT_TYPES(cls):
return {"required": {
"image_width": ("INT", {"default": 512, "min": 64, "max": 2048}),
"image_height": ("INT", {"default": 512, "min": 64, "max": 2048}),
"text": ("STRING", {"multiline": True, "default": "Hello World"}),
"font_size": ("INT", {"default": 50, "min": 1, "max": 1024}),
"font_color": (["white", "black", "red", "green", "blue", "yellow"],),
"background_color": (["white", "black", "red", "green", "blue", "yellow"],),
}
}
RETURN_TYPES = ("IMAGE",)
#RETURN_NAMES = ("IMAGE",)
FUNCTION = "draw_overlay_text"
CATEGORY = "Tutorial Nodes"
def draw_overlay_text(self, image_width, image_height, text,
font_size, font_color, background_color):
# Create a new PIL image
new_img = Image.new("RGBA", (image_width, image_height), background_color)
draw = ImageDraw.Draw(new_img)
# Define font
font = ImageFont.truetype("arial.ttf", size=font_size)
# Get the image center
image_center_x = image_width/2
image_center_y = image_height/2
# Draw the text, mm = text center
draw.text((image_center_x, image_center_y), text, fill=font_color, font=font, anchor="mm")
# Convert the PIL image to a torch tensor
image_out = pil2tensor(new_img)
return (image_out,)
__init__.py
file
Add the node to the Hello World
node in the __init__.py
file
1. Add a class mapping for the "Hello World": HelloWorld,
__init__.py
file
2. Check the updated It should look like this:
from .nodes.nodes import *
NODE_CLASS_MAPPINGS = {
"Print Hello World": PrintHelloWorld,
"Concatenate Hello World": ConcatenateHelloWorld,
"Hello World Overlay Text": HelloWorldOverlayText,
}
print("\033[34mComfyUI Tutorial Nodes: \033[92mLoaded\033[0m")