├── .github
└── workflows
│ └── publish.yml
├── LICENSE
├── README.md
├── __init__.py
├── comfyui_imagefx.py
├── comfyui_whisk.py
├── googel.json
├── pyproject.toml
├── requirements.txt
├── utils.py
└── workflows
├── ComfyUI-ImageFx.json
├── ComfyUI-Whisk&ImageFx.json
└── ComfyUI-Whisk.json
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish to Comfy registry
2 | on:
3 | workflow_dispatch:
4 | push:
5 | branches:
6 | - main
7 | - master
8 | paths:
9 | - "pyproject.toml"
10 |
11 | permissions:
12 | issues: write
13 |
14 | jobs:
15 | publish-node:
16 | name: Publish Custom Node to registry
17 | runs-on: ubuntu-latest
18 | if: ${{ github.repository_owner == 'ainewsto' }}
19 | steps:
20 | - name: Check out code
21 | uses: actions/checkout@v4
22 | with:
23 | submodules: true
24 | - name: Publish Custom Node
25 | uses: Comfy-Org/publish-node-action@v1
26 | with:
27 | ## Add your own personal access token to your Github Repository secrets and reference it here.
28 | personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | 
4 |
5 |
6 |
7 |
8 | # 👋🏻 如何设置api(非官方)?
9 | ## 视频教程地址:https://www.bilibili.com/video/BV1NnrCYCE9d
10 | ## 请打开googel.json文件,如下图所示
11 |
12 | 
13 |
14 |
15 |
16 |
17 | * `"user","expires","access_token","EMAIL" `: 这个几个数值在下图所示的位置找到并且填写好~
18 |
19 | 
20 |
21 |
22 |
23 | * `"cookies" `: 这个需要在Whisk界面随便上传一张图片才会出现,然后看下面图片所示,并且填写好保存
24 |
25 | 
26 |
27 | 
28 |
29 | > \[!IMPORTANT]\
30 | > 非官方api,所以随时都有可能被毙掉,而且也有封号风险,被封别怪我,别怪我,别怪我!且用且珍惜!!~
31 | >
32 | > googel.json里面填写的信息都是有时效性的,如果突然在comfyui里面报错401就考虑更新下
33 | >
34 | > 国内用户需要魔法,需要魔法,需要魔法,而且最佳是美国ip!!!!!不然不行,不然不行,不然不行!!!
35 | >
36 |
37 | # 🥵 comfyui workflows
38 |
39 | ## ComfyUI-Whisk🌪️
40 | * `Whisk `: 因为人间这位小天使不断地问我谷歌这个反推,我昨天有时间就弄了,这个节点可以用啦反推图片。而且比官方一次生成图片更多,可生成4张图片。
41 | 
42 |
43 |
44 | ## ComfyUI-ImageFx🖼️
45 | * `ImageFx`: 跟官方一样,就是文生图节点。
46 | 
47 |
48 |
49 | ## ComfyUI-Whisk-Prompts🌪️
50 | * `Whisk-Prompts`: 用来输出最终生成图片的提示词节点。
51 | 
52 |
53 |
54 | # 更新 Update:
55 |
56 | 20250110:`ComfyUI-Whisk🌪️`: 修改图片输入接口可以任意输入图片,生成不同效果,不需要同时输入3张。
57 | 新增节点:ComfyUI-Whisk-Prompts🌪️
58 |
59 | 查看更新/Update
60 |
61 | 
62 | 
63 | 
64 | 
65 |
66 |
67 |
68 |
69 | # :dizzy:插件感谢原项目 Comfy Resources:
70 |
71 |
72 | https://github.com/comfyanonymous/ComfyUI
73 |
74 |
75 |
76 | ## Star History
77 |
78 | [](https://star-history.com/#ainewsto/comfyui-labs-google&Date)
79 |
80 |
81 | ## 🚀 About me
82 | * website: https://ainewsto.com
83 | * Welcome valuable suggestions! 📧 **Email**: [3508432500@qq.com](mailto:1544007699@qq.com)
84 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 | from .comfyui_whisk import NODE_CLASS_MAPPINGS as WHISK_NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as WHISK_NODE_DISPLAY_NAME_MAPPINGS
2 | from .comfyui_imagefx import NODE_CLASS_MAPPINGS as COMFYUI_IMAGEFX_NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as COMFYUI_IMAGEFX_NODE_DISPLAY_NAME_MAPPINGS
3 |
4 | NODE_CLASS_MAPPINGS = {**WHISK_NODE_CLASS_MAPPINGS, **COMFYUI_IMAGEFX_NODE_CLASS_MAPPINGS}
5 | NODE_DISPLAY_NAME_MAPPINGS = {**WHISK_NODE_DISPLAY_NAME_MAPPINGS, **COMFYUI_IMAGEFX_NODE_DISPLAY_NAME_MAPPINGS}
6 |
7 | __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
8 |
9 |
--------------------------------------------------------------------------------
/comfyui_imagefx.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | import base64
4 | import requests
5 | from io import BytesIO
6 | import numpy as np
7 | import torch
8 | import time
9 | from PIL import Image, UnidentifiedImageError
10 | from typing import List, Union, Tuple
11 | import comfy.utils
12 | from .utils import pil2tensor, tensor2pil
13 | import chardet
14 |
15 | class ComfyUIImageFxNode:
16 | def __init__(self):
17 | self._initialize_auth()
18 | self.aspect_ratio_display = {
19 | "1:1 (Square)": "IMAGE_ASPECT_RATIO_SQUARE",
20 | "9:16 (Portrait)": "IMAGE_ASPECT_RATIO_PORTRAIT",
21 | "16:9 (Landscape)": "IMAGE_ASPECT_RATIO_LANDSCAPE",
22 | "3:4 (Portrait)": "IMAGE_ASPECT_RATIO_PORTRAIT_THREE_FOUR",
23 | "4:3 (Landscape)": "IMAGE_ASPECT_RATIO_LANDSCAPE_FOUR_THREE"
24 | }
25 |
26 | def _initialize_auth(self):
27 | try:
28 | current_dir = os.path.dirname(os.path.abspath(__file__))
29 | config_file_path = os.path.join(current_dir, 'googel.json')
30 |
31 | with open(config_file_path, 'rb') as file:
32 | content = file.read()
33 | encoding = chardet.detect(content)['encoding']
34 |
35 | with open(config_file_path, 'r', encoding=encoding) as f:
36 | self.auth_config = json.load(f)
37 |
38 | self.access_token = self.auth_config.get('access_token')
39 | self.user = self.auth_config.get('user', {})
40 | self.expires = self.auth_config.get('expires')
41 | self.cookies = {cookie['name']: cookie['value'] for cookie in self.auth_config.get('cookies', [])}
42 |
43 | if not self.access_token:
44 | raise ValueError("Access token not found in googel.json")
45 |
46 | except Exception as e:
47 | print(f"Authentication initialization error: {str(e)}")
48 | raise
49 |
50 | @classmethod
51 | def INPUT_TYPES(cls):
52 | aspect_ratios = [
53 | "1:1 (Square)",
54 | "9:16 (Portrait)",
55 | "16:9 (Landscape)",
56 | "3:4 (Portrait)",
57 | "4:3 (Landscape)"
58 | ]
59 | return {
60 | "required": {
61 | "prompt": ("STRING", {"multiline": True}),
62 | "seed": ("INT", {"default": 0, "min": 0, "max": 999999}),
63 | "aspect_ratio": (aspect_ratios, {"default": "16:9 (Landscape)"}),
64 | "num_images": ("INT", {"default": 4, "min": 1, "max": 4})
65 | }
66 | }
67 |
68 | RETURN_TYPES = ("IMAGE", "STRING")
69 | RETURN_NAMES = ("generated_images", "seed")
70 | FUNCTION = "generate_image"
71 | CATEGORY = "comfyui-labs-google"
72 |
73 | def _get_api_aspect_ratio(self, display_ratio: str) -> str:
74 | """Convert display aspect ratio to API format"""
75 | return self.aspect_ratio_display.get(display_ratio, "IMAGE_ASPECT_RATIO_LANDSCAPE")
76 |
77 | def generate_image(self, prompt: str, seed: int, aspect_ratio: str, num_images: int = 4) -> Tuple[torch.Tensor, str]:
78 | pbar = comfy.utils.ProgressBar(100)
79 | session_id = f";{int(time.time() * 1000)}"
80 | api_aspect_ratio = self._get_api_aspect_ratio(aspect_ratio)
81 |
82 | headers = {
83 | "accept": "*/*",
84 | "accept-encoding": "gzip, deflate, br, zstd",
85 | "accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
86 | "authorization": f"Bearer {self.access_token}",
87 | "content-type": "application/json",
88 | "origin": "https://labs.google",
89 | "referer": "https://labs.google/",
90 | "sec-ch-ua": '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"',
91 | "sec-ch-ua-mobile": "?0",
92 | "sec-ch-ua-platform": '"Windows"',
93 | "sec-fetch-dest": "empty",
94 | "sec-fetch-mode": "cors",
95 | "sec-fetch-site": "same-origin",
96 | "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
97 | }
98 |
99 | json_data = {
100 | "userInput": {
101 | "candidatesCount": num_images,
102 | "prompts": [prompt],
103 | "isExpandedPrompt": False,
104 | "seed": seed % 1000000
105 | },
106 | "clientContext": {
107 | "sessionId": session_id,
108 | "tool": "IMAGE_FX"
109 | },
110 | "aspectRatio": api_aspect_ratio,
111 | "modelInput": {
112 | "modelNameType": "IMAGEN_3_1"
113 | }
114 | }
115 |
116 | pbar.update_absolute(20)
117 |
118 | try:
119 | cleaned_headers = {k: v for k, v in headers.items() if not k.startswith(':')}
120 |
121 | response = requests.post(
122 | "https://aisandbox-pa.googleapis.com/v1:runImageFx",
123 | json=json_data,
124 | headers=cleaned_headers,
125 | cookies=self.cookies
126 | )
127 |
128 | response.raise_for_status()
129 | result = response.json()
130 |
131 | pbar.update_absolute(50)
132 |
133 | if "imagePanels" in result:
134 | image_panel = result["imagePanels"][0]
135 | images = []
136 | response_seed = None
137 |
138 | for img_data in image_panel["generatedImages"]:
139 | try:
140 | encoded_image = img_data["encodedImage"]
141 | if response_seed is None:
142 | response_seed = img_data.get("seed", seed)
143 |
144 | # Decode base64 to bytes
145 | if "," in encoded_image:
146 | encoded_image = encoded_image.split(",", 1)[1]
147 | image_bytes = base64.b64decode(encoded_image)
148 |
149 | # Convert to PIL Image
150 | pil_image = Image.open(BytesIO(image_bytes))
151 | img_tensor = pil2tensor(pil_image)
152 | images.append(img_tensor)
153 |
154 | pbar.update_absolute(50 + (40 * len(images) // num_images))
155 |
156 | except Exception as e:
157 | print(f"Error processing image: {str(e)}")
158 |
159 | if images:
160 | # Combine all images into a single tensor with shape [N, H, W, 3]
161 | combined_tensor = torch.cat(images, dim=0)
162 | pbar.update_absolute(100)
163 | return (combined_tensor, str(response_seed))
164 |
165 | # Return empty tensor with correct shape if no valid images
166 | pbar.update_absolute(100)
167 | return (torch.zeros((num_images, 512, 512, 3)), str(seed))
168 |
169 | except requests.exceptions.RequestException as e:
170 | print(f"API request error: {str(e)}")
171 | if hasattr(e.response, 'text'):
172 | print(f"Response content: {e.response.text}")
173 | return (torch.zeros((num_images, 512, 512, 3)), str(seed))
174 | except Exception as e:
175 | print(f"Error generating images: {str(e)}")
176 | return (torch.zeros((num_images, 512, 512, 3)), str(seed))
177 |
178 |
179 | NODE_CLASS_MAPPINGS = {
180 | "ComfyUI-ImageFx": ComfyUIImageFxNode
181 | }
182 |
183 | NODE_DISPLAY_NAME_MAPPINGS = {
184 | "ComfyUI-ImageFx": "ComfyUI-ImageFx🖼️"
185 | }
186 |
--------------------------------------------------------------------------------
/comfyui_whisk.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | import base64
4 | import requests
5 | from io import BytesIO
6 | import numpy as np
7 | import torch
8 | import uuid
9 | import time
10 | from PIL import Image, UnidentifiedImageError
11 | from typing import List, Union
12 | import comfy.utils
13 | from .utils import pil2tensor, tensor2pil
14 | import chardet
15 |
16 | class WhiskNode:
17 | def __init__(self):
18 | self._initialize_auth()
19 |
20 | def _initialize_auth(self):
21 | try:
22 | current_dir = os.path.dirname(os.path.abspath(__file__))
23 | config_file_path = os.path.join(current_dir, 'googel.json')
24 |
25 | with open(config_file_path, 'rb') as file:
26 | content = file.read()
27 | encoding = chardet.detect(content)['encoding']
28 |
29 | with open(config_file_path, 'r', encoding=encoding) as f:
30 | self.auth_config = json.load(f)
31 |
32 | self.access_token = self.auth_config.get('access_token')
33 | self.user = self.auth_config.get('user', {})
34 | self.expires = self.auth_config.get('expires')
35 | self.cookies = {cookie['name']: cookie['value'] for cookie in self.auth_config.get('cookies', [])}
36 |
37 | if not self.access_token:
38 | raise ValueError("Access token not found in googel.json")
39 |
40 | except Exception as e:
41 | print(f"Authentication initialization error: {str(e)}")
42 | raise
43 |
44 | @classmethod
45 | def INPUT_TYPES(cls):
46 | return {
47 | "required": {
48 | "prompt": ("STRING", {"multiline": True}),
49 | "num_images": ("INT", {"default": 2, "min": 1, "max": 4}),
50 | "seed": ("INT", {"default": 0, "min": 0, "max": 2147483647}),
51 | },
52 | "optional": {
53 | "subject_image": ("IMAGE",),
54 | "scene_image": ("IMAGE",),
55 | "style_image": ("IMAGE",),
56 | }
57 | }
58 |
59 | RETURN_TYPES = ("IMAGE", "STRING", "STRING", "STRING", "STRING")
60 | RETURN_NAMES = ("generated_images", "subject_prompt", "scene_prompt", "style_prompt", "prompts")
61 | FUNCTION = "generate_image"
62 | CATEGORY = "comfyui-labs-google"
63 |
64 | def _get_headers(self):
65 | return {
66 | "accept": "*/*",
67 | "accept-encoding": "gzip, deflate, br, zstd",
68 | "accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
69 | "authorization": f"Bearer {self.access_token}",
70 | "content-type": "application/json",
71 | "origin": "https://labs.google",
72 | "referer": "https://labs.google/fx/zh/tools/whisk",
73 | "sec-ch-ua": '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"',
74 | "sec-ch-ua-mobile": "?0",
75 | "sec-ch-ua-platform": '"Windows"',
76 | "sec-fetch-dest": "empty",
77 | "sec-fetch-mode": "cors",
78 | "sec-fetch-site": "same-origin",
79 | "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
80 | }
81 |
82 | def _generate_caption(self, image_data, category, session_id):
83 | """Generate caption for a single image"""
84 | headers = self._get_headers()
85 |
86 | caption_json_data = {
87 | "json": {
88 | "category": category,
89 | "imageBase64": image_data["base64Image"],
90 | "sessionId": session_id
91 | }
92 | }
93 |
94 | try:
95 | caption_response = requests.post(
96 | "https://labs.google/fx/api/trpc/backbone.generateCaption",
97 | json=caption_json_data,
98 | headers=headers,
99 | cookies=self.cookies
100 | )
101 | caption_response.raise_for_status()
102 |
103 | result = caption_response.json()
104 | if "result" in result and "data" in result["result"] and "json" in result["result"]["data"]:
105 | return result["result"]["data"]["json"]
106 | else:
107 | print(f"Error: Unexpected response format from generateCaption API for {category}")
108 | return ""
109 |
110 | except requests.exceptions.RequestException as e:
111 | print(f"generateCaption API request error for {category}: {str(e)}")
112 | return ""
113 |
114 | def _extract_image_data(self, image_tensor, index):
115 | """Extract image data and convert to base64"""
116 | pil_image = tensor2pil(image_tensor)[0] # Convert tensor to PIL image
117 | image_bytes = self._pil_to_bytes(pil_image)
118 | base64_image = base64.b64encode(image_bytes).decode('utf-8')
119 |
120 | return {
121 | "imageId": f"image-{uuid.uuid4()}",
122 | "category": ["CHARACTER", "LOCATION", "STYLE"][index],
123 | "isPlaceholder": False,
124 | "base64Image": f"data:image/jpeg;base64,{base64_image}",
125 | "index": index,
126 | "isUploading": False,
127 | "isLoading": False,
128 | "isSelected": True,
129 | "prompt": ""
130 | }
131 |
132 | def _pil_to_bytes(self, image):
133 | """Convert PIL image to bytes"""
134 | buffered = BytesIO()
135 | image.save(buffered, format="JPEG")
136 | return buffered.getvalue()
137 |
138 | def _generate_payload(self, subject_image, scene_image, style_image, prompt, session_id, num_images):
139 | """Generate the payload based on provided input images"""
140 | payload_data = {
141 | "json": {
142 | "characters": [],
143 | "location": None,
144 | "style": None,
145 | "pose": None,
146 | "additionalInput": prompt,
147 | "sessionId": session_id,
148 | "numImages": num_images
149 | },
150 | "meta": {}
151 | }
152 |
153 | if subject_image is not None and scene_image is not None and style_image is not None:
154 | subject_data = self._extract_image_data(subject_image, 0)
155 | subject_prompt = self._generate_caption(subject_data, "CHARACTER", session_id)
156 | subject_data["prompt"] = subject_prompt
157 | payload_data["json"]["characters"].append(subject_data)
158 |
159 | scene_data = self._extract_image_data(scene_image, 1)
160 | scene_prompt = self._generate_caption(scene_data, "LOCATION", session_id)
161 | scene_data["prompt"] = scene_prompt
162 | payload_data["json"]["location"] = scene_data
163 |
164 | style_data = self._extract_image_data(style_image, 2)
165 | style_prompt = self._generate_caption(style_data, "STYLE", session_id)
166 | style_data["prompt"] = style_prompt
167 | payload_data["json"]["style"] = style_data
168 |
169 | payload_data["meta"]["values"] = {"pose": ["undefined"]}
170 |
171 | elif subject_image is not None and scene_image is not None:
172 | subject_data = self._extract_image_data(subject_image, 0)
173 | subject_prompt = self._generate_caption(subject_data, "CHARACTER", session_id)
174 | subject_data["prompt"] = subject_prompt
175 | payload_data["json"]["characters"].append(subject_data)
176 |
177 | scene_data = self._extract_image_data(scene_image, 1)
178 | scene_prompt = self._generate_caption(scene_data, "LOCATION", session_id)
179 | scene_data["prompt"] = scene_prompt
180 | payload_data["json"]["location"] = scene_data
181 |
182 | payload_data["meta"]["values"] = {"style": ["undefined"], "pose": ["undefined"]}
183 |
184 | elif subject_image is not None and style_image is not None:
185 | subject_data = self._extract_image_data(subject_image, 0)
186 | subject_prompt = self._generate_caption(subject_data, "CHARACTER", session_id)
187 | subject_data["prompt"] = subject_prompt
188 | payload_data["json"]["characters"].append(subject_data)
189 |
190 | style_data = self._extract_image_data(style_image, 2)
191 | style_prompt = self._generate_caption(style_data, "STYLE", session_id)
192 | style_data["prompt"] = style_prompt
193 | payload_data["json"]["style"] = style_data
194 |
195 | payload_data["meta"]["values"] = {"location": ["undefined"], "pose": ["undefined"]}
196 |
197 | elif scene_image is not None and style_image is not None:
198 | scene_data = self._extract_image_data(scene_image, 1)
199 | scene_prompt = self._generate_caption(scene_data, "LOCATION", session_id)
200 | scene_data["prompt"] = scene_prompt
201 | payload_data["json"]["location"] = scene_data
202 |
203 | style_data = self._extract_image_data(style_image, 2)
204 | style_prompt = self._generate_caption(style_data, "STYLE", session_id)
205 | style_data["prompt"] = style_prompt
206 | payload_data["json"]["style"] = style_data
207 |
208 | payload_data["meta"]["values"] = {"pose": ["undefined"]}
209 |
210 | elif subject_image is not None:
211 | subject_data = self._extract_image_data(subject_image, 0)
212 | subject_prompt = self._generate_caption(subject_data, "CHARACTER", session_id)
213 | subject_data["prompt"] = subject_prompt
214 | payload_data["json"]["characters"].append(subject_data)
215 |
216 | payload_data["meta"]["values"] = {"location": ["undefined"], "style": ["undefined"], "pose": ["undefined"]}
217 |
218 | elif scene_image is not None:
219 | scene_data = self._extract_image_data(scene_image, 1)
220 | scene_prompt = self._generate_caption(scene_data, "LOCATION", session_id)
221 | scene_data["prompt"] = scene_prompt
222 | payload_data["json"]["location"] = scene_data
223 |
224 | payload_data["meta"]["values"] = {"style": ["undefined"], "pose": ["undefined"]}
225 |
226 | elif style_image is not None:
227 | style_data = self._extract_image_data(style_image, 2)
228 | style_prompt = self._generate_caption(style_data, "STYLE", session_id)
229 | style_data["prompt"] = style_prompt
230 | payload_data["json"]["style"] = style_data
231 |
232 | payload_data["meta"]["values"] = {"location": ["undefined"], "pose": ["undefined"]}
233 |
234 | return payload_data
235 |
236 | def generate_image(self, prompt, subject_image=None, scene_image=None, style_image=None, num_images=2, seed=0):
237 | pbar = comfy.utils.ProgressBar(100)
238 | session_id = f";{int(time.time() * 1000)}"
239 |
240 | payload_data = self._generate_payload(subject_image, scene_image, style_image, prompt, session_id, num_images)
241 |
242 | pbar.update_absolute(30)
243 |
244 | try:
245 | storyboard_response = requests.post(
246 | "https://labs.google/fx/api/trpc/backbone.generateStoryBoardPrompt",
247 | json=payload_data,
248 | headers=self._get_headers(),
249 | cookies=self.cookies
250 | )
251 | storyboard_response.raise_for_status()
252 | storyboard_result = storyboard_response.json()
253 |
254 | if "result" in storyboard_result and "data" in storyboard_result["result"]:
255 | storyboard_prompt = storyboard_result["result"]["data"]["json"]
256 | else:
257 | print("Error: Unexpected response from generateStoryBoardPrompt API")
258 | storyboard_prompt = ""
259 |
260 | except requests.exceptions.RequestException as e:
261 | print(f"generateStoryBoardPrompt API request error: {str(e)}")
262 | storyboard_prompt = ""
263 |
264 | pbar.update_absolute(50)
265 |
266 | imagefx_json_data = {
267 | "userInput": {
268 | "candidatesCount": num_images,
269 | "prompts": [storyboard_prompt],
270 | "isExpandedPrompt": False,
271 | "seed": seed % 2147483647
272 | },
273 | "clientContext": {
274 | "sessionId": session_id,
275 | "tool": "BACKBONE"
276 | },
277 | "aspectRatio": "IMAGE_ASPECT_RATIO_LANDSCAPE",
278 | "modelInput": {
279 | "modelNameType": "IMAGEN_3_1"
280 | }
281 | }
282 |
283 | generated_images = torch.zeros((num_images, 512, 512, 3))
284 | prompts = []
285 |
286 | try:
287 | imagefx_response = requests.post(
288 | "https://aisandbox-pa.googleapis.com/v1:runImageFx",
289 | json=imagefx_json_data,
290 | headers=self._get_headers(),
291 | cookies=self.cookies
292 | )
293 | imagefx_response.raise_for_status()
294 | imagefx_result = imagefx_response.json()
295 |
296 | if "imagePanels" in imagefx_result:
297 | image_panel = imagefx_result["imagePanels"][0]
298 | images = []
299 |
300 | for img_data in image_panel["generatedImages"]:
301 | encoded_image = img_data["encodedImage"]
302 | if "," in encoded_image:
303 | encoded_image = encoded_image.split(",", 1)[1]
304 |
305 | image_bytes = base64.b64decode(encoded_image)
306 | pil_image = Image.open(BytesIO(image_bytes))
307 | img_tensor = pil2tensor(pil_image)
308 | images.append(img_tensor)
309 |
310 | prompt = image_panel.get("prompt", "")
311 | prompts.append(prompt)
312 |
313 | if images:
314 | generated_images = torch.cat(images, dim=0)
315 | else:
316 | print("Warning: No valid images generated")
317 | else:
318 | print("Warning: No valid image panels in response")
319 |
320 | except requests.exceptions.RequestException as e:
321 | print(f"runImageFx API request error: {str(e)}")
322 |
323 | pbar.update_absolute(100)
324 | return (generated_images,
325 | payload_data['json']['characters'][0]['prompt'] if payload_data['json']['characters'] else "",
326 | payload_data['json']['location']['prompt'] if payload_data['json']['location'] else "",
327 | payload_data['json']['style']['prompt'] if payload_data['json']['style'] else "",
328 | json.dumps(prompts))
329 |
330 |
331 | class WhiskPromptsNode:
332 | @classmethod
333 | def INPUT_TYPES(cls):
334 | return {
335 | "required": {
336 | "prompts": ("STRING", {"forceInput": True}),
337 | },
338 | }
339 |
340 | RETURN_TYPES = ("STRING", "STRING", "STRING", "STRING")
341 | RETURN_NAMES = ("prompt1", "prompt2", "prompt3", "prompt4")
342 | FUNCTION = "process_prompts"
343 | CATEGORY = "comfyui-labs-google"
344 |
345 | def process_prompts(self, prompts):
346 | prompts_list = json.loads(prompts)
347 | prompts_list += [""] * (4 - len(prompts_list))
348 | return prompts_list[0], prompts_list[1], prompts_list[2], prompts_list[3]
349 |
350 |
351 | NODE_CLASS_MAPPINGS = {
352 | "ComfyUI-Whisk": WhiskNode,
353 | "ComfyUI-Whisk-Prompts": WhiskPromptsNode
354 | }
355 |
356 | NODE_DISPLAY_NAME_MAPPINGS = {
357 | "ComfyUI-Whisk": "ComfyUI-Whisk🌪️",
358 | "ComfyUI-Whisk-Prompts": "ComfyUI-Whisk-Prompts🌪️"
359 | }
360 |
--------------------------------------------------------------------------------
/googel.json:
--------------------------------------------------------------------------------
1 | {
2 | "user": {
3 | "name": "",
4 | "email": "",
5 | "image": ""
6 | },
7 | "expires": "",
8 | "access_token": "",
9 | "cookies": [
10 | {
11 | "name": "_ga",
12 | "value": "GA1.1.206839949.1734415920"
13 | },
14 | {
15 | "name": "EMAIL",
16 | "value": ""
17 | },
18 | {
19 | "name": "__Secure-next-auth.session-token",
20 | "value": ""
21 | },
22 | {
23 | "name": "__Host-next-auth.csrf-token",
24 | "value": ""
25 | }
26 | ]
27 | }
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "labs-google"
3 | description = "NODES: ComfyUI-ImageFx, ComfyUI-Whisk, ComfyUI-Whisk-Prompts"
4 | version = "1.0.0"
5 | license = {file = "LICENSE"}
6 | dependencies = ["requests", "pillow", "chardet"]
7 |
8 | [project.urls]
9 | Repository = "https://github.com/ainewsto/comfyui-labs-google"
10 | # Used by Comfy Registry https://comfyregistry.org
11 |
12 | [tool.comfy]
13 | PublisherId = "ainewsto"
14 | DisplayName = "comfyui-labs-google"
15 | Icon = ""
16 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | requests
2 | pillow
3 | chardet
4 |
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import torch
3 | from PIL import Image
4 | from typing import List, Union
5 |
6 | def pil2tensor(image: Union[Image.Image, List[Image.Image]]) -> torch.Tensor:
7 | """
8 | Convert PIL image(s) to tensor, matching ComfyUI's implementation.
9 |
10 | Args:
11 | image: Single PIL Image or list of PIL Images
12 |
13 | Returns:
14 | torch.Tensor: Image tensor with values normalized to [0, 1]
15 | """
16 | if isinstance(image, list):
17 | if len(image) == 0:
18 | return torch.empty(0)
19 | return torch.cat([pil2tensor(img) for img in image], dim=0)
20 |
21 | # Convert PIL image to RGB if needed
22 | if image.mode == 'RGBA':
23 | image = image.convert('RGB')
24 | elif image.mode != 'RGB':
25 | image = image.convert('RGB')
26 |
27 | # Convert to numpy array and normalize to [0, 1]
28 | img_array = np.array(image).astype(np.float32) / 255.0
29 |
30 | # Return tensor with shape [1, H, W, 3]
31 | return torch.from_numpy(img_array)[None,]
32 |
33 | def tensor2pil(image: torch.Tensor) -> List[Image.Image]:
34 | """
35 | Convert tensor to PIL image(s), matching ComfyUI's implementation.
36 |
37 | Args:
38 | image: Tensor with shape [B, H, W, 3] or [H, W, 3], values in range [0, 1]
39 |
40 | Returns:
41 | List[Image.Image]: List of PIL Images
42 | """
43 | batch_count = image.size(0) if len(image.shape) > 3 else 1
44 | if batch_count > 1:
45 | out = []
46 | for i in range(batch_count):
47 | out.extend(tensor2pil(image[i]))
48 | return out
49 |
50 | # Convert tensor to numpy array, scale to [0, 255], and clip values
51 | numpy_image = np.clip(255.0 * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)
52 |
53 | # Convert numpy array to PIL Image
54 | return [Image.fromarray(numpy_image)]
--------------------------------------------------------------------------------
/workflows/ComfyUI-ImageFx.json:
--------------------------------------------------------------------------------
1 | {
2 | "last_node_id": 14,
3 | "last_link_id": 11,
4 | "nodes": [
5 | {
6 | "id": 12,
7 | "type": "ComfyUI-ImageFx",
8 | "pos": [
9 | 480.75103759765625,
10 | 13.325160026550293
11 | ],
12 | "size": [
13 | 409.5832214355469,
14 | 310.7392272949219
15 | ],
16 | "flags": {},
17 | "order": 0,
18 | "mode": 0,
19 | "inputs": [],
20 | "outputs": [
21 | {
22 | "name": "generated_images",
23 | "type": "IMAGE",
24 | "links": [
25 | 10
26 | ],
27 | "slot_index": 0
28 | },
29 | {
30 | "name": "seed",
31 | "type": "STRING",
32 | "links": [
33 | 11
34 | ],
35 | "slot_index": 1
36 | }
37 | ],
38 | "properties": {
39 | "Node name for S&R": "ComfyUI-ImageFx"
40 | },
41 | "widgets_values": [
42 | "A CHUBBY REAL BLACK CAT WEARING A SAILOR MOON COSTUME SKIING ON A DESERTED SNOW MOUNTAIN",
43 | 84691,
44 | "randomize",
45 | "1:1 (Square)",
46 | 4
47 | ]
48 | },
49 | {
50 | "id": 14,
51 | "type": "ShowText|pysssss",
52 | "pos": [
53 | 486.9401550292969,
54 | 424.43902587890625
55 | ],
56 | "size": [
57 | 406.17877197265625,
58 | 77.33100128173828
59 | ],
60 | "flags": {},
61 | "order": 2,
62 | "mode": 0,
63 | "inputs": [
64 | {
65 | "name": "text",
66 | "type": "STRING",
67 | "link": 11,
68 | "widget": {
69 | "name": "text"
70 | }
71 | }
72 | ],
73 | "outputs": [
74 | {
75 | "name": "STRING",
76 | "type": "STRING",
77 | "links": null,
78 | "shape": 6
79 | }
80 | ],
81 | "properties": {
82 | "Node name for S&R": "ShowText|pysssss"
83 | },
84 | "widgets_values": [
85 | "",
86 | "765655"
87 | ]
88 | },
89 | {
90 | "id": 13,
91 | "type": "PreviewImage",
92 | "pos": [
93 | 963.2437133789062,
94 | -146.41323852539062
95 | ],
96 | "size": [
97 | 866.6326904296875,
98 | 897.4074096679688
99 | ],
100 | "flags": {},
101 | "order": 1,
102 | "mode": 0,
103 | "inputs": [
104 | {
105 | "name": "images",
106 | "type": "IMAGE",
107 | "link": 10
108 | }
109 | ],
110 | "outputs": [],
111 | "properties": {
112 | "Node name for S&R": "PreviewImage"
113 | },
114 | "widgets_values": []
115 | }
116 | ],
117 | "links": [
118 | [
119 | 10,
120 | 12,
121 | 0,
122 | 13,
123 | 0,
124 | "IMAGE"
125 | ],
126 | [
127 | 11,
128 | 12,
129 | 1,
130 | 14,
131 | 0,
132 | "STRING"
133 | ]
134 | ],
135 | "groups": [],
136 | "config": {},
137 | "extra": {
138 | "ds": {
139 | "scale": 0.6830134553650707,
140 | "offset": [
141 | -190.9710638625151,
142 | 333.1789510131922
143 | ]
144 | }
145 | },
146 | "version": 0.4
147 | }
--------------------------------------------------------------------------------
/workflows/ComfyUI-Whisk&ImageFx.json:
--------------------------------------------------------------------------------
1 | {
2 | "last_node_id": 35,
3 | "last_link_id": 58,
4 | "nodes": [
5 | {
6 | "id": 4,
7 | "type": "LoadImage",
8 | "pos": [
9 | -17.200326919555664,
10 | 847.0335083007812
11 | ],
12 | "size": [
13 | 322.08624267578125,
14 | 326.40093994140625
15 | ],
16 | "flags": {},
17 | "order": 0,
18 | "mode": 0,
19 | "inputs": [],
20 | "outputs": [
21 | {
22 | "name": "IMAGE",
23 | "type": "IMAGE",
24 | "links": [
25 | 53
26 | ]
27 | },
28 | {
29 | "name": "MASK",
30 | "type": "MASK",
31 | "links": null
32 | }
33 | ],
34 | "properties": {
35 | "Node name for S&R": "LoadImage"
36 | },
37 | "widgets_values": [
38 | "74304fd80d0b5339469565ed5c0bbd5.jpg",
39 | "image"
40 | ]
41 | },
42 | {
43 | "id": 8,
44 | "type": "ShowText|pysssss",
45 | "pos": [
46 | 399.55047607421875,
47 | 957.962890625
48 | ],
49 | "size": [
50 | 404.6029052734375,
51 | 208.39244079589844
52 | ],
53 | "flags": {},
54 | "order": 7,
55 | "mode": 0,
56 | "inputs": [
57 | {
58 | "name": "text",
59 | "type": "STRING",
60 | "link": 57,
61 | "widget": {
62 | "name": "text"
63 | }
64 | }
65 | ],
66 | "outputs": [
67 | {
68 | "name": "STRING",
69 | "type": "STRING",
70 | "links": null,
71 | "shape": 6
72 | }
73 | ],
74 | "properties": {
75 | "Node name for S&R": "ShowText|pysssss"
76 | },
77 | "widgets_values": [
78 | "",
79 | "A close-up shot with a focus on a subject in the center. The image uses a stylized, almost hyperrealistic rendering technique. The color palette is dominated by warm, glowing oranges and reds, with a strong contrast between light and shadow. The lighting is dramatic, with a strong light source seemingly emanating from behind the subject, creating a rim light effect and highlighting the texture. The overall aesthetic is playful yet slightly sinister, with a focus on creating a sense of depth and vibrancy. The image has a slightly desaturated look, with a focus on warm tones. The texture is soft and plush, giving a sense of depth and realism.\n"
80 | ]
81 | },
82 | {
83 | "id": 7,
84 | "type": "ShowText|pysssss",
85 | "pos": [
86 | 397.2067565917969,
87 | 610.9234619140625
88 | ],
89 | "size": [
90 | 414.1781921386719,
91 | 284.1037902832031
92 | ],
93 | "flags": {},
94 | "order": 6,
95 | "mode": 0,
96 | "inputs": [
97 | {
98 | "name": "text",
99 | "type": "STRING",
100 | "link": 56,
101 | "widget": {
102 | "name": "text"
103 | }
104 | }
105 | ],
106 | "outputs": [
107 | {
108 | "name": "STRING",
109 | "type": "STRING",
110 | "links": null,
111 | "shape": 6
112 | }
113 | ],
114 | "properties": {
115 | "Node name for S&R": "ShowText|pysssss"
116 | },
117 | "widgets_values": [
118 | "",
119 | "A large digital billboard displaying the words \"The ainewsto\" in a sans-serif font on a reddish-orange background hangs from a rocky overhang. Below it, a gray-brown sectional sofa sits on a reddish-brown sandy surface. A person with light skin tone and short, light-colored hair sits on the sofa, wearing a light-colored outfit. Another person, also with light skin tone, is partially visible behind them.\n\nFurther away, another gray-brown sectional sofa is visible. Three people are seated on it. One person appears to be a woman with dark hair and medium skin tone, wearing a light-colored top. Another person appears to be a woman with dark hair and medium skin tone, wearing a dark-colored top. The third person appears to be a man with dark hair and medium skin tone.\n\nIn the background, a large, metallic spacecraft hovers in the air, kicking up dust. The setting appears to be a desert landscape with reddish-brown sand and rocky formations. The sky is clear and light blue. The overall lighting suggests it is daytime. The scene is rendered in a photorealistic style.\n"
120 | ]
121 | },
122 | {
123 | "id": 6,
124 | "type": "ShowText|pysssss",
125 | "pos": [
126 | 400.6974182128906,
127 | 383.5249328613281
128 | ],
129 | "size": [
130 | 404.3658142089844,
131 | 153.22216796875
132 | ],
133 | "flags": {},
134 | "order": 5,
135 | "mode": 0,
136 | "inputs": [
137 | {
138 | "name": "text",
139 | "type": "STRING",
140 | "link": 55,
141 | "widget": {
142 | "name": "text"
143 | }
144 | }
145 | ],
146 | "outputs": [
147 | {
148 | "name": "STRING",
149 | "type": "STRING",
150 | "links": null,
151 | "shape": 6
152 | }
153 | ],
154 | "properties": {
155 | "Node name for S&R": "ShowText|pysssss"
156 | },
157 | "widgets_values": [
158 | "",
159 | "A stylized illustration depicts a large, white rubber ducky floating on a body of water at night. A black cat, wearing an orange baseball cap with the word \"LEO\" in white lettering, sits atop the duck. The cat has bright green eyes. The water is a dark teal, with small ripples and highlights suggesting movement. The background is a deep blue night sky. The duck and cat are brightly lit, creating a contrast with the darker background and water. The style is cartoonish and flat, with minimal shading and detail."
160 | ]
161 | },
162 | {
163 | "id": 2,
164 | "type": "LoadImage",
165 | "pos": [
166 | -12.575531005859375,
167 | 68.97264099121094
168 | ],
169 | "size": [
170 | 316.7715759277344,
171 | 314
172 | ],
173 | "flags": {},
174 | "order": 1,
175 | "mode": 0,
176 | "inputs": [],
177 | "outputs": [
178 | {
179 | "name": "IMAGE",
180 | "type": "IMAGE",
181 | "links": [
182 | 51
183 | ]
184 | },
185 | {
186 | "name": "MASK",
187 | "type": "MASK",
188 | "links": null
189 | }
190 | ],
191 | "properties": {
192 | "Node name for S&R": "LoadImage"
193 | },
194 | "widgets_values": [
195 | "一只巨大的可爱的发光白色鸭子,背上躺着一直绿色眼睛的黑色猫带着橘色的帽子上写着leo,治愈宫崎骏风格,极简简约,在蓝色发光的海中,昏暗简约背景 (1).png",
196 | "image"
197 | ]
198 | },
199 | {
200 | "id": 5,
201 | "type": "PreviewImage",
202 | "pos": [
203 | 859.158935546875,
204 | 67.37272644042969
205 | ],
206 | "size": [
207 | 654.9736938476562,
208 | 1101.5640869140625
209 | ],
210 | "flags": {},
211 | "order": 4,
212 | "mode": 0,
213 | "inputs": [
214 | {
215 | "name": "images",
216 | "type": "IMAGE",
217 | "link": 54
218 | }
219 | ],
220 | "outputs": [],
221 | "properties": {
222 | "Node name for S&R": "PreviewImage"
223 | },
224 | "widgets_values": []
225 | },
226 | {
227 | "id": 18,
228 | "type": "PreviewImage",
229 | "pos": [
230 | 1567.50732421875,
231 | 69.00787353515625
232 | ],
233 | "size": [
234 | 666.172119140625,
235 | 1105.1641845703125
236 | ],
237 | "flags": {},
238 | "order": 14,
239 | "mode": 0,
240 | "inputs": [
241 | {
242 | "name": "images",
243 | "type": "IMAGE",
244 | "link": 20
245 | }
246 | ],
247 | "outputs": [],
248 | "properties": {
249 | "Node name for S&R": "PreviewImage"
250 | },
251 | "widgets_values": []
252 | },
253 | {
254 | "id": 13,
255 | "type": "ShowText|pysssss",
256 | "pos": [
257 | 242.27862548828125,
258 | -184.30130004882812
259 | ],
260 | "size": [
261 | 397.2799987792969,
262 | 184.90000915527344
263 | ],
264 | "flags": {},
265 | "order": 9,
266 | "mode": 0,
267 | "inputs": [
268 | {
269 | "name": "text",
270 | "type": "STRING",
271 | "link": 46,
272 | "widget": {
273 | "name": "text"
274 | }
275 | }
276 | ],
277 | "outputs": [
278 | {
279 | "name": "STRING",
280 | "type": "STRING",
281 | "links": [
282 | 19
283 | ],
284 | "slot_index": 0,
285 | "shape": 6
286 | }
287 | ],
288 | "properties": {
289 | "Node name for S&R": "ShowText|pysssss"
290 | },
291 | "widgets_values": [
292 | "",
293 | "A stylized, hyperrealistic image depicting a large, white rubber ducky floating on a body of water at night. A black cat, wearing an orange baseball cap with the word \"LEO\" in white lettering, sits atop the duck. The cat has bright green eyes. The water is a dark teal, with small ripples and highlights suggesting movement. The duck and cat are brightly lit, creating a strong contrast with the darker background and water. The overall color palette is dominated by warm, glowing oranges and reds, with a strong contrast between light and shadow. The lighting is dramatic, with a strong light source seemingly emanating from behind the duck and cat, creating a rim light effect and highlighting the texture. The background is a large digital billboard displaying \"The ainewsto\" in a sans-serif font on a reddish-orange background, hanging from a rocky overhang. Below it, a gray-brown sectional sofa sits on reddish-brown sand. The scene is set in a desert landscape with reddish-brown sand and rocky formations, under a clear light blue sky. A large, metallic spacecraft hovers in the background, kicking up dust. The style is playful yet slightly sinister, with a slightly desaturated look focusing on warm tones. The texture is soft and plush, giving a sense of depth and realism.\n"
294 | ]
295 | },
296 | {
297 | "id": 14,
298 | "type": "ShowText|pysssss",
299 | "pos": [
300 | 655.3232421875,
301 | -185.16087341308594
302 | ],
303 | "size": [
304 | 394.8599853515625,
305 | 188.52999877929688
306 | ],
307 | "flags": {},
308 | "order": 10,
309 | "mode": 0,
310 | "inputs": [
311 | {
312 | "name": "text",
313 | "type": "STRING",
314 | "link": 47,
315 | "widget": {
316 | "name": "text"
317 | }
318 | }
319 | ],
320 | "outputs": [
321 | {
322 | "name": "STRING",
323 | "type": "STRING",
324 | "links": [],
325 | "slot_index": 0,
326 | "shape": 6
327 | }
328 | ],
329 | "properties": {
330 | "Node name for S&R": "ShowText|pysssss"
331 | },
332 | "widgets_values": [
333 | "",
334 | "A stylized, hyperrealistic image depicting a large, white rubber ducky floating on a body of water at night. A black cat, wearing an orange baseball cap with the word \"LEO\" in white lettering, sits atop the duck. The cat has bright green eyes. The water is a dark teal, with small ripples and highlights suggesting movement. The duck and cat are brightly lit, creating a strong contrast with the darker background and water. The overall color palette is dominated by warm, glowing oranges and reds, with a strong contrast between light and shadow. The lighting is dramatic, with a strong light source seemingly emanating from behind the duck and cat, creating a rim light effect and highlighting the texture. The background is a large digital billboard displaying \"The ainewsto\" in a sans-serif font on a reddish-orange background, hanging from a rocky overhang. Below it, a gray-brown sectional sofa sits on reddish-brown sand. The scene is set in a desert landscape with reddish-brown sand and rocky formations, under a clear light blue sky. A large, metallic spacecraft hovers in the background, kicking up dust. The style is playful yet slightly sinister, with a slightly desaturated look focusing on warm tones. The texture is soft and plush, giving a sense of depth and realism.\n"
335 | ]
336 | },
337 | {
338 | "id": 15,
339 | "type": "ShowText|pysssss",
340 | "pos": [
341 | 1066.5977783203125,
342 | -184.9000244140625
343 | ],
344 | "size": [
345 | 396.0699768066406,
346 | 187.3199920654297
347 | ],
348 | "flags": {},
349 | "order": 11,
350 | "mode": 0,
351 | "inputs": [
352 | {
353 | "name": "text",
354 | "type": "STRING",
355 | "link": 48,
356 | "widget": {
357 | "name": "text"
358 | }
359 | }
360 | ],
361 | "outputs": [
362 | {
363 | "name": "STRING",
364 | "type": "STRING",
365 | "links": [],
366 | "shape": 6
367 | }
368 | ],
369 | "properties": {
370 | "Node name for S&R": "ShowText|pysssss"
371 | },
372 | "widgets_values": [
373 | "",
374 | "A stylized, hyperrealistic image depicting a large, white rubber ducky floating on a body of water at night. A black cat, wearing an orange baseball cap with the word \"LEO\" in white lettering, sits atop the duck. The cat has bright green eyes. The water is a dark teal, with small ripples and highlights suggesting movement. The duck and cat are brightly lit, creating a strong contrast with the darker background and water. The overall color palette is dominated by warm, glowing oranges and reds, with a strong contrast between light and shadow. The lighting is dramatic, with a strong light source seemingly emanating from behind the duck and cat, creating a rim light effect and highlighting the texture. The background is a large digital billboard displaying \"The ainewsto\" in a sans-serif font on a reddish-orange background, hanging from a rocky overhang. Below it, a gray-brown sectional sofa sits on reddish-brown sand. The scene is set in a desert landscape with reddish-brown sand and rocky formations, under a clear light blue sky. A large, metallic spacecraft hovers in the background, kicking up dust. The style is playful yet slightly sinister, with a slightly desaturated look focusing on warm tones. The texture is soft and plush, giving a sense of depth and realism.\n"
375 | ]
376 | },
377 | {
378 | "id": 16,
379 | "type": "ShowText|pysssss",
380 | "pos": [
381 | 1480.5489501953125,
382 | -184.73851013183594
383 | ],
384 | "size": [
385 | 397.2630615234375,
386 | 188.7053985595703
387 | ],
388 | "flags": {},
389 | "order": 12,
390 | "mode": 0,
391 | "inputs": [
392 | {
393 | "name": "text",
394 | "type": "STRING",
395 | "link": 49,
396 | "widget": {
397 | "name": "text"
398 | }
399 | }
400 | ],
401 | "outputs": [
402 | {
403 | "name": "STRING",
404 | "type": "STRING",
405 | "links": [],
406 | "shape": 6
407 | }
408 | ],
409 | "properties": {
410 | "Node name for S&R": "ShowText|pysssss"
411 | },
412 | "widgets_values": [
413 | ""
414 | ]
415 | },
416 | {
417 | "id": 17,
418 | "type": "ComfyUI-ImageFx",
419 | "pos": [
420 | 1893.0498046875,
421 | -187.53294372558594
422 | ],
423 | "size": [
424 | 332.6513977050781,
425 | 191.2154083251953
426 | ],
427 | "flags": {},
428 | "order": 13,
429 | "mode": 0,
430 | "inputs": [
431 | {
432 | "name": "prompt",
433 | "type": "STRING",
434 | "link": 19,
435 | "widget": {
436 | "name": "prompt"
437 | }
438 | }
439 | ],
440 | "outputs": [
441 | {
442 | "name": "generated_images",
443 | "type": "IMAGE",
444 | "links": [
445 | 20
446 | ],
447 | "slot_index": 0
448 | },
449 | {
450 | "name": "seed",
451 | "type": "STRING",
452 | "links": null,
453 | "slot_index": 1
454 | }
455 | ],
456 | "properties": {
457 | "Node name for S&R": "ComfyUI-ImageFx"
458 | },
459 | "widgets_values": [
460 | "",
461 | 954287,
462 | "randomize",
463 | "16:9 (Landscape)",
464 | 3
465 | ]
466 | },
467 | {
468 | "id": 35,
469 | "type": "ComfyUI-Whisk",
470 | "pos": [
471 | 404.9886169433594,
472 | 78.20560455322266
473 | ],
474 | "size": [
475 | 400,
476 | 228
477 | ],
478 | "flags": {},
479 | "order": 3,
480 | "mode": 0,
481 | "inputs": [
482 | {
483 | "name": "subject_image",
484 | "type": "IMAGE",
485 | "link": 51,
486 | "shape": 7
487 | },
488 | {
489 | "name": "scene_image",
490 | "type": "IMAGE",
491 | "link": 52,
492 | "shape": 7
493 | },
494 | {
495 | "name": "style_image",
496 | "type": "IMAGE",
497 | "link": 53,
498 | "shape": 7
499 | }
500 | ],
501 | "outputs": [
502 | {
503 | "name": "generated_images",
504 | "type": "IMAGE",
505 | "links": [
506 | 54
507 | ],
508 | "slot_index": 0
509 | },
510 | {
511 | "name": "subject_prompt",
512 | "type": "STRING",
513 | "links": [
514 | 55
515 | ],
516 | "slot_index": 1
517 | },
518 | {
519 | "name": "scene_prompt",
520 | "type": "STRING",
521 | "links": [
522 | 56
523 | ],
524 | "slot_index": 2
525 | },
526 | {
527 | "name": "style_prompt",
528 | "type": "STRING",
529 | "links": [
530 | 57
531 | ],
532 | "slot_index": 3
533 | },
534 | {
535 | "name": "prompts",
536 | "type": "STRING",
537 | "links": [
538 | 58
539 | ],
540 | "slot_index": 4
541 | }
542 | ],
543 | "properties": {
544 | "Node name for S&R": "ComfyUI-Whisk"
545 | },
546 | "widgets_values": [
547 | "black cat with a duck",
548 | 3,
549 | 1908763980,
550 | "randomize"
551 | ]
552 | },
553 | {
554 | "id": 3,
555 | "type": "LoadImage",
556 | "pos": [
557 | -12.90776252746582,
558 | 455.0110168457031
559 | ],
560 | "size": [
561 | 315,
562 | 314
563 | ],
564 | "flags": {},
565 | "order": 2,
566 | "mode": 0,
567 | "inputs": [],
568 | "outputs": [
569 | {
570 | "name": "IMAGE",
571 | "type": "IMAGE",
572 | "links": [
573 | 52
574 | ]
575 | },
576 | {
577 | "name": "MASK",
578 | "type": "MASK",
579 | "links": null
580 | }
581 | ],
582 | "properties": {
583 | "Node name for S&R": "LoadImage"
584 | },
585 | "widgets_values": [
586 | "leo19000_IMAGE_A_film_poster_with_the_title_The_ainewsto_writte_b2628f27-c56c-42ec-86d0-8f5218b4cd5d.png",
587 | "image"
588 | ]
589 | },
590 | {
591 | "id": 34,
592 | "type": "ComfyUI-Whisk-Prompts",
593 | "pos": [
594 | -3.9363317489624023,
595 | -182.1118927001953
596 | ],
597 | "size": [
598 | 216.0800018310547,
599 | 181.85000610351562
600 | ],
601 | "flags": {},
602 | "order": 8,
603 | "mode": 0,
604 | "inputs": [
605 | {
606 | "name": "prompts",
607 | "type": "STRING",
608 | "link": 58,
609 | "widget": {
610 | "name": "prompts"
611 | }
612 | }
613 | ],
614 | "outputs": [
615 | {
616 | "name": "prompt1",
617 | "type": "STRING",
618 | "links": [
619 | 46
620 | ],
621 | "slot_index": 0
622 | },
623 | {
624 | "name": "prompt2",
625 | "type": "STRING",
626 | "links": [
627 | 47
628 | ],
629 | "slot_index": 1
630 | },
631 | {
632 | "name": "prompt3",
633 | "type": "STRING",
634 | "links": [
635 | 48
636 | ],
637 | "slot_index": 2
638 | },
639 | {
640 | "name": "prompt4",
641 | "type": "STRING",
642 | "links": [
643 | 49
644 | ],
645 | "slot_index": 3
646 | }
647 | ],
648 | "properties": {
649 | "Node name for S&R": "ComfyUI-Whisk-Prompts"
650 | },
651 | "widgets_values": [
652 | ""
653 | ]
654 | }
655 | ],
656 | "links": [
657 | [
658 | 19,
659 | 13,
660 | 0,
661 | 17,
662 | 0,
663 | "STRING"
664 | ],
665 | [
666 | 20,
667 | 17,
668 | 0,
669 | 18,
670 | 0,
671 | "IMAGE"
672 | ],
673 | [
674 | 46,
675 | 34,
676 | 0,
677 | 13,
678 | 0,
679 | "STRING"
680 | ],
681 | [
682 | 47,
683 | 34,
684 | 1,
685 | 14,
686 | 0,
687 | "STRING"
688 | ],
689 | [
690 | 48,
691 | 34,
692 | 2,
693 | 15,
694 | 0,
695 | "STRING"
696 | ],
697 | [
698 | 49,
699 | 34,
700 | 3,
701 | 16,
702 | 0,
703 | "STRING"
704 | ],
705 | [
706 | 51,
707 | 2,
708 | 0,
709 | 35,
710 | 0,
711 | "IMAGE"
712 | ],
713 | [
714 | 52,
715 | 3,
716 | 0,
717 | 35,
718 | 1,
719 | "IMAGE"
720 | ],
721 | [
722 | 53,
723 | 4,
724 | 0,
725 | 35,
726 | 2,
727 | "IMAGE"
728 | ],
729 | [
730 | 54,
731 | 35,
732 | 0,
733 | 5,
734 | 0,
735 | "IMAGE"
736 | ],
737 | [
738 | 55,
739 | 35,
740 | 1,
741 | 6,
742 | 0,
743 | "STRING"
744 | ],
745 | [
746 | 56,
747 | 35,
748 | 2,
749 | 7,
750 | 0,
751 | "STRING"
752 | ],
753 | [
754 | 57,
755 | 35,
756 | 3,
757 | 8,
758 | 0,
759 | "STRING"
760 | ],
761 | [
762 | 58,
763 | 35,
764 | 4,
765 | 34,
766 | 0,
767 | "STRING"
768 | ]
769 | ],
770 | "groups": [],
771 | "config": {},
772 | "extra": {
773 | "ds": {
774 | "scale": 0.513158118230707,
775 | "offset": [
776 | 332.2254294116682,
777 | 345.6596660056208
778 | ]
779 | }
780 | },
781 | "version": 0.4
782 | }
--------------------------------------------------------------------------------
/workflows/ComfyUI-Whisk.json:
--------------------------------------------------------------------------------
1 | {
2 | "last_node_id": 11,
3 | "last_link_id": 9,
4 | "nodes": [
5 | {
6 | "id": 7,
7 | "type": "ShowText|pysssss",
8 | "pos": [
9 | 411.7012939453125,
10 | 597.3950805664062
11 | ],
12 | "size": [
13 | 399.68359375,
14 | 284.1037902832031
15 | ],
16 | "flags": {},
17 | "order": 6,
18 | "mode": 0,
19 | "inputs": [
20 | {
21 | "name": "text",
22 | "type": "STRING",
23 | "link": 6,
24 | "widget": {
25 | "name": "text"
26 | }
27 | }
28 | ],
29 | "outputs": [
30 | {
31 | "name": "STRING",
32 | "type": "STRING",
33 | "links": null,
34 | "shape": 6
35 | }
36 | ],
37 | "properties": {
38 | "Node name for S&R": "ShowText|pysssss"
39 | },
40 | "widgets_values": [
41 | "",
42 | "A large digital billboard displaying the words \"The ainewsto\" in a sans-serif font on a reddish-orange background hangs from a rocky overhang. Below it, a gray modular sectional sofa sits on a reddish-brown sandy surface. A person with light skin tone and short, light-colored hair is seated on the sofa, wearing a light-colored outfit. Another person is partially visible behind them.\n\nFurther away, another gray modular sectional sofa is visible. Three people are seated on it, facing away from the camera. One appears to be a woman with dark hair and medium skin tone, wearing a light-colored top. The other two appear to be a man with dark hair and medium skin tone, and another person whose features are less visible.\n\nIn the background, a large, metallic spacecraft hovers in the sky, emitting a plume of dust or vapor. The landscape is barren and desert-like, with reddish-brown sand and rocky formations. The sky is a clear, light blue. The overall lighting suggests daytime. The scene appears to be digitally rendered.\n"
43 | ]
44 | },
45 | {
46 | "id": 8,
47 | "type": "ShowText|pysssss",
48 | "pos": [
49 | 410.8240051269531,
50 | 962.7944946289062
51 | ],
52 | "size": [
53 | 404.6029052734375,
54 | 208.39244079589844
55 | ],
56 | "flags": {},
57 | "order": 7,
58 | "mode": 0,
59 | "inputs": [
60 | {
61 | "name": "text",
62 | "type": "STRING",
63 | "link": 7,
64 | "widget": {
65 | "name": "text"
66 | }
67 | }
68 | ],
69 | "outputs": [
70 | {
71 | "name": "STRING",
72 | "type": "STRING",
73 | "links": null,
74 | "shape": 6
75 | }
76 | ],
77 | "properties": {
78 | "Node name for S&R": "ShowText|pysssss"
79 | },
80 | "widgets_values": [
81 | "",
82 | "A close-up shot with a focus on a subject in the center. The image uses a stylized, almost hyperrealistic rendering technique. The color palette is dominated by warm, glowing oranges and reds, with a strong contrast between light and shadow. The lighting is dramatic, with a strong light source seemingly emanating from behind the subject, creating a rim light effect and highlighting the texture. The overall aesthetic is playful yet slightly menacing, achieved through the combination of soft textures and intense lighting. The image has a slightly desaturated look, with a focus on the warm tones. The style suggests a digital painting or 3D render with a focus on realistic textures and lighting effects.\n"
83 | ]
84 | },
85 | {
86 | "id": 2,
87 | "type": "LoadImage",
88 | "pos": [
89 | -22.319116592407227,
90 | 68.97264099121094
91 | ],
92 | "size": [
93 | 315,
94 | 314
95 | ],
96 | "flags": {},
97 | "order": 0,
98 | "mode": 0,
99 | "inputs": [],
100 | "outputs": [
101 | {
102 | "name": "IMAGE",
103 | "type": "IMAGE",
104 | "links": [
105 | 1
106 | ]
107 | },
108 | {
109 | "name": "MASK",
110 | "type": "MASK",
111 | "links": null
112 | }
113 | ],
114 | "properties": {
115 | "Node name for S&R": "LoadImage"
116 | },
117 | "widgets_values": [
118 | "一只巨大的可爱的发光白色鸭子,背上躺着一直绿色眼睛的黑色猫带着橘色的帽子上写着leo,治愈宫崎骏风格,极简简约,在蓝色发光的海中,昏暗简约背景 (1).png",
119 | "image"
120 | ]
121 | },
122 | {
123 | "id": 5,
124 | "type": "PreviewImage",
125 | "pos": [
126 | 912.123291015625,
127 | 68.3939437866211
128 | ],
129 | "size": [
130 | 654.9736938476562,
131 | 1101.5640869140625
132 | ],
133 | "flags": {},
134 | "order": 4,
135 | "mode": 0,
136 | "inputs": [
137 | {
138 | "name": "images",
139 | "type": "IMAGE",
140 | "link": 4
141 | }
142 | ],
143 | "outputs": [],
144 | "properties": {
145 | "Node name for S&R": "PreviewImage"
146 | },
147 | "widgets_values": []
148 | },
149 | {
150 | "id": 1,
151 | "type": "ComfyUI-Whisk",
152 | "pos": [
153 | 406.5554504394531,
154 | 68.47631072998047
155 | ],
156 | "size": [
157 | 400,
158 | 228
159 | ],
160 | "flags": {},
161 | "order": 3,
162 | "mode": 0,
163 | "inputs": [
164 | {
165 | "name": "subject_image",
166 | "type": "IMAGE",
167 | "link": 1
168 | },
169 | {
170 | "name": "scene_image",
171 | "type": "IMAGE",
172 | "link": 2
173 | },
174 | {
175 | "name": "style_image",
176 | "type": "IMAGE",
177 | "link": 3
178 | }
179 | ],
180 | "outputs": [
181 | {
182 | "name": "generated_images",
183 | "type": "IMAGE",
184 | "links": [
185 | 4
186 | ],
187 | "slot_index": 0
188 | },
189 | {
190 | "name": "subject_prompt",
191 | "type": "STRING",
192 | "links": [
193 | 5
194 | ],
195 | "slot_index": 1
196 | },
197 | {
198 | "name": "scene_prompt",
199 | "type": "STRING",
200 | "links": [
201 | 6
202 | ],
203 | "slot_index": 2
204 | },
205 | {
206 | "name": "style_prompt",
207 | "type": "STRING",
208 | "links": [
209 | 7
210 | ],
211 | "slot_index": 3
212 | },
213 | {
214 | "name": "seed",
215 | "type": "INT",
216 | "links": null
217 | }
218 | ],
219 | "properties": {
220 | "Node name for S&R": "ComfyUI-Whisk"
221 | },
222 | "widgets_values": [
223 | "black cat with a duck",
224 | 3,
225 | 1664347230,
226 | "randomize"
227 | ]
228 | },
229 | {
230 | "id": 6,
231 | "type": "ShowText|pysssss",
232 | "pos": [
233 | 410.5299377441406,
234 | 379.39453125
235 | ],
236 | "size": [
237 | 393.4757995605469,
238 | 142.33216857910156
239 | ],
240 | "flags": {},
241 | "order": 5,
242 | "mode": 0,
243 | "inputs": [
244 | {
245 | "name": "text",
246 | "type": "STRING",
247 | "link": 5,
248 | "widget": {
249 | "name": "text"
250 | }
251 | }
252 | ],
253 | "outputs": [
254 | {
255 | "name": "STRING",
256 | "type": "STRING",
257 | "links": null,
258 | "shape": 6
259 | }
260 | ],
261 | "properties": {
262 | "Node name for S&R": "ShowText|pysssss"
263 | },
264 | "widgets_values": [
265 | "",
266 | "A black cat wearing an orange baseball cap with the word \"LEO\" on it sits on a large white rubber ducky that floats on a body of water at night. The cat has bright green eyes. The water is a dark teal color and reflects the ducky. The sky is dark blue. The ducky is stylized and cartoonish."
267 | ]
268 | },
269 | {
270 | "id": 3,
271 | "type": "LoadImage",
272 | "pos": [
273 | -20.525474548339844,
274 | 456.7825927734375
275 | ],
276 | "size": [
277 | 315,
278 | 314
279 | ],
280 | "flags": {},
281 | "order": 1,
282 | "mode": 0,
283 | "inputs": [],
284 | "outputs": [
285 | {
286 | "name": "IMAGE",
287 | "type": "IMAGE",
288 | "links": [
289 | 2
290 | ]
291 | },
292 | {
293 | "name": "MASK",
294 | "type": "MASK",
295 | "links": null
296 | }
297 | ],
298 | "properties": {
299 | "Node name for S&R": "LoadImage"
300 | },
301 | "widgets_values": [
302 | "leo19000_IMAGE_A_film_poster_with_the_title_The_ainewsto_writte_b2628f27-c56c-42ec-86d0-8f5218b4cd5d.png",
303 | "image"
304 | ]
305 | },
306 | {
307 | "id": 4,
308 | "type": "LoadImage",
309 | "pos": [
310 | -17.200326919555664,
311 | 847.0335083007812
312 | ],
313 | "size": [
314 | 322.08624267578125,
315 | 326.40093994140625
316 | ],
317 | "flags": {},
318 | "order": 2,
319 | "mode": 0,
320 | "inputs": [],
321 | "outputs": [
322 | {
323 | "name": "IMAGE",
324 | "type": "IMAGE",
325 | "links": [
326 | 3
327 | ]
328 | },
329 | {
330 | "name": "MASK",
331 | "type": "MASK",
332 | "links": null
333 | }
334 | ],
335 | "properties": {
336 | "Node name for S&R": "LoadImage"
337 | },
338 | "widgets_values": [
339 | "74304fd80d0b5339469565ed5c0bbd5.jpg",
340 | "image"
341 | ]
342 | }
343 | ],
344 | "links": [
345 | [
346 | 1,
347 | 2,
348 | 0,
349 | 1,
350 | 0,
351 | "IMAGE"
352 | ],
353 | [
354 | 2,
355 | 3,
356 | 0,
357 | 1,
358 | 1,
359 | "IMAGE"
360 | ],
361 | [
362 | 3,
363 | 4,
364 | 0,
365 | 1,
366 | 2,
367 | "IMAGE"
368 | ],
369 | [
370 | 4,
371 | 1,
372 | 0,
373 | 5,
374 | 0,
375 | "IMAGE"
376 | ],
377 | [
378 | 5,
379 | 1,
380 | 1,
381 | 6,
382 | 0,
383 | "STRING"
384 | ],
385 | [
386 | 6,
387 | 1,
388 | 2,
389 | 7,
390 | 0,
391 | "STRING"
392 | ],
393 | [
394 | 7,
395 | 1,
396 | 3,
397 | 8,
398 | 0,
399 | "STRING"
400 | ]
401 | ],
402 | "groups": [],
403 | "config": {},
404 | "extra": {
405 | "ds": {
406 | "scale": 0.6209213230591554,
407 | "offset": [
408 | 364.3393088895507,
409 | 106.61671731381173
410 | ]
411 | }
412 | },
413 | "version": 0.4
414 | }
--------------------------------------------------------------------------------