From 0918dfef073407d4c210648bfceb2e7903b77e0a Mon Sep 17 00:00:00 2001 From: Yanick112 Date: Fri, 14 Feb 2025 19:41:30 +0800 Subject: [PATCH] 2025-02-14-19:41:28 --- __init__.py | 6 +- __pycache__/__init__.cpython-312.pyc | Bin 0 -> 580 bytes __pycache__/svgnode.cpython-312.pyc | Bin 0 -> 10191 bytes svgnode.py | 87 +++++++++++++++++++-------- 4 files changed, 65 insertions(+), 28 deletions(-) create mode 100644 __pycache__/__init__.cpython-312.pyc create mode 100644 __pycache__/svgnode.cpython-312.pyc diff --git a/__init__.py b/__init__.py index d1dc8b5..276c8f5 100644 --- a/__init__.py +++ b/__init__.py @@ -4,14 +4,16 @@ NODE_CLASS_MAPPINGS = { "ConvertRasterToVectorColor": ConvertRasterToVectorColor, "ConvertRasterToVectorBW": ConvertRasterToVectorBW, "ConvertVectorToRaster": ConvertVectorToRaster, - "SaveSVG": SaveSVG + "SaveSVG": SaveSVG, + "SVGPreview": SVGPreview, } NODE_DISPLAY_NAME_MAPPINGS = { "ConvertRasterToVectorColor": "Raster to Vector (SVG)Color", "ConvertRasterToVectorBW": "Raster to Vector (SVG)BW", "ConvertVectorToRaster": "Vector to Raster (SVG)", - "SaveSVG": "Save SVG" + "SaveSVG": "Save SVG", + "SVGPreview": "SVG Preview", } __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a9d7bba0cc7600b2d57480f6ca34466d587af10 GIT binary patch literal 580 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 WRXrpiz7V(uZu6y@-w=4P+4?UGmjFBf literal 0 HcmV?d00001 diff --git a/svgnode.py b/svgnode.py index e0839f9..feaacd5 100644 --- a/svgnode.py +++ b/svgnode.py @@ -10,6 +10,14 @@ from io import BytesIO import fitz +import numpy as np +import torch +import random +import folder_paths + +from PIL import Image +from nodes import SaveImage + # Tensor to PIL def tensor2pil(image): return Image.fromarray(np.clip(255. * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) @@ -37,7 +45,8 @@ class ConvertRasterToVectorColor: } } - RETURN_TYPES = ("LIST",) + RETURN_TYPES = ("STRING",) + OUTPUT_IS_LIST = (True,) FUNCTION = "convert_to_svg" CATEGORY = "💎TOSVG" @@ -92,7 +101,8 @@ class ConvertRasterToVectorBW: } } - RETURN_TYPES = ("LIST",) + RETURN_TYPES = ("STRING",) + OUTPUT_IS_LIST = (True,) FUNCTION = "convert_to_svg" CATEGORY = "💎TOSVG" @@ -133,7 +143,7 @@ class ConvertVectorToRaster: def INPUT_TYPES(cls): return { "required": { - "svg_strings": ("LIST", {"forceInput": True}) + "svg_strings": ("STRING", {"forceInput": True}) } } @@ -143,13 +153,12 @@ class ConvertVectorToRaster: def convert_svg_to_image(self, svg_strings): - for svg_string in svg_strings: - doc = fitz.open(stream=svg_string.encode('utf-8'), filetype="svg") - page = doc.load_page(0) - pix = page.get_pixmap() + doc = fitz.open(stream=svg_strings.encode('utf-8'), filetype="svg") + page = doc.load_page(0) + pix = page.get_pixmap() - image_data = pix.tobytes("png") - pil_image = Image.open(BytesIO(image_data)).convert("RGB") + image_data = pix.tobytes("png") + pil_image = Image.open(BytesIO(image_data)).convert("RGB") return (pil2tensor(pil_image),) @@ -162,7 +171,7 @@ class SaveSVG: def INPUT_TYPES(cls): return { "required": { - "svg_strings": ("LIST", {"forceInput": True}), + "svg_strings": ("STRING", {"forceInput": True}), "filename_prefix": ("STRING", {"default": "ComfyUI_SVG"}), }, "optional": { @@ -173,7 +182,6 @@ class SaveSVG: CATEGORY = "💎TOSVG" DESCRIPTION = "Save SVG data to a file." - RETURN_TYPES = () OUTPUT_NODE = True FUNCTION = "save_svg_file" @@ -190,21 +198,48 @@ class SaveSVG: output_path = custom_output_path if custom_output_path else self.output_dir os.makedirs(output_path, exist_ok=True) - ui_info_list = [] + unique_filename = self.generate_unique_filename(f"{filename_prefix}", append_timestamp) + final_filepath = os.path.join(output_path, unique_filename) + + + with open(final_filepath, "w") as svg_file: + svg_file.write(svg_strings) + + + ui_info = {"ui": {"saved_svg": unique_filename, "path": final_filepath}} - for index, svg_string in enumerate(svg_strings): - - unique_filename = self.generate_unique_filename(f"{filename_prefix}_{index}", append_timestamp) - final_filepath = os.path.join(output_path, unique_filename) - - - with open(final_filepath, "w") as svg_file: - svg_file.write(svg_string) - - - ui_info = {"ui": {"saved_svg": unique_filename, "path": final_filepath}} - ui_info_list.append(ui_info) - - return ui_info_list + return ui_info + + +class SVGPreview(SaveImage): + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "svg_strings": ("STRING", {"forceInput": True}) + } + } + + FUNCTION = "svg_preview" + CATEGORY = "💎TOSVG" + OUTPUT_NODE = True + + def __init__(self): + self.output_dir = folder_paths.get_temp_directory() + self.type = "temp" + self.prefix_append = "_temp_" + ''.join(random.choice("abcdefghijklmnopqrstupvxyz1234567890") for x in range(5)) + self.compress_level = 4 + + def svg_preview(self, svg_strings): + doc = fitz.open(stream=svg_strings.encode('utf-8'), filetype="svg") + page = doc.load_page(0) + pix = page.get_pixmap() + + image_data = pix.tobytes("png") + pil_image = Image.open(BytesIO(image_data)).convert("RGB") + + preview = pil2tensor(pil_image) + + return self.save_images(preview, "PointPreview") \ No newline at end of file