| |
| |
| |
| |
|
|
| import numpy as np |
| import torch |
| import os |
| from PIL import Image, ImageDraw, ImageOps, ImageFont |
| from ..categories import icons |
| from ..config import color_mapping, COLORS |
| from ..nodes.graphics_functions import (hex_to_rgb, |
| get_color_values, |
| text_panel, |
| combine_images, |
| apply_outline_and_border, |
| get_font_size, |
| draw_text_on_image, |
| crop_and_resize_image) |
|
|
| 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")] |
|
|
| |
| |
| |
| |
| |
|
|
| |
| |
| ALIGN_OPTIONS = ["top", "center", "bottom"] |
| ROTATE_OPTIONS = ["text center", "image center"] |
| JUSTIFY_OPTIONS = ["left", "center", "right"] |
| PERSPECTIVE_OPTIONS = ["top", "bottom", "left", "right"] |
|
|
| |
|
|
| def tensor2pil(image): |
| return Image.fromarray(np.clip(255. * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) |
|
|
| def pil2tensor(image): |
| return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0) |
| |
| |
| class CR_MultiPanelMemeTemplate: |
|
|
| @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")] |
| templates = ["vertical - 2 image + 2 text", |
| "vertical - 3 image + 3 text", |
| "vertical - 4 image + 4 text", |
| "horizontal - 2 image + 2 text", |
| "horizontal - text bar + 2 image", |
| "text bar + 1 image with overlay text", |
| "text bar + 4 image", |
| "text bar + 4 image with overlay text"] |
| colors = COLORS[1:] |
| |
| return {"required": { |
| "template": (templates,), |
| "image_1": ("IMAGE",), |
| "text_1": ("STRING", {"multiline": True, "default": "text_1"}), |
| "text_2": ("STRING", {"multiline": True, "default": "text_2"}), |
| "text_3": ("STRING", {"multiline": True, "default": "text_3"}), |
| "text_4": ("STRING", {"multiline": True, "default": "text_4"}), |
| "font_name": (file_list,), |
| "font_size": ("INT", {"default": 50, "min": 1, "max": 1024}), |
| "font_color": (colors,), |
| "bar_color": (colors,), |
| "reverse_panels": (["No", "Yes"],), |
| }, |
| "optional": { |
| "image_2": ("IMAGE",), |
| "image_3": ("IMAGE",), |
| "image_4": ("IMAGE",), |
| } |
| } |
|
|
| RETURN_TYPES = ("IMAGE", "STRING", ) |
| RETURN_NAMES = ("image", "show_help", ) |
| FUNCTION = "draw_text" |
| CATEGORY = icons.get("Comfyroll/Graphics/Template") |
|
|
| def draw_text(self, template, image_1, text_1, text_2, text_3, text_4, |
| font_name, font_size, font_color, bar_color, reverse_panels, image_2 = None, image_3 = None, image_4 = None): |
| |
| show_help = "example help text" |
| |
| |
| return image_1, show_help, |
|
|
| |
| class CR_PopularMemeTemplates: |
|
|
| @classmethod |
| def INPUT_TYPES(s): |
|
|
| templates = ["Expanding brain", |
| "My honest reaction", |
| "The GF I want", |
| "Who would win?", |
| "I have 4 sides", |
| "This is Fine", |
| "Is This a Pigeon?", |
| "Drake hotline bling"] |
| colors = COLORS[1:] |
| |
| return {"required": { |
| "meme": (templates,), |
| "image_1": ("IMAGE",), |
| |
| "text_1": ("STRING", {"multiline": True, "default": "text_1"}), |
| "text_2": ("STRING", {"multiline": True, "default": "text_2"}), |
| "text_3": ("STRING", {"multiline": True, "default": "text_3"}), |
| "text_4": ("STRING", {"multiline": True, "default": "text_4"}), |
| "font_name": (file_list,), |
| "font_size": ("INT", {"default": 50, "min": 1, "max": 1024}), |
| "font_color": (colors,), |
| }, |
| "optional": { |
| "image_2": ("IMAGE",), |
| "image_3": ("IMAGE",), |
| "image_4": ("IMAGE",), |
| } |
| } |
|
|
| RETURN_TYPES = ("IMAGE", "STRING", ) |
| RETURN_NAMES = ("image", "show_help", ) |
| FUNCTION = "draw_text" |
| CATEGORY = icons.get("Comfyroll/Graphics/Template") |
|
|
| def draw_text(self, meme, image_1, text_1, text_2, text_3, text_4, |
| font_name, font_size, font_color, image_2 = None, image_3 = None, image_4 = None): |
|
|
| show_help = "example help text" |
| |
| |
| return image_1, show_help, |
|
|
| |
| class CR_DrawPerspectiveText: |
| |
| @classmethod |
| def INPUT_TYPES(s): |
| |
| 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": "text"}), |
| "font_name": (file_list,), |
| "font_size": ("INT", {"default": 50, "min": 1, "max": 1024}), |
| "font_color": (COLORS,), |
| "background_color": (COLORS,), |
| "align": (ALIGN_OPTIONS,), |
| "justify": (JUSTIFY_OPTIONS,), |
| "margins": ("INT", {"default": 0, "min": -1024, "max": 1024}), |
| "line_spacing": ("INT", {"default": 0, "min": -1024, "max": 1024}), |
| "position_x": ("INT", {"default": 0, "min": -4096, "max": 4096}), |
| "position_y": ("INT", {"default": 0, "min": -4096, "max": 4096}), |
| "perspective_factor": ("FLOAT", {"default": 0.00, "min": 0.00, "max": 1.00, "step": 0.01}), |
| "perspective_direction": (PERSPECTIVE_OPTIONS,), |
| }, |
| "optional": { |
| "font_color_hex": ("STRING", {"multiline": False, "default": "#000000"}), |
| "bg_color_hex": ("STRING", {"multiline": False, "default": "#000000"}) |
| } |
| } |
|
|
| RETURN_TYPES = ("IMAGE", "STRING", ) |
| RETURN_NAMES = ("image", "show_help", ) |
| FUNCTION = "draw_text" |
| CATEGORY = icons.get("Comfyroll/Graphics/Text") |
|
|
| def draw_text(self, image_width, image_height, text, |
| font_name, font_size, font_color, background_color, |
| margins, line_spacing, |
| position_x, position_y, |
| align, justify, |
| perspective_factor, perspective_direction, |
| font_color_hex='#000000', bg_color_hex='#000000'): |
|
|
| |
| text_color = get_color_values(font_color, font_color_hex, color_mapping) |
| bg_color = get_color_values(background_color, bg_color_hex, color_mapping) |
| |
| |
| size = (image_width, image_height) |
| text_image = Image.new('RGB', size, text_color) |
| back_image = Image.new('RGB', size, bg_color) |
| text_mask = Image.new('L', back_image.size) |
|
|
| |
| text_mask = draw_masked_text_v2(text_mask, text, font_name, font_size, |
| margins, line_spacing, |
| position_x, position_y, |
| align, justify, |
| perspective_factor, perspective_direction) |
|
|
| |
| image_out = Image.composite(text_image, back_image, text_mask) |
| preview_out = text_mask |
| |
| show_help = "example help text" |
| |
| |
| return pil2tensor(image_out), pil2tensor(preview_out), show_help, |
|
|
| |
| class CR_SimpleAnnotations: |
|
|
| @classmethod |
| def INPUT_TYPES(s): |
|
|
| bar_opts = ["top", "bottom", "top and bottom", "no bars"] |
| |
| return {"required": { |
| "image": ("IMAGE",), |
| "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": 100, "min": 50, "max": 150}), |
| "font_color": (COLORS,), |
| "bar_color": (COLORS,), |
| "bar_options": (bar_opts,), |
| "bar_scaling_factor": ("FLOAT", {"default": 0.2, "min": 0.1, "max": 2, "step": 0.1}), |
| }, |
| "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/Text") |
|
|
| def make_meme(self, image, |
| text_top, text_bottom, |
| font_name, max_font_size, |
| font_color, bar_color, bar_options, bar_scaling_factor, |
| font_color_hex='#000000', |
| bar_color_hex='#000000'): |
|
|
| text_color = get_color_values(font_color, font_color_hex, color_mapping) |
| bar_color = get_color_values(bar_color, bar_color_hex, color_mapping) |
|
|
| |
| image_3d = image[0, :, :, :] |
|
|
| |
| if bar_options == "top": |
| height_factor = 1 + bar_scaling_factor |
| elif bar_options == "bottom": |
| height_factor = 1 + bar_scaling_factor |
| elif bar_options == "top and bottom": |
| height_factor = 1 + 2 * bar_scaling_factor |
| else: |
| height_factor = 1.0 |
|
|
| |
| back_image = tensor2pil(image_3d) |
| size = back_image.width, int(back_image.height * height_factor) |
| result_image = Image.new("RGB", size) |
|
|
| |
| font_file = "fonts\\" + str(font_name) |
| resolved_font_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), font_file) |
| |
| |
| draw = ImageDraw.Draw(result_image) |
| |
| |
| bar_width = back_image.width |
| bar_height = back_image.height // 5 |
| top_bar = Image.new("RGB", (bar_width, bar_height), bar_color) |
| bottom_bar = Image.new("RGB", (bar_width, bar_height), bar_color) |
|
|
| |
| 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)) |
| |
| |
| 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, "No") |
| |
| 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, "No") |
|
|
| |
| 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, "No") |
|
|
| 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, "No") |
|
|
| if 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 - bar_height |
| draw_text_on_image(draw, y_position, bar_width, bar_height, text_bottom, font_bottom, text_color, "No") |
| |
| show_help = "example help text" |
| |
| image_out = np.array(result_image).astype(np.float32) / 255.0 |
| image_out = torch.from_numpy(image_out).unsqueeze(0) |
| |
| |
| |
| return (image_out, show_help, ) |
|
|
| |
| class CR_ApplyAnnotations: |
|
|
| @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"] |
| |
| return {"required": { |
| "image": ("IMAGE", ), |
| "annotation_stack": ("ANNOTATION_STACK", ), |
| } |
| } |
|
|
| RETURN_TYPES = ("IMAGE", "STRING", ) |
| RETURN_NAMES = ("image", "show_help", ) |
| FUNCTION = "apply_annotations" |
| CATEGORY = icons.get("Comfyroll/Graphics/Text") |
|
|
| def apply_annotations(self, image, annotation_stack): |
|
|
| show_help = "example help text" |
|
|
| return (image_out, show_help, ) |
|
|
| |
| class CR_AddAnnotation: |
|
|
| @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"] |
| |
| return {"required": { |
| "text": ("STRING", {"multiline": True, "default": "text_top"}), |
| "font_name": (file_list,), |
| "font_size": ("INT", {"default": 100, "min": 20, "max": 150}), |
| "font_color": (COLORS,), |
| "position_x": ("INT", {"default": 0, "min": 0, "max": 4096}), |
| "position_y": ("INT", {"default": 0, "min": 0, "max": 4096}), |
| "justify": (JUSTIFY_OPTIONS,), |
| }, |
| "optional": { |
| "annotation_stack": ("ANNOTATION_STACK",), |
| "font_color_hex": ("STRING", {"multiline": False, "default": "#000000"}), |
| } |
| } |
|
|
| RETURN_TYPES = ("ANNOTATION_STACK", "STRING", ) |
| RETURN_NAMES = ("ANNOTATION_STACK", "show_help", ) |
| FUNCTION = "add_annotation" |
| CATEGORY = icons.get("Comfyroll/Graphics/Text") |
|
|
| def add_annotation(self, image, |
| font_name, font_size, font_color, |
| position_x, position_y, justify, |
| annotation_stack=None, font_color_hex='#000000'): |
| |
| show_help = "example help text" |
| |
| return (annotation_stack, show_help, ) |
| |
| |
| class CR_SimpleImageWatermark: |
| |
| @classmethod |
| def INPUT_TYPES(cls): |
| |
| ALIGN_OPTIONS = ["center", "top left", "top center", "top right", "bottom left", "bottom center", "bottom right"] |
|
|
| return {"required": { |
| "image": ("IMAGE",), |
| "watermark_image": ("IMAGE",), |
| "watermark_scale": ("FLOAT", {"default": 1, "min": 0.1, "max": 5.00, "step": 0.01}), |
| "opacity": ("FLOAT", {"default": 0.30, "min": 0.00, "max": 1.00, "step": 0.01}), |
| "align": (ALIGN_OPTIONS,), |
| "x_margin": ("INT", {"default": 20, "min": -1024, "max": 1024}), |
| "y_margin": ("INT", {"default": 20, "min": -1024, "max": 1024}), |
| } |
| } |
|
|
| RETURN_TYPES = ("IMAGE", ) |
| FUNCTION = "overlay_image" |
| CATEGORY = icons.get("Comfyroll/Graphics/Layout") |
|
|
| def overlay_image(self, image, watermark_image, watermark_scale, opacity, align, x_margin, y_margin): |
| |
| |
| image = tensor2pil(image) |
| watermark_image = tensor2pil(watermark_image) |
| |
| |
| image = image.convert("RGBA") |
| watermark = watermark_image.convert("RGBA") |
|
|
| |
| watermark = watermark.resize(image.size) |
|
|
| |
| watermark_layer = Image.new("RGBA", image.size, (0, 0, 0, 0)) |
| draw = ImageDraw.Draw(watermark_layer) |
|
|
| |
| if align == 'center': |
| watermark_pos = ((image.width - watermark.width) // 2, (image.height - watermark.height) // 2) |
| elif align == 'top left': |
| watermark_pos = (x_margin, y_margin) |
| elif align == 'top center': |
| watermark_pos = ((image.width - watermark.width) // 2, y_margin) |
| elif align == 'top right': |
| watermark_pos = (image.width - watermark.width - x_margin, y_margin) |
| elif align == 'bottom left': |
| watermark_pos = (x_margin, image.height - watermark.height - y_margin) |
| elif align == 'bottom center': |
| watermark_pos = ((image.width - watermark.width) // 2, image.height - watermark.height - y_margin) |
| elif align == 'bottom right': |
| watermark_pos = (image.width - watermark.width - x_margin, image.height - watermark.height - y_margin) |
|
|
| |
| |
|
|
| |
| |
| |
| |
| if opacity != 1: |
| watermark_layer = reduce_opacity(watermark_layer, opacity) |
| |
| |
| image_out = Image.composite(watermark_layer, image, watermark_layer) |
|
|
| |
| return pil2tensor(image_out) |
|
|
| |
| class CR_ComicPanelTemplatesAdvanced: |
|
|
| @classmethod |
| def INPUT_TYPES(s): |
| |
| directions = ["left to right", "right to left"] |
|
|
| templates = ["custom", |
| "G22", "G33", |
| "H2", "H3", |
| "H12", "H13", |
| "H21", "H23", |
| "H31", "H32", |
| "V2", "V3", |
| "V12", "V13", |
| "V21", "V23", |
| "V31", "V32"] |
| |
| return {"required": { |
| "page_width": ("INT", {"default": 512, "min": 8, "max": 4096}), |
| "page_height": ("INT", {"default": 512, "min": 8, "max": 4096}), |
| "template": (templates,), |
| "reading_direction": (directions,), |
| "border_thickness": ("INT", {"default": 5, "min": 0, "max": 1024}), |
| "outline_thickness": ("INT", {"default": 2, "min": 0, "max": 1024}), |
| "outline_color": (COLORS,), |
| "panel_color": (COLORS,), |
| "background_color": (COLORS,), |
| }, |
| "optional": { |
| "images1": ("IMAGE",), |
| "images2": ("IMAGE",), |
| "images3": ("IMAGE",), |
| "images4": ("IMAGE",), |
| "custom_panel_layout": ("STRING", {"multiline": False, "default": "H123"}), |
| "outline_color_hex": ("STRING", {"multiline": False, "default": "#000000"}), |
| "panel_color_hex": ("STRING", {"multiline": False, "default": "#000000"}), |
| "bg_color_hex": ("STRING", {"multiline": False, "default": "#000000"}), |
| } |
| } |
|
|
| RETURN_TYPES = ("IMAGE", "STRING", ) |
| RETURN_NAMES = ("image", "show_help", ) |
| FUNCTION = "layout" |
| CATEGORY = icons.get("Comfyroll/Graphics/Template") |
| |
| def layout(self, page_width, page_height, template, reading_direction, |
| border_thickness, outline_thickness, |
| outline_color, panel_color, background_color, |
| images1=None, images2=None, images3=None, images4=None, custom_panel_layout='G44', |
| outline_color_hex='#000000', panel_color_hex='#000000', bg_color_hex='#000000'): |
|
|
| |
|
|
| panels = [] |
| k = 0 |
| batches = 0 |
| |
| |
| if images1 is not None: |
| images1 = [tensor2pil(image) for image in images1] |
| len_images1 = len(images1) |
| batches+=1 |
| |
| if images2 is not None: |
| images2 = [tensor2pil(image) for image in images2] |
| len_images2 = len(images2) |
| batches+=1 |
| |
| if images3 is not None: |
| images3 = [tensor2pil(image) for image in images3] |
| len_images3 = len(images3) |
| batches+=1 |
| |
| if images4 is not None: |
| images4 = [tensor2pil(image) for image in images4] |
| len_images4 = len(images4) |
| batches+=1 |
|
|
| |
| outline_color = get_color_values(outline_color, outline_color_hex, color_mapping) |
| panel_color = get_color_values(panel_color, panel_color_hex, color_mapping) |
| bg_color = get_color_values(background_color, bg_color_hex, color_mapping) |
|
|
| |
| size = (page_width - (2 * border_thickness), page_height - (2 * border_thickness)) |
| page = Image.new('RGB', size, bg_color) |
| draw = ImageDraw.Draw(page) |
| |
| if template == "custom": |
| template = custom_panel_layout |
| |
| |
| first_char = template[0] |
| if first_char == "G": |
| rows = int(template[1]) |
| columns = int(template[2]) |
| panel_width = (page.width - (2 * columns * (border_thickness + outline_thickness))) // columns |
| panel_height = (page.height - (2 * rows * (border_thickness + outline_thickness))) // rows |
| |
| |
| |
| for i in range(rows): |
| |
| for j in range(columns): |
| |
| create_and_paste_panel(page, border_thickness, outline_thickness, |
| panel_width, panel_height, page.width, |
| panel_color, bg_color, outline_color, |
| images1, i, j, k, len_images1, reading_direction) |
| k += 1 |
|
|
| elif first_char == "H": |
| rows = len(template) - 1 |
| panel_height = (page.height - (2 * rows * (border_thickness + outline_thickness))) // rows |
| |
| |
| |
| for i in range(rows): |
| columns = int(template[i+1]) |
| panel_width = (page.width - (2 * columns * (border_thickness + outline_thickness))) // columns |
| |
| for j in range(columns): |
| |
| create_and_paste_panel(page, border_thickness, outline_thickness, |
| panel_width, panel_height, page.width, |
| panel_color, bg_color, outline_color, |
| images1, i, j, k, len_images1, reading_direction) |
| k += 1 |
| |
| elif first_char == "V": |
| columns = len(template) - 1 |
| panel_width = (page.width - (2 * columns * (border_thickness + outline_thickness))) // columns |
| |
| |
| |
| for j in range(columns): |
| rows = int(template[j+1]) |
| panel_height = (page.height - (2 * rows * (border_thickness + outline_thickness))) // rows |
| |
| for i in range(rows): |
| |
| create_and_paste_panel(page, border_thickness, outline_thickness, |
| panel_width, panel_height, page.width, |
| panel_color, bg_color, outline_color, |
| images1, i, j, k, len_images1, reading_direction) |
| k += 1 |
| |
| |
| if border_thickness > 0: |
| page = ImageOps.expand(page, border_thickness, bg_color) |
| |
| show_help = "example help text" |
|
|
| return (pil2tensor(page), show_help, ) |
| |
| |
| ''' |
| class CR_ASCIIPattern: |
| |
| @classmethod |
| def INPUT_TYPES(s): |
| |
| return {"required": { |
| "image": ("IMAGE",), |
| } |
| } |
| |
| RETURN_TYPES = ("STRING", "STRING", ) |
| RETURN_NAMES = ("multiline_text", "show_help", ) |
| FUNCTION = "draw_pattern" |
| CATEGORY = icons.get("Comfyroll/Graphics/Pattern") |
| |
| def draw_pattern(self, image): |
| |
| pixel_ascii_map = "`^\",:;Il!i~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$" |
| |
| im = image |
| x = list(im.getdata()) |
| for pixel in iter(x): |
| x = sum(pixel) // 3 # integer division |
| x = (x * len(pixel_ascii_map)) // 255 # rescaling |
| ascii_val = pixel_ascii_map[x] |
| |
| text_out = ascii_val |
| |
| show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Text-Nodes#cr-ascii-pattern" |
| |
| # Convert the PIL image back to a torch tensor |
| return (text_out, show_help, ) |
| ''' |
| |
| |
| |
| |
| ''' |
| NODE_CLASS_MAPPINGS = { |
| "CR Multi-Panel Meme Template": CR_MultiPanelMemeTemplate, |
| "CR Popular Meme Templates": CR_PopularMemeTemplates, |
| "CR Draw Perspective Text": CR_DrawPerspectiveText, |
| "CR Simple Annotations": CR_SimpleAnnotations, |
| "CR Apply Annotations": CR_ApplyAnnotations, |
| "CR Add Annotation": CR_AddAnnotation, |
| "CR Simple Image Watermark": CR_SimpleImageWatermark, |
| "CR Comic Panel Templates Advanced": CR_ComicPanelTemplatesAdvanced, |
| "CR ASCII Pattern": CR_ASCIIPattern, |
| } |
| ''' |
|
|
|
|