Skip to content

Tutorial 4 ‐ Hello World Overlay Text

Akatsuzi edited this page Dec 5, 2023 · 8 revisions

In this tutorial, we are going to build the Hello World node below

image

The node overlays text onto a color background and outputs an image.

Steps

1. Open the nodes.py file in Notepad++ or an IDE

  • 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 types
  • RETURN_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 function
  • CATEGORY 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,)

Add the node to the __init__.py file

1. Add a class mapping for the Hello World node in the __init__.py file

    "Hello World": HelloWorld,

2. Check the updated __init__.py file

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")    

3. You can now start ComfyUI to test the node

Clone this wiki locally