diff --git a/.gitignore b/.gitignore
index a43654a..cea31fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@ __pycache__/
https/
nodes/config.json
workflow/my_workflow.json
-workflow/my_workflow_app.json
\ No newline at end of file
+workflow/my_workflow_app.json
+app/*
\ No newline at end of file
diff --git a/README.md b/README.md
index 681722f..213bfd9 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,25 @@
##
-v0.6.0 🚀🚗🚚🏃 Workflow-to-APP
+v0.7.0 🚀🚗🚚🏃 Workflow-to-APP
+- 支持多个web app 切换
- 新增AppInfo节点,可以通过简单的配置,把workflow转变为一个Web APP。
+- Support multiple web app switching.
- Add the AppInfo node, which allows you to transform the workflow into a web app by simple configuration.
+
+

+
Example:
- workflow

+[text-to-image](./workflow/Text-to-Image-app.json)
APP-JSON:
-- [text-to-image](./app/text-to-image_1_Wed%20Dec%2027%202023.json)
-- [image-to-image](./app/image-to-image_1_Wed%20Dec%2027%202023.json)
+- [text-to-image](./example/text-to-image_1_Wed%20Dec%2027%202023.json)
+- [image-to-image](./example/image-to-image_1_Wed%20Dec%2027%202023.json)
- text-to-text
-> 暂时支持6种节点作为界面上的输入节点:Load Image、CLIPTextEncode、TextInput_、FloatSlider、CheckpointLoaderSimple、LoraLoader
+> 暂时支持6种节点作为界面上的输入节点:Load Image、CLIPTextEncode、TextInput_、FloatSlider、IntNumber、CheckpointLoaderSimple、LoraLoader
> 输出节点:PreviewImage 、SaveImage、ShowTextForGPT、VHS_VideoCombine
diff --git a/__init__.py b/__init__.py
index c277074..f53cc05 100644
--- a/__init__.py
+++ b/__init__.py
@@ -4,7 +4,7 @@ import subprocess
import importlib.util
import sys,json
import urllib
-
+import hashlib
import datetime
@@ -79,6 +79,13 @@ install_openai()
current_path = os.path.abspath(os.path.dirname(__file__))
+
+def calculate_md5(string):
+ encoded_string = string.encode()
+ md5_hash = hashlib.md5(encoded_string).hexdigest()
+ return md5_hash
+
+
def create_key(key_p,crt_p):
import OpenSSL
# 生成自签名证书
@@ -162,17 +169,75 @@ def get_workflows():
workflows=read_workflow_json_files(workflow_path)
return workflows
-def get_my_workflow_for_app():
- # print("#####path::", current_path)
- workflow_path=os.path.join(current_path, "workflow/my_workflow_app.json")
- print('workflow_path: ',workflow_path)
- json_data={}
- try:
- with open(workflow_path) as json_file:
- json_data = json.load(json_file)
- except:
- print('-')
- return json_data
+def get_my_workflow_for_app(filename="my_workflow_app.json"):
+ app_path=os.path.join(current_path, "app")
+ if not os.path.exists(app_path):
+ os.mkdir(app_path)
+
+ apps=[]
+ if filename==None:
+ data=read_workflow_json_files(app_path)
+ i=0
+ for item in data:
+ try:
+ x=item["data"]
+ if i==0:
+ apps.append({
+ "filename":item["filename"],
+ "data":x,
+ "date":item["date"]
+ })
+ else:
+ apps.append({
+ "filename":item["filename"],
+ "data":{
+ "app":{
+ "description":x['app']['description'],
+ "filename":(x['app']['filename'] if 'filename' in x['app'] else "") ,
+ "icon":(x['app']['icon'] if 'icon' in x['app'] else None),
+ "name":x['app']['name'],
+ "version":x['app']['version'],
+ }
+ },
+ "date":item["date"]
+ })
+ i+=1
+ except Exception as e:
+ print("发生异常:", str(e))
+ else:
+ app_workflow_path=os.path.join(app_path, filename)
+ # print('app_workflow_path: ',app_workflow_path)
+ try:
+ with open(app_workflow_path) as json_file:
+ apps = [{
+ 'filename':filename,
+ 'data':json.load(json_file)
+ }]
+ except Exception as e:
+ print("发生异常:", str(e))
+
+ if len(apps)==1:
+ data=read_workflow_json_files(app_path)
+
+ for item in data:
+ x=item["data"]
+ print(apps[0]['filename'] ,item["filename"])
+ if apps[0]['filename']!=item["filename"]:
+ apps.append({
+ "filename":item["filename"],
+ "data":{
+ "app":{
+ "description":x['app']['description'],
+ "filename":(x['app']['filename'] if 'filename' in x['app'] else "") ,
+ "icon":(x['app']['icon'] if 'icon' in x['app'] else None),
+ "name":x['app']['name'],
+ "version":x['app']['version'],
+ }
+ },
+ "date":item["date"]
+ })
+
+ return apps
def save_workflow_json(data):
workflow_path=os.path.join(current_path, "workflow/my_workflow.json")
@@ -180,11 +245,22 @@ def save_workflow_json(data):
json.dump(data, file)
return workflow_path
-def save_workflow_for_app(data):
- workflow_path=os.path.join(current_path, "workflow/my_workflow_app.json")
- with open(workflow_path, 'w') as file:
+def save_workflow_for_app(data,filename="my_workflow_app.json"):
+ app_path=os.path.join(current_path, "app")
+ if not os.path.exists(app_path):
+ os.mkdir(app_path)
+ app_workflow_path=os.path.join(app_path, filename)
+
+ try:
+ output_str = json.dumps(data['output'])
+ data['app']['id']=calculate_md5(output_str)
+ # id=data['app']['id']
+ except Exception as e:
+ print("发生异常:", str(e))
+
+ with open(app_workflow_path, 'w') as file:
json.dump(data, file)
- return workflow_path
+ return filename
def get_nodes_map():
# print("#####path::", current_path)
@@ -295,14 +371,17 @@ async def mixlab_workflow_hander(request):
'file_path':file_path
}
elif data['task']=='save_app':
- file_path=save_workflow_for_app(data['data'])
+ file_path=save_workflow_for_app(data['data'],data['filename'])
result={
'status':'success',
'file_path':file_path
}
elif data['task']=='my_app':
+ filename=None
+ if 'filename' in data:
+ filename=data['filename']
result={
- 'data':get_my_workflow_for_app(),
+ 'data':get_my_workflow_for_app(filename),
'status':'success',
}
elif data['task']=='list':
@@ -359,7 +438,7 @@ 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,ResizeImage,TextImage,SvgImage,Image3D,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
diff --git a/assets/0-m-app.png b/assets/0-m-app.png
new file mode 100644
index 0000000..c36f856
Binary files /dev/null and b/assets/0-m-app.png differ
diff --git a/app/image-to-image_1_Wed Dec 27 2023.json b/example/image-to-image_1_Wed Dec 27 2023.json
similarity index 100%
rename from app/image-to-image_1_Wed Dec 27 2023.json
rename to example/image-to-image_1_Wed Dec 27 2023.json
diff --git a/app/text-to-image_1_Wed Dec 27 2023.json b/example/text-to-image_1_Wed Dec 27 2023.json
similarity index 100%
rename from app/text-to-image_1_Wed Dec 27 2023.json
rename to example/text-to-image_1_Wed Dec 27 2023.json
diff --git a/nodes/ChatGPT.py b/nodes/ChatGPT.py
index 65a506d..5e08ee8 100644
--- a/nodes/ChatGPT.py
+++ b/nodes/ChatGPT.py
@@ -75,11 +75,11 @@ class ChatGPTNode:
"required": {
"api_key":("KEY", {"default": "", "multiline": True}),
"api_url":("URL", {"default": "", "multiline": True}),
- "prompt": ("STRING", {"multiline": True}),
+ "prompt": ("STRING", {"multiline": True,"dynamicPrompts": False}),
"system_content": ("STRING",
{
"default": "You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible.",
- "multiline": True
+ "multiline": True,"dynamicPrompts": False
}),
"model": (["gpt-3.5-turbo","gpt-35-turbo","gpt-3.5-turbo-16k", "gpt-3.5-turbo-16k-0613", "gpt-4-0613","gpt-4-1106-preview"],
{"default": "gpt-3.5-turbo"}),
@@ -167,7 +167,7 @@ class ShowTextForGPT:
def INPUT_TYPES(s):
return {
"required": {
- "text": ("STRING", {"forceInput": True}),
+ "text": ("STRING", {"forceInput": True,"dynamicPrompts": False}),
}
}
@@ -189,8 +189,8 @@ class CharacterInText:
def INPUT_TYPES(s):
return {
"required": {
- "text": ("STRING", {"multiline": True}),
- "character": ("STRING", {"multiline": True}),
+ "text": ("STRING", {"multiline": True,"dynamicPrompts": False}),
+ "character": ("STRING", {"multiline": True,"dynamicPrompts": False}),
"start_index": ("INT", {
"default": 1,
"min": 0, #Minimum value
diff --git a/nodes/Utils.py b/nodes/Utils.py
index 65d4f61..6134c08 100644
--- a/nodes/Utils.py
+++ b/nodes/Utils.py
@@ -369,14 +369,14 @@ class AppInfo:
@classmethod
def INPUT_TYPES(s):
return {"required": {
- "name": ("STRING",{"multiline": False,"default": "Mixlab-App"}),
+ "name": ("STRING",{"multiline": False,"default": "Mixlab-App","dynamicPrompts": False}),
"image": ("IMAGE",),
- "input_ids":("STRING",{"multiline": True,"default": "\n".join(["1","2","3"])}),
- "output_ids":("STRING",{"multiline": True,"default": "\n".join(["5","9"])}),
+ "input_ids":("STRING",{"multiline": True,"default": "\n".join(["1","2","3"]),"dynamicPrompts": False}),
+ "output_ids":("STRING",{"multiline": True,"default": "\n".join(["5","9"]),"dynamicPrompts": False}),
},
"optional":{
- "description":("STRING",{"multiline": True,"default": ""}),
+ "description":("STRING",{"multiline": True,"default": "","dynamicPrompts": False}),
"version":("INT", {
"default": 1,
"min": 1,
@@ -384,6 +384,7 @@ class AppInfo:
"step": 1,
"display": "number"
}),
+ "share_prefix":("STRING",{"multiline": False,"default": "","dynamicPrompts": False}),
}
}
@@ -398,13 +399,13 @@ class AppInfo:
INPUT_IS_LIST = False
OUTPUT_IS_LIST = (False,)
- def run(self,name,image,input_ids,output_ids,description,version):
+ def run(self,name,image,input_ids,output_ids,description,version,share_prefix):
im=create_temp_file(image)
# id=get_json_hash([name,im,input_ids,output_ids,description,version])
- return {"ui": {"json": [name,im,input_ids,output_ids,description,version]}, "result": (image,)}
+ return {"ui": {"json": [name,im,input_ids,output_ids,description,version,share_prefix]}, "result": (image,)}
diff --git a/web/index.html b/web/index.html
index 2e60eb6..05afdc8 100644
--- a/web/index.html
+++ b/web/index.html
@@ -13,7 +13,77 @@
margin-left: 5%;
}
+ .apps {
+ margin: 0 32px;
+ background: whitesmoke;
+ color: black;
+ padding: 12px;
+ cursor: pointer;
+ }
+ .apps .content {
+ display: flex;
+ flex-wrap: wrap;
+ }
+
+
+ .apps .card {
+ width: 200px;
+ margin: 12px;
+ display: flex;
+ flex-direction: row;
+ background: #f8f8f8;
+ cursor: pointer;
+ user-select: none;
+ }
+
+ .apps .selected {
+ box-shadow: 0px 0px 10px 10px #fbe9f0
+ }
+
+ .apps .card:hover {
+ box-shadow: 0px 0px 10px 10px #e9fbfa
+ }
+
+ .apps .card h5 {
+ font-size: 14px;
+ margin: 10px 0;
+ }
+
+ .apps .card p {
+ margin: 0;
+ padding: 0;
+ }
+
+ .apps .card img {
+ width: auto;
+ height: 100%;
+
+ margin: 0px;
+ }
+
+ .apps .card .item {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ align-items: flex-start;
+ }
+
+ .apps .card .icon {
+ width: 120px;
+ height: 120px;
+ overflow: hidden;
+ background: #e3e3e3;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+
+ .apps .card .version {
+ font-size: 12px;
+
+ }
.status {
background: black;
@@ -42,17 +112,24 @@
display: flex;
flex-direction: column;
min-width: 400px;
- background: #eee;
+ /* background: #eee; */
margin: 24px;
flex: 1;
align-items: center;
/* justify-content: center; */
}
+ .panel .header {
+ margin-bottom: 8px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ }
+
.panel h1 {
padding: 0 12px;
- margin-top: 12px;
- margin-bottom: 0;
+ margin: 0;
}
.panel img,
@@ -68,13 +145,18 @@
flex-direction: column;
}
+ .output {
+ width: 90%;
+ margin: 12px;
+ }
+
.output_card {
height: 100%;
width: 100%;
- box-shadow: 0px 0px 8px 3px #e6e7e7;
-
+ box-shadow: 0px 0px 20px 7px #e6e7e7;
+ margin-top: 24px;
display: flex;
-
+ flex-wrap: wrap;
/* justify-content: center;
align-items: center; */
@@ -84,6 +166,8 @@
video {
max-width: 400px;
max-height: 600px;
+ margin: 8px;
+ min-width: 200px;
}
.card {
@@ -125,7 +209,7 @@
border: 3px solid;
}
- .run_btn:hover {
+ button:hover {
border-color: yellow;
color: yellow;
}
@@ -138,28 +222,28 @@
.upload_btn {
width: 188px;
cursor: pointer;
- height: 188px;
- background: black;
+ /* height: 188px; */
+ /* background: black; */
color: white;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
font-size: 14px;
- margin-left: calc(50% - 94px);
- margin-top: calc(30vh - 94px);
+ color: black;
}
- .upload_btn:hover {
+ /* .upload_btn:hover {
outline: 4px solid yellow;
color: yellow;
- }
+ } */
.show_text {
font-size: 14px;
/* display: inline-block; */
- /* margin: 13px; */
+ margin: 8px;
padding: 32px;
+ min-width: 200px;
background: #242424;
color: white;
}
@@ -170,15 +254,39 @@
font-size: 12px;
font-weight: 300;
}
+
+ label::after {
+ content: attr(data-content);
+ /* Set the initial content using the data-content attribute */
+ /* position: absolute; */
+ /* top: 100%;
+ left: 0; */
+ margin-left: 4px;
+ font-size: 12px;
+ color: #555;
+ }
+
+ select,
+ button,
+ input {
+ height: 32px;
+ cursor: pointer;
+ background: #000000bf;
+ color: white;
+ outline: none;
+ border: none;
+ border-radius: 4px;
+ }
- Explore your creative potential with
Explore your creative potential with mixlab-nodes / 尽情发挥你的创意
ComfyUI中文爱好者社区推荐
@@ -258,46 +366,104 @@
});
}
- async function get_my_app() {
+
+ function success(isSuccess, btn, text) {
+ isSuccess ? btn.innerText = 'success' : text;
+ setTimeout(() => {
+ btn.innerText = text;
+ }, 5000)
+ }
+
+ async function get_my_app(filename = null) {
let url = get_url()
const res = await fetch(`${url}/mixlab/workflow`, {
method: 'POST',
body: JSON.stringify({
- task: 'my_app'
+ task: 'my_app',
+ filename
})
})
let result = await res.json();
+ let data = [];
+ try {
+ for (const res of result.data) {
+ let { output, app } = res.data;
+ if (app.filename) data.push({
+ ...app,
+ data: output,
+ date: res.date
+ })
+ }
+ } catch (error) {
- let { output, app } = result.data
-
- return {
- ...app,
- data: output
}
+
+
+ return data
}
function createOutputs(outputData) {
- // Array.from( window._appData.output,n=>n.id)
- const container = document.createElement("div");
- container.className = 'output_card'
+ const container = document.createElement('div');
+ container.className = "output";
+
+ const action = document.createElement('div');
+ container.appendChild(action)
+
+ const copyHTML = document.createElement('button');
+ copyHTML.innerText = 'copy as html'
+ action.appendChild(copyHTML)
+
+ const copyImage = document.createElement('button');
+ copyImage.innerText = 'copy image'
+ action.appendChild(copyImage)
+ copyImage.style.marginLeft = '18px';
+
+ const copyText = document.createElement('button');
+ copyText.innerText = 'copy text for share'
+ action.appendChild(copyText)
+ copyText.style.marginLeft = '18px';
+
+ const output_card = document.createElement("div");
+ output_card.className = 'output_card'
+ container.appendChild(output_card)
+
+
+
+ copyText.addEventListener('click', e => {
+ e.preventDefault();
+ copyTextToClipboard((window._appData.share_prefix || '') + " " + output_card.outerHTML, (r) => success(r, copyText, 'copy text for share'))
+
+ })
+
+ copyImage.addEventListener('click', e => {
+ e.preventDefault();
+ // copyHtmlWithImagesToClipboard(output_card.outerHTML)
+ copyImagesToClipboard(output_card.outerHTML, (r) => success(r, copyImage, 'copy image'))
+ // copyTextToClipboard()
+ })
+ copyHTML.addEventListener('click', e => {
+ e.preventDefault();
+ copyHtmlWithImagesToClipboard((window._appData.share_prefix || '') + " " + output_card.outerHTML, (r) => success(r, copyHTML, 'copy as html'))
+ // copyImagesToClipboard(output_card.outerHTML)
+ })
for (const node of outputData) {
- console.log('output', node)
+ // console.log('output', node)
if (node.class_type == "ShowTextForGPT") {
let div = document.createElement('div');
div.className = "show_text"
div.id = `output_${node.id}`;
- div.innerText = node.inputs.text[0]
- container.appendChild(div);
+ div.innerText = Array.isArray(node.inputs.text) ? node.inputs.text[0] : node.inputs.text
+ output_card.appendChild(div);
};
if (["SaveImage", "PreviewImage"].includes(node.class_type)) {
let img = new Image();
img.id = `output_${node.id}`;
img.src = base64Df;
- container.appendChild(img);
+ output_card.appendChild(img);
}
// video ,gif
@@ -313,7 +479,7 @@
v.appendChild(video);
v.appendChild(img);
- container.appendChild(v);
+ output_card.appendChild(v);
}
}
@@ -362,6 +528,134 @@
}
}
+
+ function copyHtmlWithImagesToClipboard(data, cb) {
+ // 创建一个临时div元素
+ const tempDiv = document.createElement('div');
+
+ // 将HTML字符串赋值给div的innerHTML属性
+ tempDiv.innerHTML = data;
+
+ // 获取div中的所有图像元素
+ const images = tempDiv.getElementsByTagName('img');
+
+ // 遍历图像元素,并将图像数据转换为Base64编码
+ for (let i = 0; i < images.length; i++) {
+ const image = images[i];
+ const canvas = document.createElement('canvas');
+ const context = canvas.getContext('2d');
+
+ // 设置canvas尺寸与图像尺寸相同
+ canvas.width = image.width;
+ canvas.height = image.height;
+
+ // 在canvas上绘制图像
+ context.drawImage(image, 0, 0);
+
+ // 将canvas转换为Base64编码
+ const imageData = canvas.toDataURL();
+
+ // 将Base64编码替换图像元素的src属性
+ image.src = imageData;
+ }
+
+
+ let richText = tempDiv.innerHTML;
+
+ // 创建一个新的Blob对象,并将富文本字符串作为数据传递进去
+ const blob = new Blob([richText], { type: 'text/html' });
+
+ // 创建一个ClipboardItem对象,并将Blob对象添加到其中
+ const clipboardItem = new ClipboardItem({ 'text/html': blob });
+
+ // 使用Clipboard API将内容复制到剪贴板
+ navigator.clipboard.write([clipboardItem])
+ .then(() => {
+ console.log('富文本已成功复制到剪贴板');
+ tempDiv.remove()
+ if (cb) cb(true)
+ })
+ .catch((error) => {
+ console.error('复制到剪贴板失败:', error);
+ tempDiv.remove()
+ if (cb) cb(false)
+ });
+
+ }
+
+ // const htmlWithImages = "
这是要复制的HTML内容

