Compare commits

..
Author SHA1 Message Date
BriaOr 8cf75db231 Update Readme.md 2025-01-09 11:30:25 +02:00
or 3af0cc4341 new doc version updated 2025-01-09 11:02:26 +02:00
or 1d10365fe1 V1 of the documentation 2025-01-08 18:22:02 +02:00
or f50bf3f2ed Added more changes 2025-01-08 18:08:37 +02:00
or e4ea36e135 Added coming soon 2025-01-08 15:33:00 +02:00
or f42b100e1b Added modifications to the readme 2025-01-08 15:23:12 +02:00
BriaOr 424678c8e8 Merge pull request #2 from Bria-AI/t2i-comfy
nodes folder
2025-01-07 15:10:10 +02:00
Tair e4cf57f129 nodes folder 2025-01-06 16:47:06 +00:00
BriaOr c45ad0647d Update Readme.md 2024-12-22 22:31:02 +02:00
or 158838158b Added product shot generation collaterals 2024-12-22 22:30:22 +02:00
ori-liberman 6c1d953896 Merge branch 'main' of https://github.com/Bria-AI/ComfyUI-BRIA-API into main 2024-12-22 14:21:17 +00:00
ori-liberman 808721a995 Change optimize_description and enhance_ref_image types from BOOLEAN to INT 2024-12-22 14:21:15 +00:00
OriL 7510ccca3a Update Readme.md 2024-12-22 15:21:03 +02:00
BriaOr 7d3edf6174 Update Readme.md 2024-12-22 11:42:51 +02:00
OriL 396d56eb2a Add files via upload 2024-12-19 15:19:45 +02:00
OriL e4a6238935 Update Readme.md 2024-12-19 14:40:40 +02:00
ori-liberman 796013d91a Bump version to 1.0.2 in pyproject.toml 2024-12-19 08:07:59 +00:00
ori-liberman 0b935dcffc Add ShotByTextNode and ShotByImageNode classes with API integration 2024-12-18 15:11:57 +00:00
BriaOr 99155fb898 Update Readme.md 2024-12-03 18:28:55 +02:00
or c266970425 Updated readme and new workflows 2024-12-03 18:26:49 +02:00
or 83a1f760f4 updated genfill node 2024-12-03 18:17:00 +02:00
DvirYBria 7886ec31e2 Update Readme.md 2024-12-03 15:17:16 +02:00
or cbd980ac92 Working GenFill node 2024-12-03 11:53:37 +02:00
DvirYBria 0ef5288ff6 Update pyproject.toml 2024-12-02 15:40:38 +02:00
DvirYBria 928091f7bb Update __init__.py 2024-12-02 15:35:48 +02:00
DvirYBria 0a0e7eebaa Update __init__.py 2024-12-02 15:33:52 +02:00
DvirYBria 6357dfccf0 Update __init__.py 2024-12-02 15:27:38 +02:00
BriaOr 9e6f75a7bf Merge pull request #1 from Bria-AI/generative_fill_node
Update and added GenFill node bria_api_node.py
2024-12-02 09:11:49 +01:00
19 changed files with 847 additions and 116 deletions
+1
View File
@@ -0,0 +1 @@
*.pyc
+48 -15
View File
@@ -1,30 +1,30 @@
# BRIA ComfyUI API Nodes
## Overview
This repository contains custom nodes for ComfyUI that allow access to BRIA's API endpoints. You can find our API documentation [here](https://bria-ai-api-docs.redoc.ly/#operation//generation/bria-v2/text-to-image).
<p align="center" style="background-color:black; padding:10px;">
<img src="./images/Bria Logo.svg" alt="BRIA Logo" width="200"/>
</p>
To use the nodes in the workflow, you need a valid BRIA API token. You can get one [here](https://bria.ai/api/) (with 1000 free calls)
This repository provides custom nodes for ComfyUI, enabling direct access to **BRIA's API endpoints** for image generation workflows. **API documentation** is available [**here**](https://bria-ai-api-docs.redoc.ly/#operation//generation/bria-v2/text-to-image).
You can load the workflow, which includes all available nodes, by importing the [workflow.json](workflow.json) file in this repo.
An API token is required to use the nodes in your workflows. Get started quickly here
<a href="https://bria.ai/api/" style="text-decoration:none; vertical-align:middle;">
<img src="https://img.shields.io/badge/GET%20YOUR%20TOKEN-1000%20Free%20Calls-blue?style=flat-square" alt="Get Your Token" height="20">
</a>.
You can also download the following image and import it to comfyui:
To load a workflow, import the compatible workflow.json files from this [folder](workflows).
<img src="./images/eraser_workflow.png" alt="Original image" width="500"/>
An illustration of the workflow:
<!-- Placeholder image of cool workflows. -->
<img src="./images/eraser_workflow_diagram.jpg" alt="Eraser workflow example" width="650"/> <img src="./images/original_image.jpg" alt="Original image" width="150"/>
## Available Nodes
<!-- <img src="./images/bria_api_nodes_workflow_diagram.png" alt="all workflows example" width="400"/> <img src="./images/bria_api_nodes_workflow_diagram_2.png" alt="all workflows example" width="400"/> -->
### Eraser
The **Eraser** node allows users to remove specific objects or areas from an image by providing a mask.
# Coming soon
This functionality is powered by BRIA's ControlNet inpainting, available on [this model card](https://huggingface.co/briaai/BRIA-2.3-ControlNet-Inpainting) on Hugging Face.
- [ ] Image Generation
- [ ] Video Editing
You can also try out BRIA's Eraser demo by visiting our Hugging Face space [here](https://huggingface.co/spaces/briaai/BRIA-Eraser-API).
## Installation
# Installation
There are two methods to install the BRIA ComfyUI API nodes:
### Method 1: Using ComfyUI's Custom Node Manager
@@ -43,3 +43,36 @@ There are two methods to install the BRIA ComfyUI API nodes:
```
3. Restart ComfyUI and load the workflows.
# Available Nodes
## Tailored Generation Nodes
These nodes use pre-trained tailored models to generate images in a specific visual style based on provided samples. [[API docs](https://bria-ai-api-docs.redoc.ly/tag/Tailored-Generation)].
### **Tailored Model Info**
This node retrieves the **default settings** and **prompt prefix** of a **trained tailored model**. It provides the necessary information to configure and run the model in the **Tailored Gen node**, ensuring consistency with the model's intended behavior.
### **Tailored Gen**
This node is used to generate using a trained tailored model. It is designed to preserve the visual characteristics and ensure style fidelity established during model training.
## Image Editing Nodes
These nodes modify specific parts of images, enabling adjustments, while maintaining the integrity of the rest of the image.[[API docs](https://bria-ai-api-docs.redoc.ly/tag/Image-Editing)]
### **Eraser**
This node is used to remove specific objects or areas from an image by providing a mask. Powered by BRIA's ControlNet inpainting [[🤗model card](https://huggingface.co/briaai/BRIA-2.3-ControlNet-Inpainting)] [[🤗HF demo](https://huggingface.co/spaces/briaai/BRIA-Eraser-API)].
### **GenFill**
This node is used to generate objects by prompt in a specific region of an image. This functionality is powered by BRIA's ControlNet Generative Fill. [[🤗model card](https://huggingface.co/briaai/BRIA-2.3-ControlNet-Generative-Fill)] [[🤗HF demo](https://huggingface.co/spaces/briaai/BRIA-Generative-Fill-API)]
## Product Shot Generation Nodes
These nodes create high-quality product images for eCommerce workflows. [[API docs](https://bria-ai-api-docs.redoc.ly/tag/Product-Shots-Generation)]
### **ShotByText**
This node is used to modify the background in an image by providing a prompt, This functionality is powered by BRIA's ControlNet Background-Generation.[[🤗ContrlNet model card](https://huggingface.co/briaai/BRIA-2.3-ControlNet-BG-Gen)] [[🤗HF demo](https://huggingface.co/spaces/briaai/Product-Shot-Generation)].
### **ShotByImage**
This node is used to modify the background in an image by providing a reference image. This functionality is powered by BRIA's ControlNet Background-Generation and BRIA's Image-Prompt. [[🤗ContrlNet model card](https://huggingface.co/briaai/BRIA-2.3-ControlNet-Inpainting)] [[🤗IP-Adapter model card](https://huggingface.co/briaai/Image-Prompt)] [[🤗HF demo](https://huggingface.co/spaces/briaai/Product-Shot-Generation)].
<!-- ### Campaign generation
Coming soon -->
+7 -3
View File
@@ -1,11 +1,15 @@
from .bria_api_node import EraserNode
from .nodes import EraserNode, GenFillNode, ShotByTextNode, ShotByImageNode
# Map the node class to a name used internally by ComfyUI
NODE_CLASS_MAPPINGS = {
"BriaEraser": EraserNode, # Return the class, not an instance
"BriaGenFill": GenFillNode,
"ShotByTextNode": ShotByTextNode,
"ShotByImageNode": ShotByImageNode,
}
# Map the node display name to the one shown in the ComfyUI node interface
NODE_DISPLAY_NAME_MAPPINGS = {
"BriaEraser": "Bria Eraser",
"BriaGenFill": "Bria GenFill",
"ShotByTextNode": "Bria Shot By Text",
"ShotByImageNode": "Bria Shot By Image",
}
+21
View File
@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="132" height="85.104" viewBox="0 0 132 85.104">
<defs>
<style>
.cls-2{fill:#5300c9}.cls-3{fill:#80f}
</style>
</defs>
<g id="Logo" transform="translate(-471.45 -246.19)">
<circle id="Ellipse_1" data-name="Ellipse 1" cx="9.553" cy="9.553" r="9.553" transform="translate(560.271 310.103)" style="fill:#d80067"/>
<g id="Group_56" data-name="Group 56" transform="translate(471.45 246.19)">
<path id="Path_504" data-name="Path 504" class="cls-2" d="M690.915 569.28h-6.548a.077.077 0 0 0-.078.078v6.042a.077.077 0 0 0 .078.078h6.421c2.237 0 3.46-1.224 3.46-3.164a3.008 3.008 0 0 0-3.333-3.034z" transform="translate(-652.51 -521.037)"/>
<path id="Path_505" data-name="Path 505" class="cls-2" d="M684.378 502.736h6a3.179 3.179 0 0 0 3.24-2.044 3.127 3.127 0 0 0-3.039-4.032h-6.2a.077.077 0 0 0-.078.078v5.922a.077.077 0 0 0 .077.076z" transform="translate(-652.518 -459.261)"/>
<path id="Path_506" data-name="Path 506" class="cls-2" d="M877.962 498.92h-6.5a.077.077 0 0 0-.078.078v6.639a.077.077 0 0 0 .078.078h6.5c2.489 0 4.093-1.35 4.093-3.418 0-2.027-1.604-3.377-4.093-3.377z" transform="translate(-811.664 -461.183)"/>
<path id="Path_507" data-name="Path 507" class="cls-2" d="M552.856 278.056a.077.077 0 0 1 .078-.078h2.244a42.566 42.566 0 1 0-2.322 28.112zm-41.9 28.191h-14.609a.077.077 0 0 1-.078-.078v-28.113a.077.077 0 0 1 .078-.078h14.564c5.19 0 8.565 3.08 8.565 7.721a5.646 5.646 0 0 1-4.641 5.949v.169c2.616.211 5.443 2.237 5.443 6.5 0 4.683-3.164 7.929-9.325 7.929zm30.8 0a.074.074 0 0 1-.058-.027l-8.477-9.652a.08.08 0 0 0-.058-.027h-1.913a.077.077 0 0 0-.078.078v9.55a.077.077 0 0 1-.078.078h-6.807a.077.077 0 0 1-.078-.078v-28.113a.077.077 0 0 1 .078-.078h14.227c6.117 0 10.168 3.712 10.168 9.24 0 4.6-2.818 7.914-7.3 8.959a.075.075 0 0 0-.04.124l8.658 9.817a.077.077 0 0 1-.058.128z" transform="translate(-471.45 -246.19)"/>
</g>
<g id="Group_57" data-name="Group 57" transform="translate(557.15 259.772)">
<path id="Path_508" data-name="Path 508" class="cls-3" d="M1147.2 613.979a.078.078 0 0 0-.072-.049h-11.793a.076.076 0 0 0-.072.049l-1.327 3.446a23.417 23.417 0 0 0 15.136 1.414z" transform="translate(-1120.72 -572.602)"/>
<path id="Path_509" data-name="Path 509" class="cls-3" d="M1068.251 337.15a23.451 23.451 0 0 0-22.851 18.206h2.591a.077.077 0 0 1 .078.078v17.094a23.542 23.542 0 0 0 4.712 5.68l9.529-22.8a.078.078 0 0 1 .072-.048h7.028a.079.079 0 0 1 .072.048l10.624 25.421a23.445 23.445 0 0 0-11.854-43.675z" transform="translate(-1045.4 -337.15)"/>
<path id="Path_510" data-name="Path 510" class="cls-3" d="M1166.073 521.687a.077.077 0 0 0 .072-.106l-3.515-8.992a.078.078 0 0 0-.145 0l-3.475 8.992a.078.078 0 0 0 .072.106z" transform="translate(-1142.042 -486.351)"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

+4
View File
@@ -0,0 +1,4 @@
from .eraser_node import EraserNode
from .generative_fill_node import GenFillNode
from .shot_by_text_node import ShotByTextNode
from .shot_by_image_node import ShotByImageNode
+8 -97
View File
@@ -33,6 +33,14 @@ class BriaAPINode:
print("Unexpected mask dimensions. Expected 3D tensor.")
return mask
def postprocess_image(self, image):
result_image = Image.open(io.BytesIO(image))
result_image = result_image.convert("RGB")
result_image = np.array(result_image).astype(np.float32) / 255.0
result_image = torch.from_numpy(result_image)[None,]
return result_image
def image_to_base64(self, pil_image):
# Convert a PIL image to a base64-encoded string
buffered = io.BytesIO()
@@ -86,100 +94,3 @@ class BriaAPINode:
except Exception as e:
raise Exception(f"{e}")
# Eraser Node
class EraserNode(BriaAPINode):
@staticmethod
def INPUT_TYPES():
return {
"required": {
"image": ("IMAGE",), # Input image from another node
"mask": ("MASK",), # Binary mask input
"api_key": ("STRING", {"default": "BRIA_API_TOKEN"}) # API Key input with a default value
}
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("output_image",)
CATEGORY = "API Nodes"
FUNCTION = "execute" # This is the method that will be executed
def __init__(self):
super().__init__("https://engine.prod.bria-api.com/v1/eraser") # Eraser API URL
# Define the execute method as expected by ComfyUI
def execute(self, image, mask, api_key):
return self.process_request(image, mask, api_key)
# Generative Fill Node
class GenerativeFillNode(BriaAPINode):
@staticmethod
def INPUT_TYPES():
return {
"required": {
"image": ("IMAGE",), # Input image from another node
"mask": ("MASK",), # Binary mask input
"prompt": ("STRING",),
"api_key": ("STRING", {"default": "BRIA_API_TOKEN"}), # API Key input with a default value
},
"optional": {
"negative_prompt": ("STRING", {"default": None}),
},
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("output_image",)
CATEGORY = "API Nodes"
FUNCTION = "execute" # This is the method that will be executed
def __init__(self):
super().__init__("https://engine.prod.bria-api.com/v1/gen_fill") # Eraser API URL
# Define the execute method as expected by ComfyUI
def execute(self, image, mask, prompt, negative_prompt, api_key):
if api_key.strip() == "" or api_key.strip() == "BRIA_API_TOKEN":
raise Exception("Please insert a valid API key.")
# Check if image and mask are tensors, if so, convert to NumPy arrays
if isinstance(image, torch.Tensor):
image = self.preprocess_image(image)
if isinstance(mask, torch.Tensor):
mask = self.preprocess_mask(mask)
# Convert the image and mask directly to Base64 strings
image_base64 = self.image_to_base64(image)
mask_base64 = self.image_to_base64(mask)
# Prepare the API request payload
payload = {
"file": f"{image_base64}",
"mask_file": f"{mask_base64}",
"prompt": prompt,
"negative_prompt": negative_prompt,
"sync": True
}
headers = {
"Content-Type": "application/json",
"api_token": f"{api_key}"
}
try:
response = requests.post(self.api_url, json=payload, headers=headers)
# Check for successful response
if response.status_code == 200:
print('response is 200')
# Process the output image from API response
response_dict = response.json()
image_response = requests.get(response_dict['urls'][0])
result_image = Image.open(io.BytesIO(image_response.content))
result_image = result_image.convert("RGB")
result_image = np.array(result_image).astype(np.float32) / 255.0
result_image = torch.from_numpy(result_image)[None,]
return (result_image,)
else:
raise Exception(f"Error: API request failed with status code {response.status_code}")
except Exception as e:
raise Exception(f"{e}")
+34
View File
@@ -0,0 +1,34 @@
import numpy as np
import requests
from PIL import Image
import io
import base64
from torchvision.transforms import ToPILImage, ToTensor
import torch
from .base_node import BriaAPINode
# Eraser Node
class EraserNode(BriaAPINode):
@staticmethod
def INPUT_TYPES():
return {
"required": {
"image": ("IMAGE",), # Input image from another node
"mask": ("MASK",), # Binary mask input
"api_key": ("STRING", {"default": "BRIA_API_TOKEN"}) # API Key input with a default value
}
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("output_image",)
CATEGORY = "API Nodes"
FUNCTION = "execute" # This is the method that will be executed
def __init__(self):
super().__init__("https://engine.prod.bria-api.com/v1/eraser") # Eraser API URL
# Define the execute method as expected by ComfyUI
def execute(self, image, mask, api_key):
return self.process_request(image, mask, api_key)
+79
View File
@@ -0,0 +1,79 @@
import numpy as np
import requests
from PIL import Image
import io
import base64
from torchvision.transforms import ToPILImage, ToTensor
import torch
from .base_node import BriaAPINode
# Generative Fill Node
class GenFillNode(BriaAPINode):
@staticmethod
def INPUT_TYPES():
return {
"required": {
"image": ("IMAGE",), # Input image from another node
"mask": ("MASK",), # Binary mask input
"prompt": ("STRING",),
"api_key": ("STRING", {"default": "BRIA_API_TOKEN"}), # API Key input with a default value
},
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("output_image",)
CATEGORY = "API Nodes"
FUNCTION = "execute" # This is the method that will be executed
def __init__(self):
super().__init__("https://engine.prod.bria-api.com/v1/gen_fill") # Eraser API URL
# Define the execute method as expected by ComfyUI
def execute(self, image, mask, prompt, api_key):
if api_key.strip() == "" or api_key.strip() == "BRIA_API_TOKEN":
raise Exception("Please insert a valid API key.")
# Check if image and mask are tensors, if so, convert to NumPy arrays
if isinstance(image, torch.Tensor):
image = self.preprocess_image(image)
if isinstance(mask, torch.Tensor):
mask = self.preprocess_mask(mask)
# Convert the image and mask directly to Base64 strings
image_base64 = self.image_to_base64(image)
mask_base64 = self.image_to_base64(mask)
# Prepare the API request payload
payload = {
"file": f"{image_base64}",
"mask_file": f"{mask_base64}",
"prompt": prompt,
"negative_prompt": "blurry",
"sync": True
}
headers = {
"Content-Type": "application/json",
"api_token": f"{api_key}"
}
try:
response = requests.post(self.api_url, json=payload, headers=headers)
# Check for successful response
if response.status_code == 200:
print('response is 200')
# Process the output image from API response
response_dict = response.json()
image_response = requests.get(response_dict['urls'][0])
result_image = Image.open(io.BytesIO(image_response.content))
result_image = result_image.convert("RGB")
result_image = np.array(result_image).astype(np.float32) / 255.0
result_image = torch.from_numpy(result_image)[None,]
return (result_image,)
else:
raise Exception(f"Error: API request failed with status code {response.status_code}")
except Exception as e:
raise Exception(f"{e}")
+74
View File
@@ -0,0 +1,74 @@
import numpy as np
import requests
from PIL import Image
import io
import base64
from torchvision.transforms import ToPILImage, ToTensor
import torch
from .base_node import BriaAPINode
# shot by image Node
class ShotByImageNode(BriaAPINode):
@staticmethod
def INPUT_TYPES():
return {
"required": {
"image": ("IMAGE",), # Input image from another node
"ref_image": ("IMAGE",), # ref image from another node
"enhance_ref_image": ("INT", {"default": 1}),
"api_key": ("STRING", {"default": "BRIA_API_TOKEN"}) # API Key input with a default value
}
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("output_image",)
CATEGORY = "API Nodes"
FUNCTION = "execute" # This is the method that will be executed
def __init__(self):
super().__init__("https://engine.prod.bria-api.com/v1/product/lifestyle_shot_by_image") # Eraser API URL
# Define the execute method as expected by ComfyUI
def execute(self, image, ref_image, api_key, enhance_ref_image, ):
if api_key.strip() == "" or api_key.strip() == "BRIA_API_TOKEN":
raise Exception("Please insert a valid API key.")
# Check if image and mask are tensors, if so, convert to NumPy arrays
if isinstance(image, torch.Tensor):
image = self.preprocess_image(image)
if isinstance(ref_image, torch.Tensor):
ref_image = self.preprocess_image(ref_image)
# Convert the image and mask directly to Base64 strings
image_base64 = self.image_to_base64(image)
ref_image_base64 = self.image_to_base64(ref_image)
enhance_ref_image = bool(enhance_ref_image)
payload = {
"file": image_base64,
"ref_image_file": ref_image_base64,
"enhance_ref_image": enhance_ref_image,
"placement_type": "original",
"original_quality": True,
"sync": True
}
headers = {
"Content-Type": "application/json",
"api_token": f"{api_key}"
}
try:
response = requests.post(self.api_url, json=payload, headers=headers)
# Check for successful response
if response.status_code == 200:
print('response is 200')
# Process the output image from API response
response_dict = response.json()
image_response = requests.get(response_dict['result'][0][0])
result_image = self.postprocess_image(image_response.content)
return (result_image,)
else:
raise Exception(f"Error: API request failed with status code {response.status_code}")
except Exception as e:
raise Exception(f"{e}")
+70
View File
@@ -0,0 +1,70 @@
import numpy as np
import requests
from PIL import Image
import io
import base64
from torchvision.transforms import ToPILImage, ToTensor
import torch
from .base_node import BriaAPINode
# shot by text Node
class ShotByTextNode(BriaAPINode):
@staticmethod
def INPUT_TYPES():
return {
"required": {
"image": ("IMAGE",), # Input image from another node
"scene_description": ("STRING",),
"optimize_description": ("INT", {"default": 1}),
"api_key": ("STRING", {"default": "BRIA_API_TOKEN"}) # API Key input with a default value
}
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("output_image",)
CATEGORY = "API Nodes"
FUNCTION = "execute" # This is the method that will be executed
def __init__(self):
super().__init__("https://engine.prod.bria-api.com/v1/product/lifestyle_shot_by_text") # Eraser API URL
# Define the execute method as expected by ComfyUI
def execute(self, image, api_key, scene_description, optimize_description, ):
if api_key.strip() == "" or api_key.strip() == "BRIA_API_TOKEN":
raise Exception("Please insert a valid API key.")
# Check if image and mask are tensors, if so, convert to NumPy arrays
if isinstance(image, torch.Tensor):
image = self.preprocess_image(image)
optimize_description = bool(optimize_description)
image_base64 = self.image_to_base64(image)
payload = {
"file": image_base64,
"scene_description": scene_description,
"optimize_description": optimize_description,
"placement_type": "original",
"original_quality": True,
"sync": True
}
headers = {
"Content-Type": "application/json",
"api_token": f"{api_key}"
}
try:
response = requests.post(self.api_url, json=payload, headers=headers)
# Check for successful response
if response.status_code == 200:
print('response is 200')
# Process the output image from API response
response_dict = response.json()
image_response = requests.get(response_dict['result'][0][0])
result_image = self.postprocess_image(image_response.content)
return (result_image,)
else:
raise Exception(f"Error: API request failed with status code {response.status_code}")
except Exception as e:
raise Exception(f"{e}")
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui-bria-api"
description = "Custom nodes for ComfyUI using BRIA's API."
version = "1.0.0"
version = "1.0.2"
license = {file = "LICENSE"}
[project.urls]
@@ -0,0 +1,296 @@
{
"last_node_id": 42,
"last_link_id": 65,
"nodes": [
{
"id": 42,
"type": "LoadImage",
"pos": {
"0": 591,
"1": 593
},
"size": {
"0": 315,
"1": 314
},
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
64,
65
],
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"A_bottle_of_perfume.png",
"image"
]
},
{
"id": 39,
"type": "LoadImage",
"pos": {
"0": 600,
"1": 988
},
"size": {
"0": 315,
"1": 314
},
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
59
],
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"A_red_studio_with_a_shelf__close_up.png",
"image"
]
},
{
"id": 15,
"type": "Note",
"pos": {
"0": 995.4524536132812,
"1": 601.5353393554688
},
"size": {
"0": 306.28387451171875,
"1": 58
},
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {},
"widgets_values": [
"You can get your BRIA API token at:\nhttps://bria.ai/api/"
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 40,
"type": "PreviewImage",
"pos": {
"0": 1408,
"1": 623
},
"size": [
210,
246
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 62
}
],
"outputs": [],
"properties": {
"Node name for S&R": "PreviewImage"
}
},
{
"id": 41,
"type": "PreviewImage",
"pos": {
"0": 1408,
"1": 951
},
"size": [
210,
246
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 63
}
],
"outputs": [],
"properties": {
"Node name for S&R": "PreviewImage"
}
},
{
"id": 36,
"type": "ShotByTextNode",
"pos": {
"0": 996,
"1": 736
},
"size": {
"0": 315,
"1": 106
},
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": 64
}
],
"outputs": [
{
"name": "output_image",
"type": "IMAGE",
"links": [
62
],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "ShotByTextNode"
},
"widgets_values": [
"a beautiful sunset",
1,
""
]
},
{
"id": 37,
"type": "ShotByImageNode",
"pos": {
"0": 999,
"1": 932
},
"size": {
"0": 315,
"1": 102
},
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": 65
},
{
"name": "ref_image",
"type": "IMAGE",
"link": 59
}
],
"outputs": [
{
"name": "output_image",
"type": "IMAGE",
"links": [
63
],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "ShotByImageNode"
},
"widgets_values": [
0,
""
]
}
],
"links": [
[
59,
39,
0,
37,
1,
"IMAGE"
],
[
62,
36,
0,
40,
0,
"IMAGE"
],
[
63,
37,
0,
41,
0,
"IMAGE"
],
[
64,
42,
0,
36,
0,
"IMAGE"
],
[
65,
42,
0,
37,
0,
"IMAGE"
]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 0.9849732675807669,
"offset": [
-339.6686422794803,
-496.4354678014682
]
}
},
"version": 0.4
}
+204
View File
@@ -0,0 +1,204 @@
{
"last_node_id": 35,
"last_link_id": 55,
"nodes": [
{
"id": 33,
"type": "PreviewImage",
"pos": {
"0": 1420,
"1": 574
},
"size": {
"0": 433.29193115234375,
"1": 357.1255187988281
},
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 54
}
],
"outputs": [],
"properties": {
"Node name for S&R": "PreviewImage"
}
},
{
"id": 30,
"type": "LoadImage",
"pos": {
"0": 479,
"1": 572
},
"size": {
"0": 395.7845153808594,
"1": 352.8512268066406
},
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
53
],
"slot_index": 0,
"shape": 3
},
{
"name": "MASK",
"type": "MASK",
"links": [
55
],
"slot_index": 1,
"shape": 3
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"clipspace/clipspace-mask-1438488.400000006.png [input]",
"image"
]
},
{
"id": 14,
"type": "Note",
"pos": {
"0": 478,
"1": 444
},
"size": {
"0": 396.80859375,
"1": 61.8046875
},
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {},
"widgets_values": [
"Right click, and choose \"Open in Mask Editor\" to draw a mask of areas you want to erase."
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 15,
"type": "Note",
"pos": {
"0": 983,
"1": 440
},
"size": {
"0": 306.28387451171875,
"1": 58
},
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {},
"widgets_values": [
"You can get your BRIA API token at:\nhttps://bria.ai/api/"
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 34,
"type": "BriaGenFill",
"pos": {
"0": 992,
"1": 572
},
"size": {
"0": 315,
"1": 102
},
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": 53
},
{
"name": "mask",
"type": "MASK",
"link": 55
}
],
"outputs": [
{
"name": "output_image",
"type": "IMAGE",
"links": [
54
],
"shape": 3,
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "BriaGenFill"
},
"widgets_values": [
"a beautiful paint brush",
"BRIA_API_TOKEN"
]
}
],
"links": [
[
53,
30,
0,
34,
0,
"IMAGE"
],
[
54,
34,
0,
33,
0,
"IMAGE"
],
[
55,
30,
1,
34,
1,
"MASK"
]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 0.8264462809917364,
"offset": [
-266.96526103236687,
114.47857424738714
]
}
},
"version": 0.4
}