📱 CR Simple Meme Template¶
Documentation¶
- Class name:
CR Simple Meme Template
- Category:
🧩 Comfyroll Studio/👾 Graphics/📱 Template
- Output node:
False
This node is designed to facilitate the creation of simple meme templates, allowing users to easily generate memes by providing customizable text and image inputs. It abstracts the complexity of meme generation into a user-friendly interface, enabling quick and creative meme creation.
Input types¶
Required¶
image
- The 'image' input allows users to provide the base image on which the meme text will be overlaid. This is a crucial component for meme creation, setting the visual context for the text.
- Comfy dtype:
IMAGE
- Python dtype:
Image
preset
- The 'preset' input offers predefined meme formats that users can select to quickly generate popular meme styles, enhancing the ease of meme creation.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
text_top
- The 'text_top' input allows users to specify the text that appears at the top of the meme, enabling personalized messages or jokes.
- Comfy dtype:
STRING
- Python dtype:
str
text_bottom
- The 'text_bottom' input allows users to specify the text that appears at the bottom of the meme, complementing the top text for a complete meme experience.
- Comfy dtype:
STRING
- Python dtype:
str
font_name
- The 'font_name' input lets users choose the font style for the meme text, allowing for further customization of the meme's appearance.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
max_font_size
- The 'max_font_size' input determines the maximum size of the meme text, ensuring the text remains readable and visually appealing.
- Comfy dtype:
INT
- Python dtype:
int
font_color
- The 'font_color' input allows users to select the color of the meme text, enabling visual contrast and emphasis.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
font_outline
- The 'font_outline' input provides options for adding an outline to the meme text, enhancing readability against varied backgrounds.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
bar_color
- The 'bar_color' input enables users to choose the color of optional bars that can be added to the top and/or bottom of the meme for aesthetic or thematic purposes.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
bar_options
- The 'bar_options' input allows users to select the placement of optional bars in the meme, offering additional layout customization.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
Optional¶
font_color_hex
- The 'font_color_hex' input offers an alternative way to specify the meme text color using hexadecimal color codes, providing precise color customization.
- Comfy dtype:
STRING
- Python dtype:
str
bar_color_hex
- The 'bar_color_hex' input offers an alternative way to specify the color of optional bars using hexadecimal color codes, allowing for precise color matching.
- Comfy dtype:
STRING
- Python dtype:
str
Output types¶
image
- Comfy dtype:
IMAGE
- The 'image' output represents the final meme generated by the node, ready for sharing or further use.
- Python dtype:
Image
- Comfy dtype:
show_help
- Comfy dtype:
STRING
- The 'show_help' output provides guidance or additional information about the meme generation process, assisting users in creating their desired memes.
- Python dtype:
str
- Comfy dtype:
Usage tips¶
- Infra type:
CPU
- Common nodes:
Source code¶
class CR_SimpleMemeTemplate:
@classmethod
def INPUT_TYPES(s):
font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "fonts")
file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith(".ttf")]
bar_opts = ["no bars", "top", "bottom", "top and bottom"]
simple_meme_presets = ["custom",
"One Does Not Simply ... MEME IN COMFY",
"This is fine.",
"Good Morning ... No Such Thing!"]
return {"required": {
"image": ("IMAGE",),
"preset": (simple_meme_presets,),
"text_top": ("STRING", {"multiline": True, "default": "text_top"}),
"text_bottom": ("STRING", {"multiline": True, "default": "text_bottom"}),
"font_name": (file_list,),
"max_font_size": ("INT", {"default": 150, "min": 20, "max": 2048}),
"font_color": (COLORS,),
"font_outline": (["none", "thin", "thick", "extra thick"],),
"bar_color": (COLORS,),
"bar_options": (bar_opts,),
},
"optional": {
"font_color_hex": ("STRING", {"multiline": False, "default": "#000000"}),
"bar_color_hex": ("STRING", {"multiline": False, "default": "#000000"})
}
}
RETURN_TYPES = ("IMAGE", "STRING", )
RETURN_NAMES = ("image", "show_help", )
FUNCTION = "make_meme"
CATEGORY = icons.get("Comfyroll/Graphics/Template")
def make_meme(self, image, preset,
text_top, text_bottom,
font_name, max_font_size, font_color, font_outline,
bar_color, bar_options,
font_color_hex='#000000', bar_color_hex='#000000'):
# Get RGB values for the text and bar colors
text_color = get_color_values(font_color, font_color_hex, color_mapping)
bar_color = get_color_values(bar_color, bar_color_hex, color_mapping)
total_images = []
for img in image:
# Calculate the height factor
if bar_options == "top":
height_factor = 1.2
elif bar_options == "bottom":
height_factor = 1.2
elif bar_options == "top and bottom":
height_factor = 1.4
else:
height_factor = 1.0
if preset == "One Does Not Simply ... MEME IN COMFY":
text_top = "One Does Not Simply"
text_bottom = "MEME IN COMFY"
if preset == "This is fine.":
text_top = "This is fine."
text_bottom = ""
if preset == "Good Morning ... No Such Thing!":
text_top = "Good Morning"
text_bottom = "\"No Such Thing!\""
# Create PIL images for the image and text bars
back_image = tensor2pil(img)
size = back_image.width, int(back_image.height * height_factor)
result_image = Image.new("RGB", size)
# Define font settings
#font_file = "fonts\\" + str(font_name)
font_file = os.path.join("fonts", font_name)
resolved_font_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), font_file)
# Create the drawing context
draw = ImageDraw.Draw(result_image)
# Create two color bars at the top and bottom
bar_width = back_image.width
bar_height = back_image.height // 5 ### add parameter for this in adv node
top_bar = Image.new("RGB", (bar_width, bar_height), bar_color)
bottom_bar = Image.new("RGB", (bar_width, bar_height), bar_color)
# Composite the result image onto the input image
if bar_options == "top" or bar_options == "top and bottom":
image_out = result_image.paste(back_image, (0, bar_height))
else:
image_out = result_image.paste(back_image, (0, 0))
# Get the font size and draw the text
if bar_options == "top" or bar_options == "top and bottom":
result_image.paste(top_bar, (0, 0))
font_top = get_font_size(draw, text_top, bar_width, bar_height, resolved_font_path, max_font_size)
draw_text_on_image(draw, 0, bar_width, bar_height, text_top, font_top, text_color, font_outline)
if bar_options == "bottom" or bar_options == "top and bottom":
result_image.paste(bottom_bar, (0, (result_image.height - bar_height)))
font_bottom = get_font_size(draw, text_bottom, bar_width, bar_height, resolved_font_path, max_font_size)
if bar_options == "bottom":
y_position = back_image.height
else:
y_position = bar_height + back_image.height
draw_text_on_image(draw, y_position, bar_width, bar_height, text_bottom, font_bottom, text_color, font_outline)
# Overlay text on image
if bar_options == "bottom" and text_top > "":
font_top = get_font_size(draw, text_top, bar_width, bar_height, resolved_font_path, max_font_size)
draw_text_on_image(draw, 0, bar_width, bar_height, text_top, font_top, text_color, font_outline)
if (bar_options == "top" or bar_options == "none") and text_bottom > "":
font_bottom = get_font_size(draw, text_bottom, bar_width, bar_height, resolved_font_path, max_font_size)
y_position = back_image.height
draw_text_on_image(draw, y_position, bar_width, bar_height, text_bottom, font_bottom, text_color, font_outline)
if bar_options == "no bars" and text_bottom > "":
font_bottom = get_font_size(draw, text_bottom, bar_width, bar_height, resolved_font_path, max_font_size)
y_position = back_image.height - bar_height
draw_text_on_image(draw, y_position, bar_width, bar_height, text_bottom, font_bottom, text_color, font_outline)
if bar_options == "no bars" and text_top > "":
font_top = get_font_size(draw, text_top, bar_width, bar_height, resolved_font_path, max_font_size)
draw_text_on_image(draw, 0, bar_width, bar_height, text_top, font_top, text_color, font_outline)
#image_out = np.array(result_image).astype(np.float32) / 255.0
#image_out = torch.from_numpy(image_out).unsqueeze(0)
# Convert the PIL image back to a torch tensor
#return (pil2tensor(image_out), show_help, )
#return (image_out, show_help, )
# Convert to tensor
out_image = np.array(result_image.convert("RGB")).astype(np.float32) / 255.0
out_image = torch.from_numpy(out_image).unsqueeze(0)
total_images.append(out_image)
# Batch the images
images_out = torch.cat(total_images, 0)
show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Template-Nodes#cr-simple-meme-template"
return (images_out, show_help, )