"
+ // copyHtmlWithImagesToClipboard(htmlWithImages);
+
+ function copyImagesToClipboard(html, cb) {
+ const tempDiv = document.createElement('div');
+ tempDiv.innerHTML = html;
+ const images = tempDiv.querySelectorAll('img');
+ const promises = Array.from(images).map((image) => {
+ return new Promise((resolve) => {
+ const img = new Image();
+ img.src = image.src;
+ img.onload = () => {
+ const canvas = document.createElement('canvas');
+ const context = canvas.getContext('2d');
+ canvas.width = img.width;
+ canvas.height = img.height;
+ context.drawImage(img, 0, 0);
+ canvas.toBlob((blob) => {
+ const clipboardItem = new ClipboardItem({ 'image/png': blob });
+ navigator.clipboard.write([clipboardItem])
+ .then(() => {
+ resolve();
+ tempDiv.remove()
+ if (cb) cb(true)
+ })
+ .catch((error) => {
+ reject(error);
+ tempDiv.remove()
+ if (cb) cb(false)
+ });
+ });
+ };
+ });
+ });
+ Promise.all([...promises])
+ .then(() => {
+ console.log('所有图片已成功复制到剪贴板');
+ if (cb) cb(true)
+ tempDiv.remove()
+ })
+ .catch((error) => {
+ console.error('复制到剪贴板失败:', error);
+ if (cb) cb(false)
+ tempDiv.remove()
+ });
+ }
+
+ function copyTextToClipboard(html, cb) {
+ const tempDiv = document.createElement('div');
+ tempDiv.innerHTML = html;
+
+ const text = tempDiv.innerText;
+ const textData = new ClipboardItem({ 'text/plain': new Blob([text], { type: 'text/plain' }) });
+
+ navigator.clipboard.write([textData])
+ .then(() => {
+ console.log('所有文本已成功复制到剪贴板', text);
+ if (cb) cb(true)
+ tempDiv.remove()
+ })
+ .catch((error) => {
+ console.error('复制到剪贴板失败:', error);
+ if (cb) cb(false)
+ tempDiv.remove()
+ });
+ }
+
+
+ // const htmlString = "
这是要复制的HTML内容


