From bfced5b4da6f31dc9c4f82aa8a34c6cb36885a1f Mon Sep 17 00:00:00 2001 From: shadowcz007 Date: Fri, 29 Dec 2023 12:49:05 +0800 Subject: [PATCH] test --- __init__.py | 6 +- data/extension-node-map.json | 8 ++- nodes/ImageNode.py | 98 ++++++++++++++++++++++++++++- nodes/ShareNode.py | 37 +++++++++++ nodes/Utils.py | 3 + web/javascript/share_mixlab.js | 110 +++++++++++++++++++++++++++++++++ 6 files changed, 256 insertions(+), 6 deletions(-) create mode 100644 nodes/ShareNode.py create mode 100644 web/javascript/share_mixlab.js diff --git a/__init__.py b/__init__.py index c277074..7837790 100644 --- a/__init__.py +++ b/__init__.py @@ -359,14 +359,14 @@ PromptServer.add_routes=new_add_routes # 导入节点 from .nodes.PromptNode import RandomPrompt -from .nodes.ImageNode import NoiseImage,TransparentImage,LoadImagesFromPath,LoadImagesFromURL,ResizeImage,TextImage,SvgImage,Image3D,EmptyLayer,ShowLayer,NewLayer,MergeLayers,AreaToMask,SmoothMask,FeatheredMask,SplitLongMask,ImageCropByAlpha,EnhanceImage,FaceToMask +from .nodes.ImageNode import NoiseImage,TransparentImage,LoadImagesFromPath,LoadImagesFromURL,UploadImageForSMMS,ResizeImage,TextImage,SvgImage,Image3D,EmptyLayer,ShowLayer,NewLayer,MergeLayers,AreaToMask,SmoothMask,FeatheredMask,SplitLongMask,ImageCropByAlpha,EnhanceImage,FaceToMask from .nodes.Vae import VAELoader,VAEDecode from .nodes.ScreenShareNode import ScreenShareNode,FloatingVideo from .nodes.Clipseg import CLIPSeg,CombineMasks from .nodes.ChatGPT import ChatGPTNode,ShowTextForGPT,CharacterInText from .nodes.Audio import GamePal,SpeechRecognition,SpeechSynthesis from .nodes.Utils import AppInfo,IntNumber,FloatSlider,TextInput,ColorInput,FontInput,TextToNumber,DynamicDelayProcessor,LimitNumber,SwitchByIndex,GetImageSize_,MultiplicationNode - +from .nodes.ShareNode import ShareToWeibo # 要导出的所有节点及其名称的字典 # 注意:名称应全局唯一 @@ -413,6 +413,8 @@ NODE_CLASS_MAPPINGS = { "GetImageSize_":GetImageSize_, "SwitchByIndex":SwitchByIndex, "LimitNumber":LimitNumber, + # "UploadImageForSMMS":UploadImageForSMMS, + "ShareToWeibo":ShareToWeibo # "GamePal":GamePal } diff --git a/data/extension-node-map.json b/data/extension-node-map.json index 14bc5de..ae47d4b 100644 --- a/data/extension-node-map.json +++ b/data/extension-node-map.json @@ -4798,7 +4798,13 @@ "VAELoaderConsistencyDecoder", "TextToNumber", "TextInput_", - "DynamicDelayProcessor" + "DynamicDelayProcessor", + "MultiplicationNode", + "ShareToWeibo", + "LimitNumber", + "SwitchByIndex", + "UploadImageForSMMS", + "GetImageSize_" ], { "title_aux": "comfyui-mixlab-nodes" diff --git a/nodes/ImageNode.py b/nodes/ImageNode.py index 15a5fa9..d99b244 100644 --- a/nodes/ImageNode.py +++ b/nodes/ImageNode.py @@ -560,7 +560,7 @@ def base64_to_image(base64_string): return image -def create_temp_file(image): +def create_temp_file(image,fn='material'): output_dir = folder_paths.get_temp_directory() ( @@ -569,7 +569,7 @@ def create_temp_file(image): counter, subfolder, _, - ) = folder_paths.get_save_image_path('material', output_dir) + ) = folder_paths.get_save_image_path(fn, output_dir) image=tensor2pil(image) @@ -586,6 +586,42 @@ def create_temp_file(image): "type": "temp" }] +def create_temp_file_for_upload(image,fn='tmp'): + output_dir = folder_paths.get_temp_directory() + + ( + full_output_folder, + filename, + counter, + subfolder, + _, + ) = folder_paths.get_save_image_path(fn, output_dir) + + + image=tensor2pil(image) + + image_file = f"{filename}_{counter:05}.png" + + image_path=os.path.join(full_output_folder, image_file) + + image.save(image_path,compress_level=4) + + return image_path + + +def upload_smms(fp,token): + # print(json.dumps(res, indent=4)) + image_url='' + try: + headers = {'Authorization': token} + files = {'smfile': open(fp, 'rb')} + url = 'https://sm.ms/api/v2/upload' + res = requests.post(url, files=files, headers=headers).json() + image_url=res['data']['url'] + except: + print('upload error') + return image_url + class SmoothMask: @classmethod @@ -1676,4 +1712,60 @@ class ResizeImage: im=pil2tensor(im) - return (im,) \ No newline at end of file + return (im,) + + + + +class UploadImageForSMMS: + @classmethod + def INPUT_TYPES(s): + return {"required": { + "image": ("IMAGE",), + "token": ("STRING",{"multiline": False,"default": "","dynamicPrompts": False}), + }, + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("url",) + + FUNCTION = "run" + + CATEGORY = "♾️Mixlab/image" + + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self,image,token): + # print(image,token) + fp=create_temp_file_for_upload(image) + + url=upload_smms(fp,token) + + return (url,) + + +# 压缩到5M +# from PIL import Image +# import os + +# def compress_image(input_image_path, output_image_path): +# image = Image.open(input_image_path) +# image.save(output_image_path, optimize=True, quality=50) + +# def get_image_size(image_path): +# return os.path.getsize(image_path) / (1024 * 1024) # 将文件大小从字节转换为兆字节 + +# def compress_to_5mb(input_image_path, output_image_path): +# compress_image(input_image_path, output_image_path) +# max_iterations = 10 # 设置最大循环次数 +# iterations = 0 +# while get_image_size(output_image_path) > 5 and iterations < max_iterations: +# compress_image(output_image_path, output_image_path) +# iterations += 1 + +# # 示例用法 +# input_image_path = "input.jpg" +# output_image_path = "output.jpg" +# compress_to_5mb(input_image_path, output_image_path) + diff --git a/nodes/ShareNode.py b/nodes/ShareNode.py new file mode 100644 index 0000000..95ab57c --- /dev/null +++ b/nodes/ShareNode.py @@ -0,0 +1,37 @@ + +import urllib.parse + + +# 分享到微博 +class ShareToWeibo: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "title":("STRING",{"multiline": True,"default": "","dynamicPrompts": False}), + "pic_url":("STRING",{"multiline": False,"default": "","dynamicPrompts": False}), + "url":("STRING",{"multiline": False,"default": "","dynamicPrompts": False}), + } + } + + RETURN_TYPES = () + # RETURN_NAMES = ("number",) + + FUNCTION = "run" + + CATEGORY = "♾️Mixlab/share" + + INPUT_IS_LIST = False + OUTPUT_NODE = True + # OUTPUT_IS_LIST = () + + def run(self, title, pic_url, url): + encoded_title = urllib.parse.quote(title) + encoded_pic_url = urllib.parse.quote(pic_url) + encoded_url = urllib.parse.quote(url) + url = "https://service.weibo.com/share/share.php?title={}&pic={}&url={}".format(encoded_title,encoded_pic_url,encoded_url) + print(url) + return {"ui": {"url": [url]}, "result": ()} + + + diff --git a/nodes/Utils.py b/nodes/Utils.py index 65d4f61..5c4f100 100644 --- a/nodes/Utils.py +++ b/nodes/Utils.py @@ -397,6 +397,7 @@ class AppInfo: INPUT_IS_LIST = False OUTPUT_IS_LIST = (False,) + OUTPUT_NODE = True def run(self,name,image,input_ids,output_ids,description,version): @@ -524,3 +525,5 @@ class LimitNumber: return (nn,) + + \ No newline at end of file diff --git a/web/javascript/share_mixlab.js b/web/javascript/share_mixlab.js new file mode 100644 index 0000000..5fb5aaf --- /dev/null +++ b/web/javascript/share_mixlab.js @@ -0,0 +1,110 @@ +import { app } from '../../../scripts/app.js' +import { $el } from '../../../scripts/ui.js' +import { api } from '../../../scripts/api.js' + +function get_position_style (ctx, widget_width, y, node_height) { + const MARGIN = 12 // the margin around the html element + + /* Create a transform that deals with all the scrolling and zooming */ + const elRect = ctx.canvas.getBoundingClientRect() + const transform = new DOMMatrix() + .scaleSelf( + elRect.width / ctx.canvas.width, + elRect.height / ctx.canvas.height + ) + .multiplySelf(ctx.getTransform()) + .translateSelf(MARGIN, MARGIN + y) + + return { + transformOrigin: '0 0', + transform: transform, + left: `0`, + top: `0`, + cursor: 'pointer', + position: 'absolute', + maxWidth: `${widget_width - MARGIN * 2}px`, + // maxHeight: `${node_height - MARGIN * 2}px`, // we're assuming we have the whole height of the node + width: `${widget_width - MARGIN * 2}px`, + // height: `${node_height * 0.3 - MARGIN * 2}px`, + // background: '#EEEEEE', + display: 'flex', + flexDirection: 'row', + // alignItems: 'center', + justifyContent: 'flex-start' + } +} + +app.registerExtension({ + name: 'Mixlab.share.ShareToWeibo', + async beforeRegisterNodeDef (nodeType, nodeData, app) { + if (nodeType.comfyClass == 'ShareToWeibo') { + const orig_nodeCreated = nodeType.prototype.onNodeCreated + nodeType.prototype.onNodeCreated = function () { + orig_nodeCreated?.apply(this, arguments) + // console.log(this) + const widget = { + type: 'div', + name: 'ShareToWeiboBtn', + draw (ctx, node, widget_width, y, widget_height) { + Object.assign( + this.div.style, + get_position_style( + ctx, + widget_width, + node.widgets[2].last_y +16, + node.size[1] + ) + ) + } + } + + const style = ` + flex-direction: row; + background-color: var(--comfy-input-bg); + border-radius: 8px; + border-color: var(--border-color); + border-style: solid; + color: var(--descrip-text);` + + widget.div = $el('div', {}) + + const btn = document.createElement('button') + btn.innerText = 'Share' + btn.style = style + + btn.addEventListener('click', () => { + if (window._mixlab_share_to_weibo) + window.open(window._mixlab_share_to_weibo) + }) + + document.body.appendChild(widget.div) + widget.div.appendChild(btn) + + this.addCustomWidget(widget) + + const onRemoved = this.onRemoved + this.onRemoved = () => { + widget.div.remove() + return onRemoved?.() + } + + this.serialize_widgets = true //需要保存参数 + } + + const onExecuted = nodeType.prototype.onExecuted + nodeType.prototype.onExecuted = async function (message) { + onExecuted?.apply(this, arguments) + // console.log(this.widgets) + + window._mixlab_share_to_weibo = message.url + try { + const div = this.widgets.filter(w => w.div)[0].div + Array.from( + div.querySelectorAll('button'), + b => (b.style.background = 'yellow') + ) + } catch (error) {} + } + } + } +})