├── .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 | ![新建项目](https://github.com/user-attachments/assets/fad1e0ab-7fe4-41bb-b65d-fd2b1b936f08) 2 | 3 | ![whisk_storyboard125f1524db374ba182fb3bc29c6559](https://github.com/user-attachments/assets/cea9358d-9e6b-4b03-ba8e-fa048314c8ca) 4 | 5 |
6 | 7 | Static Badge 8 | # 👋🏻 如何设置api(非官方)? 9 | ## 视频教程地址:https://www.bilibili.com/video/BV1NnrCYCE9d 10 | ## 请打开googel.json文件,如下图所示 11 | 12 | ![3736698276867701ade5ba6e8f34545](https://github.com/user-attachments/assets/5914fa4a-db9a-4552-8b36-6adc4b7eaffd) 13 | 14 |
15 | 16 | 17 | * `"user","expires","access_token","EMAIL" `: 这个几个数值在下图所示的位置找到并且填写好~ 18 | 19 | ![ac1ec09cc0d8f5968b2b188f695f014](https://github.com/user-attachments/assets/44c4aa13-e551-483b-87f0-46110c3b9187) 20 | 21 | 22 | 23 | * `"cookies" `: 这个需要在Whisk界面随便上传一张图片才会出现,然后看下面图片所示,并且填写好保存 24 | 25 | ![049cdc2fcd74fcc47540c6f0d856bc6](https://github.com/user-attachments/assets/4d9e2639-f41e-41e2-9229-b91ef01788f4) 26 | 27 | ![d2878b8880c98048673d2832d2fec4d](https://github.com/user-attachments/assets/9b492f47-29dc-4843-a9e0-8862d25175f5) 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 | ![8fdf6a4ac8beb4650c0afb31e3a1cc9](https://github.com/user-attachments/assets/a50723a0-78b5-4554-922c-aa416d496ad4) 42 | 43 | 44 | ## ComfyUI-ImageFx🖼️ 45 | * `ImageFx`: 跟官方一样,就是文生图节点。 46 | ![8b614f5cc8fdecb56c278ff74f0818d](https://github.com/user-attachments/assets/e93849e1-0414-4110-83a5-77716d230d2d) 47 | 48 | 49 | ## ComfyUI-Whisk-Prompts🌪️ 50 | * `Whisk-Prompts`: 用来输出最终生成图片的提示词节点。 51 | ![1e555771af62beeeb7a7d7903e52a41](https://github.com/user-attachments/assets/95736792-b83b-4b02-8bea-e516d916825c) 52 | 53 | 54 | # 更新 Update: 55 | 56 | 20250110:`ComfyUI-Whisk🌪️`: 修改图片输入接口可以任意输入图片,生成不同效果,不需要同时输入3张。 57 | 新增节点:ComfyUI-Whisk-Prompts🌪️ 58 |
59 | 查看更新/Update 60 | 61 | ![c4a3a8e27ce5ab65fbb18d897ce0bd2](https://github.com/user-attachments/assets/e7247daa-5ed2-4614-8660-aff9bd640f80) 62 | ![0ab3139bdde955b8bdb1249207847ca](https://github.com/user-attachments/assets/1a5a0fbe-8415-4dd3-9401-624d1a5e4e5a) 63 | ![7c851d570fedef52fceb220c31a22b2](https://github.com/user-attachments/assets/7f2af700-2a97-4451-8448-7439c239b738) 64 | ![b2ba12be74c7209f0c8fdd3ce20cd55](https://github.com/user-attachments/assets/14f0db0e-1d2a-4282-8d30-0de03bef607b) 65 | 66 | 67 |
68 | 69 | # :dizzy:插件感谢原项目 Comfy Resources: 70 | 71 | 72 | https://github.com/comfyanonymous/ComfyUI 73 | 74 | 75 | 76 | ## Star History 77 | 78 | [![Star History Chart](https://api.star-history.com/svg?repos=ainewsto/comfyui-labs-google&type=Date)](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 | } --------------------------------------------------------------------------------