";
+ // copyImagesToClipboard(htmlString);
+
+
+
function createInputs(inputData) {
// Assuming you have an HTML element with the id "container" to hold the UI
const container = document.createElement("div");
@@ -393,6 +687,7 @@
// Create a label for the upload control
const nameLabel = document.createElement("label");
nameLabel.textContent = data.title || "LoadImage: ";
+ nameLabel.style.marginBottom = '12px'
uploadContainer.appendChild(nameLabel);
let actionDiv = document.createElement('div');
@@ -408,9 +703,7 @@
actionDiv.appendChild(uploadImageInputHide);
const btnFromClipboard = document.createElement("button");
- btnFromClipboard.style = `width: 156px;
- height: 24px;
- margin-left: 18px;`
+ btnFromClipboard.style = `width: 156px; margin-left: 18px;`
btnFromClipboard.innerText = 'paste from clipboard'
actionDiv.appendChild(btnFromClipboard);
@@ -469,9 +762,14 @@
if (['FloatSlider', 'IntNumber'].includes(data.class_type)) {
// 滑块输入
- let silde = createFloatSlide(data.title, data.inputs.number, (v) => {
- window._appData.data[data.id].inputs.number = v;
- })
+ let silde = createNumSlide(data.title,
+ data.inputs.number,
+ (v) => {
+ window._appData.data[data.id].inputs.number = v;
+ },
+ 0,
+ data.class_type === 'IntNumber' ? 6000 : 1,
+ data.class_type === 'IntNumber' ? 'int' : 'float')
container.appendChild(silde);
}
@@ -537,19 +835,20 @@
return container
}
- function createFloatSlide(labelText, value = 0, callback, minValue = 0, maxValue = 1) {
+ function createNumSlide(labelText, value = 0, callback, minValue = 0, maxValue = 1, type = 'float') {
// 创建滑块输入元素
var slider = document.createElement("input");
slider.type = "range";
slider.min = minValue;
slider.max = maxValue;
- slider.step = 0.01
+ slider.step = type == 'float' ? 0.01 : 1
slider.value = value;
// 创建标签元素
var label = document.createElement("label");
label.innerHTML = labelText;
+ label.setAttribute('data-content', value);
// 创建容器元素,并将滑块输入和标签添加到容器中
var container = document.createElement("div");
@@ -558,9 +857,11 @@
container.className = 'card'
// 添加change事件监听器
- slider.addEventListener("change", function (event) {
+ slider.addEventListener("input", function (event) {
var value = event.target.value;
+ value = type == 'float' ? value : Math.round(value)
console.log("滑块输入的值为:" + value);
+ label.setAttribute('data-content', value);
// 在这里可以执行其他操作,根据需要进行相应的处理
callback && callback(value)
});
@@ -599,21 +900,21 @@
return [div, selectElement];
}
- function getTypeFromUrl(url) {
+ function getFilenameFromUrl(url) {
const queryString = url.split('?')[1];
if (!queryString) {
return null;
}
const params = new URLSearchParams(queryString);
- const type = params.get('type');
+ const filename = decodeURIComponent(params.get('filename'));
- return type;
+ return filename;
}
- function createUI(inputData, outputData) {
+ function createUI(inputData, outputData, share = true) {
let mainDiv = document.createElement('div');
let leftDiv = document.createElement('div');
@@ -631,8 +932,26 @@
// top: 12px;flex:0.6`
// 创建标题
+ let titleDiv = document.createElement('div');
+ titleDiv.className = 'header'
+
var title = document.createElement('h1');
title.textContent = 'My Application';
+ titleDiv.appendChild(title);
+
+ if (share) {
+ const shareBtn = document.createElement('button');
+ shareBtn.innerText = 'copy url';
+ shareBtn.addEventListener('click', e => {
+ e.preventDefault();
+ let url = `${get_url()}/mixlab/app?filename=${encodeURIComponent(window._appData.filename)}`;
+ copyTextToClipboard(url, success(e, shareBtn, 'copy url'));
+ })
+
+ titleDiv.appendChild(shareBtn);
+ }
+
+
let iconDes = document.createElement('div');
// 创建应用图标
@@ -663,7 +982,7 @@
submitButton.className = 'run_btn'
// 将所有UI元素添加到页面中
- leftDiv.appendChild(title);
+ leftDiv.appendChild(titleDiv);
leftDiv.appendChild(iconDes);
// leftDiv.appendChild(des);
leftDiv.appendChild(status);
@@ -750,16 +1069,16 @@
});
}
- }
+ },
};
}
- function createUploadJson() {
+ function createUploadJson(detail) {
// 创建一个div元素
var div = document.createElement('div');
- div.className = 'upload_btn'
- div.textContent = '点击上传JSON文件';
+ div.className = 'upload_btn card'
+ div.textContent = '上传并运行你的JSON文件';
div.addEventListener('click', function () {
document.getElementById('jsonFileInput').click();
});
@@ -775,10 +1094,11 @@
reader.onload = function (e) {
var contents = e.target.result;
var jsonData = JSON.parse(contents);
- setTimeout(() => {
- div.remove();
- input.remove();
- }, 500);
+
+
+ Array.from(detail.querySelectorAll('.card'), c => c.classList.remove('selected'));
+ div.className = 'upload_btn card selected'
+
let { output, app } = jsonData;
@@ -786,8 +1106,8 @@
...app,
data: output
};
-
- createApp(window._appData);
+ if (document.body.querySelector('.app')) document.body.querySelector('.app').remove()
+ createApp(window._appData, false);
// res(jsonData);
};
@@ -795,16 +1115,16 @@
});
// 将div和input元素添加到body中
- document.body.appendChild(div);
+ // document.body.appendChild(div);
document.body.appendChild(input);
-
-
+ return div
}
- async function createApp(appData) {
+ async function createApp(appData, share = true) {
+ console.log(appData)
// 使用示例:
- var ui = createUI(appData.input, appData.output);
+ var ui = createUI(appData.input, appData.output, share);
// 更新标题
ui.title.update(appData.name || 'Mixlab APP');
@@ -859,8 +1179,8 @@
// if (!images) return;
const src = `${get_url()}/view?filename=${encodeURIComponent(images[0].filename)}&type=${images[0].type}&subfolder=${encodeURIComponent(images[0].subfolder)}&t=${+new Date()}`;
show(src, detail.node, 'image');
- } else if (text && text[0]) {
- ui.output.update("text", text[0], detail.node)
+ } else if (text) {
+ ui.output.update("text", Array.isArray(text) ? text[0] : text, detail.node)
} else if (gifs && gifs[0]) {
// if (!images) return;
const src = `${get_url()}/view?filename=${encodeURIComponent(gifs[0].filename)}&type=${gifs[0].type}&subfolder=${encodeURIComponent(gifs[0].subfolder)
@@ -886,24 +1206,72 @@
api.api_base = ""
api.init();
+
}
+ // 创建app的选择菜单
+ function createAppList(apps = []) {
+ let details = document.createElement('details');
+ details.className = 'apps';
+
+ details.innerHTML = `
ComfyUI APP Store / ${apps.length}
+
`
+
+ let div = details.querySelector('div');
+
+ for (let index = 0; index < apps.length; index++) {
+ const app = apps[index];
+ let d = document.createDocumentFragment();
+ let dd = document.createElement('div');
+ d.appendChild(dd);
+ dd.className = 'card' + (index == 0 ? ' selected' : '')
+ dd.innerHTML = `
+
+

+
+
+
+
${app.name}
+
${app.description}
+
+
+
version: ${app.version}
+
+
+
+ `
+
+ div.appendChild(d);
+ dd.addEventListener('click', async e => {
+ e.preventDefault();
+ Array.from(div.querySelectorAll('.card'), c => c.classList.remove('selected'));
+ dd.className = 'card selected'
+ // console.log(app.filename)
+
+ window._appData = (await get_my_app(app.filename))[0];
+ if (document.body.querySelector('.app')) document.body.querySelector('.app').remove()
+ createApp(window._appData);
+
+ })
+ // console.log(div)
+ };
+
+ let uploadApp = createUploadJson(details);
+ div.appendChild(uploadApp);
+
+ document.body.appendChild(details);
+ }
async function init_app() {
- let appData = {}
+ const filename = getFilenameFromUrl(location.href);
+ window._apps = await get_my_app(filename);
- const type = getTypeFromUrl(location.href);
- if (type === 'new') {
- createUploadJson();
- } else {
- appData = await get_my_app();
- // console.log(appData)
- window._appData = appData;
+ window._appData = window._apps[0];
- createApp(appData);
- }
+ createAppList(window._apps);
+ createApp(window._appData);
};
diff --git a/web/javascript/app_mixlab.js b/web/javascript/app_mixlab.js
index 454cdcd..6af907c 100644
--- a/web/javascript/app_mixlab.js
+++ b/web/javascript/app_mixlab.js
@@ -81,8 +81,9 @@ function extractInputAndOutputData (jsonData, inputIds = [], outputIds = []) {
if (node.type === 'CheckpointLoaderSimple') {
options = node.widgets.filter(w => w.name === 'ckpt_name')[0]
.options.values
- }else if(node.type === 'LoraLoader'){
- options =node.widgets.filter(w=>w.name==='lora_name')[0].options.values
+ } else if (node.type === 'LoraLoader') {
+ options = node.widgets.filter(w => w.name === 'lora_name')[0]
+ .options.values
}
} catch (error) {}
@@ -119,7 +120,8 @@ async function save_app (json) {
method: 'POST',
body: JSON.stringify({
data: json,
- task: 'save_app'
+ task: 'save_app',
+ filename: json.app.filename
})
})
return await res.json()
@@ -144,6 +146,7 @@ function downloadJsonFile (jsonData, fileName = 'mix_app.json') {
async function save (json, download = false) {
const name = json[0],
version = json[5],
+ share_prefix = json[6], //用于分享的功能扩展
description = json[4],
inputIds = json[2].split('\n').filter(f => f),
outputIds = json[3].split('\n').filter(f => f)
@@ -170,7 +173,9 @@ async function save (json, download = false) {
description,
version,
input,
- output
+ output,
+ share_prefix,
+ filename: `${name}_${version}_${new Date().toDateString()}.json`
}
try {
@@ -180,14 +185,15 @@ async function save (json, download = false) {
// let http_workflow = app.graph.serialize()
if (download) {
- await downloadJsonFile(
- data,
- `${data.app.name}_${data.app.version}_${new Date().toDateString()}.json`
- )
+ await save_app(data)
+ await downloadJsonFile(data, data.app.filename)
let open = window.confirm(
- `You can now access the standalone application on a new page!\n${getUrl()}/mixlab/app?type=new`
+ `You can now access the standalone application on a new page!\n${getUrl()}/mixlab/app?filename=${encodeURIComponent(data.app.filename)}`
)
- if (open) window.open(`${getUrl()}/mixlab/app?type=new`)
+ if (open)
+ window.open(
+ `${getUrl()}/mixlab/app?filename=${encodeURIComponent(data.app.filename)}`
+ )
} else {
await save_app(data)
@@ -208,7 +214,7 @@ app.registerExtension({
const orig_nodeCreated = nodeType.prototype.onNodeCreated
nodeType.prototype.onNodeCreated = function () {
orig_nodeCreated?.apply(this, arguments)
- // console.log(this)
+ console.log('#orig_nodeCreated', this)
const widget = {
type: 'div',
name: 'AppInfoRun',
@@ -218,7 +224,7 @@ app.registerExtension({
get_position_style(
ctx,
widget_width,
- node.widgets[4].last_y + 24,
+ node.size[1] - widget_height,
node.size[1]
)
)
@@ -236,7 +242,7 @@ app.registerExtension({
widget.div = $el('div', {})
const btn = document.createElement('button')
- btn.innerText = 'Save For App'
+ btn.innerText = 'Save & Open'
btn.style = style
btn.addEventListener('click', () => {
@@ -246,6 +252,7 @@ app.registerExtension({
} else {
alert('Please run the workflow before saving')
// app.queuePrompt(0, 1)
+ this.widgets.filter(w => w.name === 'version')[0].value += 1
}
})
@@ -261,6 +268,7 @@ app.registerExtension({
} else {
alert('Please run the workflow before saving')
// app.queuePrompt(0, 1)
+ this.widgets.filter(w => w.name === 'version')[0].value += 1
}
})
@@ -282,7 +290,7 @@ app.registerExtension({
const onExecuted = nodeType.prototype.onExecuted
nodeType.prototype.onExecuted = async function (message) {
onExecuted?.apply(this, arguments)
- // console.log(this.widgets)
+ console.log(message.json)
window._mixlab_app_json = message.json
try {
diff --git a/web/javascript/checkVersion_mixlab.js b/web/javascript/checkVersion_mixlab.js
index 1b94800..e98c585 100644
--- a/web/javascript/checkVersion_mixlab.js
+++ b/web/javascript/checkVersion_mixlab.js
@@ -3,7 +3,7 @@ import { app } from '../../../scripts/app.js'
const repoOwner = 'shadowcz007' // 替换为仓库的所有者
const repoName = 'comfyui-mixlab-nodes' // 替换为仓库的名称
-const version = 'v0.6.0'
+const version = 'v0.7.0'
fetch(`https://api.github.com/repos/${repoOwner}/${repoName}/releases/latest`)
.then(response => response.json())
diff --git a/workflow/3D-workflow.json b/workflow/3D-workflow.json
index 54ba842..00389a6 100644
--- a/workflow/3D-workflow.json
+++ b/workflow/3D-workflow.json
@@ -1,6 +1,6 @@
{
- "last_node_id": 60,
- "last_link_id": 118,
+ "last_node_id": 65,
+ "last_link_id": 143,
"nodes": [
{
"id": 9,
@@ -52,7 +52,7 @@
"1": 246
},
"flags": {},
- "order": 31,
+ "order": 29,
"mode": 0,
"inputs": [
{
@@ -77,7 +77,7 @@
"1": 26
},
"flags": {},
- "order": 20,
+ "order": 18,
"mode": 0,
"inputs": [
{
@@ -168,8 +168,7 @@
"name": "VAE",
"type": "VAE",
"links": [
- 11,
- 23
+ 11
],
"slot_index": 2
}
@@ -219,70 +218,6 @@
" a metallic sash-like shoe,render by ue5,and blender,8k,detailed"
]
},
- {
- "id": 2,
- "type": "PreviewImage",
- "pos": [
- 673.0796203613281,
- 734.9191284179688
- ],
- "size": {
- "0": 210,
- "1": 246
- },
- "flags": {},
- "order": 8,
- "mode": 0,
- "inputs": [
- {
- "name": "images",
- "type": "IMAGE",
- "link": 76
- }
- ],
- "properties": {
- "Node name for S&R": "PreviewImage"
- }
- },
- {
- "id": 17,
- "type": "VAEEncode",
- "pos": [
- 673.0796203613281,
- 1110.9191284179688
- ],
- "size": {
- "0": 210,
- "1": 46
- },
- "flags": {},
- "order": 9,
- "mode": 0,
- "inputs": [
- {
- "name": "pixels",
- "type": "IMAGE",
- "link": 77
- },
- {
- "name": "vae",
- "type": "VAE",
- "link": 23
- }
- ],
- "outputs": [
- {
- "name": "LATENT",
- "type": "LATENT",
- "links": [],
- "shape": 3,
- "slot_index": 0
- }
- ],
- "properties": {
- "Node name for S&R": "VAEEncode"
- }
- },
{
"id": 43,
"type": "IPAdapterModelLoader",
@@ -328,7 +263,7 @@
"flags": {
"collapsed": false
},
- "order": 35,
+ "order": 33,
"mode": 0,
"inputs": [
{
@@ -368,13 +303,13 @@
"1": 106
},
"flags": {},
- "order": 15,
+ "order": 13,
"mode": 0,
"inputs": [
{
"name": "width",
"type": "INT",
- "link": 26,
+ "link": 120,
"widget": {
"name": "width"
},
@@ -383,7 +318,7 @@
{
"name": "height",
"type": "INT",
- "link": 27,
+ "link": 121,
"widget": {
"name": "height"
}
@@ -420,7 +355,7 @@
"1": 26
},
"flags": {},
- "order": 26,
+ "order": 24,
"mode": 0,
"inputs": [
{
@@ -454,7 +389,7 @@
"1": 58
},
"flags": {},
- "order": 21,
+ "order": 19,
"mode": 0,
"inputs": [
{
@@ -494,18 +429,18 @@
"1": 130
},
"flags": {},
- "order": 17,
+ "order": 15,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
- "link": 82
+ "link": 137
},
{
"name": "width",
"type": "INT",
- "link": 46,
+ "link": 124,
"widget": {
"name": "width"
}
@@ -513,7 +448,7 @@
{
"name": "height",
"type": "INT",
- "link": 47,
+ "link": 125,
"widget": {
"name": "height"
}
@@ -550,7 +485,7 @@
"1": 246
},
"flags": {},
- "order": 25,
+ "order": 23,
"mode": 0,
"inputs": [
{
@@ -575,13 +510,13 @@
"1": 130
},
"flags": {},
- "order": 18,
+ "order": 16,
"mode": 0,
"inputs": [
{
"name": "width",
"type": "INT",
- "link": 102,
+ "link": 126,
"widget": {
"name": "width"
}
@@ -589,7 +524,7 @@
{
"name": "height",
"type": "INT",
- "link": 97,
+ "link": 127,
"widget": {
"name": "height"
}
@@ -615,199 +550,6 @@
0
]
},
- {
- "id": 50,
- "type": "PreviewImage",
- "pos": [
- 673.0796203613281,
- 1698.9191284179688
- ],
- "size": {
- "0": 210,
- "1": 246
- },
- "flags": {},
- "order": 12,
- "mode": 0,
- "inputs": [
- {
- "name": "images",
- "type": "IMAGE",
- "link": 87
- }
- ],
- "properties": {
- "Node name for S&R": "PreviewImage"
- }
- },
- {
- "id": 20,
- "type": "MergeLayers",
- "pos": [
- 1613.3576354980469,
- 694
- ],
- "size": {
- "0": 210,
- "1": 46
- },
- "flags": {},
- "order": 23,
- "mode": 0,
- "inputs": [
- {
- "name": "layers",
- "type": "LAYER",
- "link": 103,
- "slot_index": 0
- },
- {
- "name": "image",
- "type": "IMAGE",
- "link": 110
- }
- ],
- "outputs": [
- {
- "name": "IMAGE",
- "type": "IMAGE",
- "links": [
- 34,
- 36
- ],
- "shape": 3,
- "slot_index": 0
- }
- ],
- "properties": {
- "Node name for S&R": "MergeLayers"
- }
- },
- {
- "id": 22,
- "type": "NewLayer",
- "pos": [
- 1198.3576354980469,
- 366
- ],
- "size": {
- "0": 315,
- "1": 234
- },
- "flags": {},
- "order": 16,
- "mode": 0,
- "inputs": [
- {
- "name": "image",
- "type": "IMAGE",
- "link": 74
- },
- {
- "name": "mask",
- "type": "MASK",
- "link": 75
- },
- {
- "name": "layers",
- "type": "LAYER",
- "link": null,
- "slot_index": 2
- },
- {
- "name": "width",
- "type": "INT",
- "link": 30,
- "widget": {
- "name": "width"
- }
- },
- {
- "name": "height",
- "type": "INT",
- "link": 31,
- "widget": {
- "name": "height"
- }
- }
- ],
- "outputs": [
- {
- "name": "layers",
- "type": "LAYER",
- "links": [
- 103
- ],
- "shape": 6,
- "slot_index": 0
- }
- ],
- "properties": {
- "Node name for S&R": "NewLayer"
- },
- "widgets_values": [
- 0,
- 0,
- 512,
- 512,
- 2,
- "width",
- ""
- ]
- },
- {
- "id": 18,
- "type": "GetImageSize",
- "pos": [
- 673.0796203613281,
- 1286.9191284179688
- ],
- "size": {
- "0": 210,
- "1": 46
- },
- "flags": {},
- "order": 10,
- "mode": 0,
- "inputs": [
- {
- "name": "image",
- "type": "IMAGE",
- "link": 78
- }
- ],
- "outputs": [
- {
- "name": "width",
- "type": "INT",
- "links": [
- 26,
- 30,
- 46,
- 102,
- 106
- ],
- "shape": 3,
- "slot_index": 0
- },
- {
- "name": "height",
- "type": "INT",
- "links": [
- 27,
- 31,
- 47,
- 97,
- 107
- ],
- "shape": 3,
- "slot_index": 1
- }
- ],
- "properties": {
- "Node name for S&R": "GetImageSize"
- }
- },
{
"id": 57,
"type": "PreviewImage",
@@ -820,7 +562,7 @@
"1": 246
},
"flags": {},
- "order": 22,
+ "order": 20,
"mode": 0,
"inputs": [
{
@@ -845,7 +587,7 @@
"1": 82
},
"flags": {},
- "order": 24,
+ "order": 21,
"mode": 0,
"inputs": [
{
@@ -886,7 +628,7 @@
"1": 309.7566223144531
},
"flags": {},
- "order": 29,
+ "order": 25,
"mode": 0,
"inputs": [
{
@@ -911,7 +653,7 @@
"1": 98
},
"flags": {},
- "order": 33,
+ "order": 31,
"mode": 0,
"inputs": [
{
@@ -961,13 +703,13 @@
"1": 529.5877685546875
},
"flags": {},
- "order": 28,
+ "order": 26,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
- "link": 36
+ "link": 142
}
],
"properties": {
@@ -986,13 +728,13 @@
"1": 26
},
"flags": {},
- "order": 13,
+ "order": 11,
"mode": 0,
"inputs": [
{
"name": "mask",
"type": "MASK",
- "link": 80
+ "link": 136
}
],
"outputs": [
@@ -1011,174 +753,6 @@
"Node name for S&R": "InvertMask"
}
},
- {
- "id": 26,
- "type": "CannyEdgePreprocessor",
- "pos": [
- 673.0796203613281,
- 1462.9191284179688
- ],
- "size": {
- "0": 315,
- "1": 106
- },
- "flags": {},
- "order": 11,
- "mode": 0,
- "inputs": [
- {
- "name": "image",
- "type": "IMAGE",
- "link": 79
- }
- ],
- "outputs": [
- {
- "name": "IMAGE",
- "type": "IMAGE",
- "links": [
- 40
- ],
- "shape": 3,
- "slot_index": 0
- }
- ],
- "properties": {
- "Node name for S&R": "CannyEdgePreprocessor"
- },
- "widgets_values": [
- 126,
- 200,
- 512
- ]
- },
- {
- "id": 56,
- "type": "ImageScale",
- "pos": [
- 1198.3576354980469,
- 1234
- ],
- "size": {
- "0": 315,
- "1": 130
- },
- "flags": {},
- "order": 19,
- "mode": 0,
- "inputs": [
- {
- "name": "image",
- "type": "IMAGE",
- "link": 108
- },
- {
- "name": "width",
- "type": "INT",
- "link": 106,
- "widget": {
- "name": "width"
- }
- },
- {
- "name": "height",
- "type": "INT",
- "link": 107,
- "widget": {
- "name": "height"
- }
- }
- ],
- "outputs": [
- {
- "name": "IMAGE",
- "type": "IMAGE",
- "links": [
- 109,
- 110,
- 117
- ],
- "shape": 3,
- "slot_index": 0
- }
- ],
- "properties": {
- "Node name for S&R": "ImageScale"
- },
- "widgets_values": [
- "nearest-exact",
- 512,
- 512,
- "disabled"
- ]
- },
- {
- "id": 42,
- "type": "IPAdapterApply",
- "pos": [
- 673.0796203613281,
- 2230.9191284179688
- ],
- "size": {
- "0": 315,
- "1": 258
- },
- "flags": {},
- "order": 14,
- "mode": 0,
- "inputs": [
- {
- "name": "ipadapter",
- "type": "IPADAPTER",
- "link": 67,
- "slot_index": 0
- },
- {
- "name": "clip_vision",
- "type": "CLIP_VISION",
- "link": 68,
- "slot_index": 1
- },
- {
- "name": "image",
- "type": "IMAGE",
- "link": 83,
- "slot_index": 2
- },
- {
- "name": "model",
- "type": "MODEL",
- "link": 70
- },
- {
- "name": "attn_mask",
- "type": "MASK",
- "link": null
- }
- ],
- "outputs": [
- {
- "name": "MODEL",
- "type": "MODEL",
- "links": [
- 71
- ],
- "shape": 3,
- "slot_index": 0
- }
- ],
- "properties": {
- "Node name for S&R": "IPAdapterApply"
- },
- "widgets_values": [
- 0.9,
- 0,
- "linear",
- 0,
- 0.886,
- false
- ]
- },
{
"id": 27,
"type": "ControlNetApply",
@@ -1191,7 +765,7 @@
"1": 98
},
"flags": {},
- "order": 32,
+ "order": 30,
"mode": 0,
"inputs": [
{
@@ -1311,7 +885,7 @@
{
"name": "image",
"type": "IMAGE",
- "link": 34
+ "link": 143
},
{
"name": "mask",
@@ -1347,7 +921,7 @@
"1": 98
},
"flags": {},
- "order": 30,
+ "order": 28,
"mode": 0,
"inputs": [
{
@@ -1398,7 +972,7 @@
"1": 262
},
"flags": {},
- "order": 34,
+ "order": 32,
"mode": 0,
"inputs": [
{
@@ -1447,17 +1021,268 @@
]
},
{
- "id": 45,
- "type": "3DImage",
+ "id": 61,
+ "type": "GetImageSize_",
"pos": [
- -981,
- 1174
+ 575,
+ 1151
],
"size": {
- "0": 473.0796203613281,
- "1": 451.867919921875
+ "0": 210,
+ "1": 46
},
"flags": {},
+ "order": 9,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "link": 133
+ }
+ ],
+ "outputs": [
+ {
+ "name": "width",
+ "type": "INT",
+ "links": [
+ 120,
+ 122,
+ 124,
+ 126,
+ 128
+ ],
+ "shape": 3,
+ "slot_index": 0
+ },
+ {
+ "name": "height",
+ "type": "INT",
+ "links": [
+ 121,
+ 123,
+ 125,
+ 127,
+ 129
+ ],
+ "shape": 3,
+ "slot_index": 1
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "GetImageSize_"
+ }
+ },
+ {
+ "id": 56,
+ "type": "ImageScale",
+ "pos": [
+ 1167,
+ 1211
+ ],
+ "size": {
+ "0": 315,
+ "1": 130
+ },
+ "flags": {},
+ "order": 17,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "link": 138
+ },
+ {
+ "name": "width",
+ "type": "INT",
+ "link": 128,
+ "widget": {
+ "name": "width"
+ }
+ },
+ {
+ "name": "height",
+ "type": "INT",
+ "link": 129,
+ "widget": {
+ "name": "height"
+ }
+ }
+ ],
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 109,
+ 117,
+ 141
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "ImageScale"
+ },
+ "widgets_values": [
+ "nearest-exact",
+ 512,
+ 512,
+ "disabled"
+ ]
+ },
+ {
+ "id": 22,
+ "type": "NewLayer",
+ "pos": [
+ 1198,
+ 366
+ ],
+ "size": {
+ "0": 315,
+ "1": 234
+ },
+ "flags": {},
+ "order": 14,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "link": 132
+ },
+ {
+ "name": "mask",
+ "type": "MASK",
+ "link": 135
+ },
+ {
+ "name": "layers",
+ "type": "LAYER",
+ "link": null,
+ "slot_index": 2
+ },
+ {
+ "name": "width",
+ "type": "INT",
+ "link": 122,
+ "widget": {
+ "name": "width"
+ }
+ },
+ {
+ "name": "height",
+ "type": "INT",
+ "link": 123,
+ "widget": {
+ "name": "height"
+ }
+ }
+ ],
+ "outputs": [
+ {
+ "name": "layers",
+ "type": "LAYER",
+ "links": [
+ 140
+ ],
+ "shape": 6,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "NewLayer"
+ },
+ "widgets_values": [
+ 0,
+ 0,
+ 512,
+ 512,
+ 2,
+ "width",
+ ""
+ ]
+ },
+ {
+ "id": 64,
+ "type": "PreviewImage",
+ "pos": [
+ 630,
+ 674
+ ],
+ "size": [
+ 210,
+ 246
+ ],
+ "flags": {},
+ "order": 8,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 131
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "PreviewImage"
+ }
+ },
+ {
+ "id": 26,
+ "type": "CannyEdgePreprocessor",
+ "pos": [
+ 673.0796203613281,
+ 1462.9191284179688
+ ],
+ "size": {
+ "0": 315,
+ "1": 106
+ },
+ "flags": {},
+ "order": 10,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "link": 134
+ }
+ ],
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 40
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "CannyEdgePreprocessor"
+ },
+ "widgets_values": [
+ 126,
+ 200,
+ 512
+ ]
+ },
+ {
+ "id": 63,
+ "type": "3DImage",
+ "pos": [
+ -707,
+ 963
+ ],
+ "size": [
+ 315,
+ 486
+ ],
+ "flags": {},
"order": 5,
"mode": 0,
"inputs": [
@@ -1472,12 +1297,10 @@
"name": "IMAGE",
"type": "IMAGE",
"links": [
- 74,
- 76,
- 77,
- 78,
- 79,
- 87
+ 131,
+ 132,
+ 133,
+ 134
],
"shape": 3,
"slot_index": 0
@@ -1486,8 +1309,8 @@
"name": "MASK",
"type": "MASK",
"links": [
- 75,
- 80
+ 135,
+ 136
],
"shape": 3,
"slot_index": 1
@@ -1496,9 +1319,9 @@
"name": "BG_IMAGE",
"type": "IMAGE",
"links": [
- 82,
- 83,
- 108
+ 137,
+ 138,
+ 139
],
"shape": 3,
"slot_index": 2
@@ -1514,19 +1337,61 @@
"Node name for S&R": "3DImage"
}
},
+ {
+ "id": 65,
+ "type": "MergeLayers",
+ "pos": [
+ 1651,
+ 674
+ ],
+ "size": {
+ "0": 210,
+ "1": 46
+ },
+ "flags": {},
+ "order": 22,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "layers",
+ "type": "LAYER",
+ "link": 140
+ },
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 141
+ }
+ ],
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 142,
+ 143
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "MergeLayers"
+ }
+ },
{
"id": 15,
"type": "PreviewImage",
"pos": [
-456,
- 1945
+ 1756
],
"size": {
"0": 439.2066345214844,
"1": 539.8549194335938
},
"flags": {},
- "order": 36,
+ "order": 34,
"mode": 0,
"inputs": [
{
@@ -1538,6 +1403,73 @@
"properties": {
"Node name for S&R": "PreviewImage"
}
+ },
+ {
+ "id": 42,
+ "type": "IPAdapterApply",
+ "pos": [
+ 658,
+ 2189
+ ],
+ "size": {
+ "0": 315,
+ "1": 258
+ },
+ "flags": {},
+ "order": 12,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "ipadapter",
+ "type": "IPADAPTER",
+ "link": 67,
+ "slot_index": 0
+ },
+ {
+ "name": "clip_vision",
+ "type": "CLIP_VISION",
+ "link": 68,
+ "slot_index": 1
+ },
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "link": 139,
+ "slot_index": 2
+ },
+ {
+ "name": "model",
+ "type": "MODEL",
+ "link": 70
+ },
+ {
+ "name": "attn_mask",
+ "type": "MASK",
+ "link": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "MODEL",
+ "type": "MODEL",
+ "links": [
+ 71
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "IPAdapterApply"
+ },
+ "widgets_values": [
+ 0.9,
+ 0,
+ "linear",
+ 0,
+ 0.886,
+ false
+ ]
}
],
"links": [
@@ -1605,14 +1537,6 @@
1,
"CONTROL_NET"
],
- [
- 23,
- 6,
- 2,
- 17,
- 1,
- "VAE"
- ],
[
25,
19,
@@ -1621,54 +1545,6 @@
3,
"LATENT"
],
- [
- 26,
- 18,
- 0,
- 19,
- 0,
- "INT"
- ],
- [
- 27,
- 18,
- 1,
- 19,
- 1,
- "INT"
- ],
- [
- 30,
- 18,
- 0,
- 22,
- 3,
- "INT"
- ],
- [
- 31,
- 18,
- 1,
- 22,
- 4,
- "INT"
- ],
- [
- 34,
- 20,
- 0,
- 14,
- 0,
- "IMAGE"
- ],
- [
- 36,
- 20,
- 0,
- 24,
- 0,
- "IMAGE"
- ],
[
40,
26,
@@ -1685,22 +1561,6 @@
0,
"CONDITIONING"
],
- [
- 46,
- 18,
- 0,
- 29,
- 1,
- "INT"
- ],
- [
- 47,
- 18,
- 1,
- 29,
- 2,
- "INT"
- ],
[
50,
32,
@@ -1789,78 +1649,6 @@
0,
"MODEL"
],
- [
- 74,
- 45,
- 0,
- 22,
- 0,
- "IMAGE"
- ],
- [
- 75,
- 45,
- 1,
- 22,
- 1,
- "MASK"
- ],
- [
- 76,
- 45,
- 0,
- 2,
- 0,
- "IMAGE"
- ],
- [
- 77,
- 45,
- 0,
- 17,
- 0,
- "IMAGE"
- ],
- [
- 78,
- 45,
- 0,
- 18,
- 0,
- "IMAGE"
- ],
- [
- 79,
- 45,
- 0,
- 26,
- 0,
- "IMAGE"
- ],
- [
- 80,
- 45,
- 1,
- 25,
- 0,
- "MASK"
- ],
- [
- 82,
- 45,
- 2,
- 29,
- 0,
- "IMAGE"
- ],
- [
- 83,
- 45,
- 2,
- 42,
- 2,
- "IMAGE"
- ],
[
85,
10,
@@ -1869,14 +1657,6 @@
0,
"IMAGE"
],
- [
- 87,
- 45,
- 0,
- 50,
- 0,
- "IMAGE"
- ],
[
95,
53,
@@ -1885,14 +1665,6 @@
0,
"IMAGE"
],
- [
- 97,
- 18,
- 1,
- 53,
- 1,
- "INT"
- ],
[
99,
52,
@@ -1901,46 +1673,6 @@
0,
"MASK"
],
- [
- 102,
- 18,
- 0,
- 53,
- 0,
- "INT"
- ],
- [
- 103,
- 22,
- 0,
- 20,
- 0,
- "LAYER"
- ],
- [
- 106,
- 18,
- 0,
- 56,
- 1,
- "INT"
- ],
- [
- 107,
- 18,
- 1,
- 56,
- 2,
- "INT"
- ],
- [
- 108,
- 45,
- 2,
- 56,
- 0,
- "IMAGE"
- ],
[
109,
56,
@@ -1949,14 +1681,6 @@
0,
"IMAGE"
],
- [
- 110,
- 56,
- 0,
- 20,
- 1,
- "IMAGE"
- ],
[
115,
60,
@@ -1988,6 +1712,190 @@
27,
1,
"CONTROL_NET"
+ ],
+ [
+ 120,
+ 61,
+ 0,
+ 19,
+ 0,
+ "INT"
+ ],
+ [
+ 121,
+ 61,
+ 1,
+ 19,
+ 1,
+ "INT"
+ ],
+ [
+ 122,
+ 61,
+ 0,
+ 22,
+ 3,
+ "INT"
+ ],
+ [
+ 123,
+ 61,
+ 1,
+ 22,
+ 4,
+ "INT"
+ ],
+ [
+ 124,
+ 61,
+ 0,
+ 29,
+ 1,
+ "INT"
+ ],
+ [
+ 125,
+ 61,
+ 1,
+ 29,
+ 2,
+ "INT"
+ ],
+ [
+ 126,
+ 61,
+ 0,
+ 53,
+ 0,
+ "INT"
+ ],
+ [
+ 127,
+ 61,
+ 1,
+ 53,
+ 1,
+ "INT"
+ ],
+ [
+ 128,
+ 61,
+ 0,
+ 56,
+ 1,
+ "INT"
+ ],
+ [
+ 129,
+ 61,
+ 1,
+ 56,
+ 2,
+ "INT"
+ ],
+ [
+ 131,
+ 63,
+ 0,
+ 64,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 132,
+ 63,
+ 0,
+ 22,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 133,
+ 63,
+ 0,
+ 61,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 134,
+ 63,
+ 0,
+ 26,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 135,
+ 63,
+ 1,
+ 22,
+ 1,
+ "MASK"
+ ],
+ [
+ 136,
+ 63,
+ 1,
+ 25,
+ 0,
+ "MASK"
+ ],
+ [
+ 137,
+ 63,
+ 2,
+ 29,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 138,
+ 63,
+ 2,
+ 56,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 139,
+ 63,
+ 2,
+ 42,
+ 2,
+ "IMAGE"
+ ],
+ [
+ 140,
+ 22,
+ 0,
+ 65,
+ 0,
+ "LAYER"
+ ],
+ [
+ 141,
+ 56,
+ 0,
+ 65,
+ 1,
+ "IMAGE"
+ ],
+ [
+ 142,
+ 65,
+ 0,
+ 24,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 143,
+ 65,
+ 0,
+ 14,
+ 0,
+ "IMAGE"
]
],
"groups": [],
diff --git a/workflow/Text-to-Image-app.json b/workflow/Text-to-Image-app.json
new file mode 100644
index 0000000..1bcdf95
--- /dev/null
+++ b/workflow/Text-to-Image-app.json
@@ -0,0 +1,717 @@
+{
+ "last_node_id": 25,
+ "last_link_id": 32,
+ "nodes": [
+ {
+ "id": 5,
+ "type": "CLIPTextEncode",
+ "pos": [
+ 1029,
+ -2149
+ ],
+ "size": {
+ "0": 425.27801513671875,
+ "1": 180.6060791015625
+ },
+ "flags": {},
+ "order": 7,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "clip",
+ "type": "CLIP",
+ "link": 6
+ }
+ ],
+ "outputs": [
+ {
+ "name": "CONDITIONING",
+ "type": "CONDITIONING",
+ "links": [
+ 3
+ ],
+ "slot_index": 0
+ }
+ ],
+ "title": "负向prompt",
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ },
+ "widgets_values": [
+ "text, watermark"
+ ]
+ },
+ {
+ "id": 6,
+ "type": "VAEDecode",
+ "pos": [
+ 1867,
+ -2378
+ ],
+ "size": {
+ "0": 210,
+ "1": 46
+ },
+ "flags": {
+ "collapsed": false
+ },
+ "order": 10,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "samples",
+ "type": "LATENT",
+ "link": 7
+ },
+ {
+ "name": "vae",
+ "type": "VAE",
+ "link": 8
+ }
+ ],
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 9
+ ],
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "VAEDecode"
+ }
+ },
+ {
+ "id": 15,
+ "type": "EnhanceImage",
+ "pos": [
+ 2591,
+ -2531
+ ],
+ "size": {
+ "0": 315,
+ "1": 58
+ },
+ "flags": {},
+ "order": 12,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "link": 25
+ }
+ ],
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 18
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "EnhanceImage"
+ },
+ "widgets_values": [
+ 1.1
+ ]
+ },
+ {
+ "id": 21,
+ "type": "EmptyLatentImage",
+ "pos": [
+ 998,
+ -2674
+ ],
+ "size": [
+ 315,
+ 106
+ ],
+ "flags": {},
+ "order": 8,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "width",
+ "type": "INT",
+ "link": 30,
+ "widget": {
+ "name": "width"
+ }
+ },
+ {
+ "name": "height",
+ "type": "INT",
+ "link": 32,
+ "widget": {
+ "name": "height"
+ }
+ }
+ ],
+ "outputs": [
+ {
+ "name": "LATENT",
+ "type": "LATENT",
+ "links": [
+ 26
+ ],
+ "shape": 3
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "EmptyLatentImage"
+ },
+ "widgets_values": [
+ 512,
+ 512,
+ 1
+ ]
+ },
+ {
+ "id": 24,
+ "type": "LimitNumber",
+ "pos": [
+ 665,
+ -2958
+ ],
+ "size": {
+ "0": 315,
+ "1": 82
+ },
+ "flags": {},
+ "order": 4,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "number",
+ "type": "*",
+ "link": 29
+ }
+ ],
+ "outputs": [
+ {
+ "name": "number",
+ "type": "*",
+ "links": [
+ 30
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LimitNumber"
+ },
+ "widgets_values": [
+ 512,
+ 4089
+ ]
+ },
+ {
+ "id": 25,
+ "type": "LimitNumber",
+ "pos": [
+ 648,
+ -2659
+ ],
+ "size": {
+ "0": 315,
+ "1": 82
+ },
+ "flags": {},
+ "order": 5,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "number",
+ "type": "*",
+ "link": 31
+ }
+ ],
+ "outputs": [
+ {
+ "name": "number",
+ "type": "*",
+ "links": [
+ 32
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LimitNumber"
+ },
+ "widgets_values": [
+ 512,
+ 4089
+ ]
+ },
+ {
+ "id": 22,
+ "type": "IntNumber",
+ "pos": [
+ 302,
+ -2758
+ ],
+ "size": {
+ "0": 315,
+ "1": 58
+ },
+ "flags": {},
+ "order": 0,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "INT",
+ "type": "INT",
+ "links": [
+ 29
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "title": "Width",
+ "properties": {
+ "Node name for S&R": "IntNumber"
+ },
+ "widgets_values": [
+ 512
+ ]
+ },
+ {
+ "id": 23,
+ "type": "IntNumber",
+ "pos": [
+ 299,
+ -2601
+ ],
+ "size": {
+ "0": 315,
+ "1": 58
+ },
+ "flags": {},
+ "order": 1,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "INT",
+ "type": "INT",
+ "links": [
+ 31
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "title": "Height",
+ "properties": {
+ "Node name for S&R": "IntNumber"
+ },
+ "widgets_values": [
+ 512
+ ]
+ },
+ {
+ "id": 2,
+ "type": "CheckpointLoaderSimple",
+ "pos": [
+ 567,
+ -2422
+ ],
+ "size": {
+ "0": 315,
+ "1": 98
+ },
+ "flags": {},
+ "order": 2,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "MODEL",
+ "type": "MODEL",
+ "links": [
+ 1
+ ],
+ "slot_index": 0
+ },
+ {
+ "name": "CLIP",
+ "type": "CLIP",
+ "links": [
+ 5,
+ 6
+ ],
+ "slot_index": 1
+ },
+ {
+ "name": "VAE",
+ "type": "VAE",
+ "links": [
+ 8
+ ],
+ "slot_index": 2
+ }
+ ],
+ "title": "Model",
+ "properties": {
+ "Node name for S&R": "CheckpointLoaderSimple"
+ },
+ "widgets_values": [
+ "deliberate_v2.safetensors"
+ ]
+ },
+ {
+ "id": 1,
+ "type": "KSampler",
+ "pos": [
+ 1509,
+ -2394
+ ],
+ "size": {
+ "0": 315,
+ "1": 262
+ },
+ "flags": {},
+ "order": 9,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "model",
+ "type": "MODEL",
+ "link": 1
+ },
+ {
+ "name": "positive",
+ "type": "CONDITIONING",
+ "link": 2
+ },
+ {
+ "name": "negative",
+ "type": "CONDITIONING",
+ "link": 3
+ },
+ {
+ "name": "latent_image",
+ "type": "LATENT",
+ "link": 26,
+ "slot_index": 3
+ },
+ {
+ "name": "denoise",
+ "type": "FLOAT",
+ "link": 16,
+ "widget": {
+ "name": "denoise"
+ },
+ "slot_index": 4
+ }
+ ],
+ "outputs": [
+ {
+ "name": "LATENT",
+ "type": "LATENT",
+ "links": [
+ 7
+ ],
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "KSampler"
+ },
+ "widgets_values": [
+ 730250870715434,
+ "randomize",
+ 15,
+ 6.9,
+ "euler",
+ "karras",
+ 0.59
+ ]
+ },
+ {
+ "id": 14,
+ "type": "FloatSlider",
+ "pos": [
+ 1007,
+ -2819
+ ],
+ "size": {
+ "0": 315,
+ "1": 58
+ },
+ "flags": {},
+ "order": 3,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "FLOAT",
+ "type": "FLOAT",
+ "links": [
+ 16
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "title": "denoise",
+ "properties": {
+ "Node name for S&R": "FloatSlider"
+ },
+ "widgets_values": [
+ 1
+ ]
+ },
+ {
+ "id": 16,
+ "type": "PreviewImage",
+ "pos": [
+ 2949,
+ -2615
+ ],
+ "size": {
+ "0": 210,
+ "1": 246
+ },
+ "flags": {},
+ "order": 13,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 18
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "PreviewImage"
+ }
+ },
+ {
+ "id": 4,
+ "type": "CLIPTextEncode",
+ "pos": [
+ 1022,
+ -2375
+ ],
+ "size": {
+ "0": 422.84503173828125,
+ "1": 164.31304931640625
+ },
+ "flags": {},
+ "order": 6,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "clip",
+ "type": "CLIP",
+ "link": 5
+ }
+ ],
+ "outputs": [
+ {
+ "name": "CONDITIONING",
+ "type": "CONDITIONING",
+ "links": [
+ 2
+ ],
+ "slot_index": 0
+ }
+ ],
+ "title": "prompt",
+ "properties": {
+ "Node name for S&R": "CLIPTextEncode"
+ },
+ "widgets_values": [
+ "superman,fat cat"
+ ]
+ },
+ {
+ "id": 7,
+ "type": "AppInfo",
+ "pos": [
+ 2134,
+ -2528
+ ],
+ "size": {
+ "0": 408.4201965332031,
+ "1": 406.9195861816406
+ },
+ "flags": {},
+ "order": 11,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "link": 9
+ }
+ ],
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 25
+ ],
+ "shape": 3,
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "AppInfo"
+ },
+ "widgets_values": [
+ "Text-to-Image",
+ "4\n22\n23\n2\n\n\n",
+ "16",
+ "演示基本的文生图流程",
+ 1,
+ "#comfyui-mixlab-nodes# ",
+ null
+ ]
+ }
+ ],
+ "links": [
+ [
+ 1,
+ 2,
+ 0,
+ 1,
+ 0,
+ "MODEL"
+ ],
+ [
+ 2,
+ 4,
+ 0,
+ 1,
+ 1,
+ "CONDITIONING"
+ ],
+ [
+ 3,
+ 5,
+ 0,
+ 1,
+ 2,
+ "CONDITIONING"
+ ],
+ [
+ 5,
+ 2,
+ 1,
+ 4,
+ 0,
+ "CLIP"
+ ],
+ [
+ 6,
+ 2,
+ 1,
+ 5,
+ 0,
+ "CLIP"
+ ],
+ [
+ 7,
+ 1,
+ 0,
+ 6,
+ 0,
+ "LATENT"
+ ],
+ [
+ 8,
+ 2,
+ 2,
+ 6,
+ 1,
+ "VAE"
+ ],
+ [
+ 9,
+ 6,
+ 0,
+ 7,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 16,
+ 14,
+ 0,
+ 1,
+ 4,
+ "FLOAT"
+ ],
+ [
+ 18,
+ 15,
+ 0,
+ 16,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 25,
+ 7,
+ 0,
+ 15,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 26,
+ 21,
+ 0,
+ 1,
+ 3,
+ "LATENT"
+ ],
+ [
+ 29,
+ 22,
+ 0,
+ 24,
+ 0,
+ "*"
+ ],
+ [
+ 30,
+ 24,
+ 0,
+ 21,
+ 0,
+ "INT"
+ ],
+ [
+ 31,
+ 23,
+ 0,
+ 25,
+ 0,
+ "*"
+ ],
+ [
+ 32,
+ 25,
+ 0,
+ 21,
+ 1,
+ "INT"
+ ]
+ ],
+ "groups": [],
+ "config": {},
+ "extra": {},
+ "version": 0.4
+}
\ No newline at end of file
diff --git a/workflow/appinfo-workflow.svg b/workflow/appinfo-workflow.svg
index 126b809..f28f21d 100644
--- a/workflow/appinfo-workflow.svg
+++ b/workflow/appinfo-workflow.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file