Delete CanvasToolLone directory

This commit is contained in:
taabata
2024-01-11 01:41:19 +03:00
committed by GitHub
parent d5a875dc55
commit 36a3a0a7bf
16 changed files with 0 additions and 3787 deletions
-25
View File
@@ -1,25 +0,0 @@
{
"savedata": {
"crpdimsref": {
"left": 0,
"top": 186,
"right": 512,
"bottom": 698
},
"crpdims": {
"left": 0,
"top": 540,
"right": 512,
"bottom": 698
},
"additionaldims": {
"left": 0,
"top": 0,
"right": 0,
"bottom": 354
},
"boxsz": "512",
"ff": "30",
"pxlsarray": ""
}
}
-49
View File
@@ -1,49 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ComfyUI</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="stylesheet" type="text/css" href="./lib/litegraph.css" />
<link rel="stylesheet" type="text/css" href="./style.css" />
<link rel="stylesheet" type="text/css" href="./user.css" />
<script type="text/javascript" src="./lib/litegraph.core.js"></script>
<script type="text/javascript" src="./lib/litegraph.extensions.js" defer></script>
<script type="module">
import { app } from "./scripts/app.js";
await app.setup();
window.app = app;
window.graph = app.graph;
</script>
<script type="module">
import { api } from "./scripts/api.js"
async function testrunscript(){
await api.fetchApi('/canvas', {
method: 'POST',
body: null
}).then(response => {}).catch(error => {
console.error('Error:', error);
});
}
async function testrunscript2(){
await api.fetchApi('/canvassame', {
method: 'POST',
body: null
}).then(response => {}).catch(error => {
console.error('Error:', error);
});
}
function welcome(){
alert("welcome");
}
document.getElementById("testbutton").addEventListener("click",testrunscript);
document.getElementById("testbutton2").addEventListener("click",testrunscript2);
</script>
</head>
<body class="litegraph"></body>
<div id="testbutton" style="position: absolute;top: 90%;left: 90%;width: 8%;height: 2.5%;background-color: rgb(43, 43, 43);cursor: pointer;border: 2px solid gray;border-radius: 5px;"><p style="width: 100%;height: 50%;font-family: Verdana, Geneva, Tahoma, sans-serif;transform: translate(0%,-100%);text-align: center;">Open Canvas</p></div>
<div id="testbutton2" style="position: absolute;top: 95%;left: 90%;width: 8%;height: 4%;background-color: rgb(43, 43, 43);cursor: pointer;border: 2px solid gray;border-radius: 5px;"><p style="width: 100%;height: 50%;font-family: Verdana, Geneva, Tahoma, sans-serif;transform: translate(0%,-70%);font-size: smaller;text-align: center;">Open Canvas (last image)</p></div>
</html>
-417
View File
@@ -1,417 +0,0 @@
from flask import Flask, render_template,jsonify,request, send_from_directory
from urllib import parse
from urllib import request as rq
import webbrowser
import os,base64,io, time, random
from PIL import Image, ImageFilter, ImageOps
try:
from signal import SIGKILL
except:
from signal import SIGABRT
import json
def stopprocess():
pid = os.getpid()
print(pid)
try:
os.kill(int(pid), SIGKILL)
except:
os.kill(int(pid), SIGABRT)
return "none"
import argparse
import numpy as np
parser = argparse.ArgumentParser()
parser.add_argument("-s","--same")
parser.add_argument("-p","--path")
args = parser.parse_args()
app = Flask(__name__)
data = {
"lastimage":"",
"done":"n"
}
json_object = json.dumps(data, indent=4)
with open("./lastimage.json", "w") as outfile:
outfile.write(json_object)
image = ""
if args.same == "yes":
with open("./lastimage.json","r") as filename:
image = Image.open(json.load(filename)["lastimage"])
w = str(int(float(image.size[0])))
h = str(int(float(image.size[1])))
try:
with open("./data.json","r") as filename:
bs = str(json.load(filename)["savedata"]["boxsz"])
pixels = json.load(filename)["savedata"]["pxlsarray"]
if pixels != "":
for i in range(0,len(pixels)):
for j in range(0,len(pixels[i])):
pixels[i][j] = tuple(pixels[i][j])
array = np.array(pixels, dtype=np.uint8)
image = Image.fromarray(array)
new_image.save('erased.png')
except:
pass
bs = "256"
if args.same == "yes":
buf = io.BytesIO()
image.save(buf, format='PNG')
byte_im = buf.getvalue()
byte_im = base64.b64encode(byte_im).decode('utf-8')
byte_im = f"data:image/png;base64,{byte_im}"
@app.route("/")
def index():
if args.same == "yes":
return render_template('index.html',byte_im=byte_im,w=w,h=h,bs=bs)
else:
return render_template('index.html',byte_im="",w="",h="",bs=bs)
@app.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(app.root_path, 'static'),
'favicon.ico', mimetype='image/vnd.microsoft.icon')
@app.route("/grabwfsmodels",methods=['GET', 'POST','DELETE'])
def grabwfsmodels():
models = [i for i in os.listdir('../../../models/diffusers') if os.path.isdir(f"../../../models/diffusers/{i}")]
wfs = os.listdir('./workflows')
return{"models":models,"wfs":wfs}
@app.route("/prepare",methods=['GET', 'POST','DELETE'])
def prep():
return{"exist":args.same}
@app.route("/generate",methods=['GET', 'POST','DELETE'])
def generate():
wf = request.json["wf"]
model = request.json["model"]
def queue_prompt(prompt_workflow):
p = {"prompt": prompt_workflow}
data = json.dumps(p).encode('utf-8')
req = rq.Request("http://127.0.0.1:8188/prompt", data=data)
rq.urlopen(req)
prompt_workflow = json.load(open(f'./workflows/{wf}'))
for i in prompt_workflow:
if "seed" in prompt_workflow[i]['inputs']:
print(i)
prompt_workflow[i]['inputs']['seed'] = random.randint(0,10000000000)
if "model_name" in prompt_workflow[i]['inputs']:
print(i)
prompt_workflow[i]['inputs']['model_name'] = model
queue_prompt(prompt_workflow)
return{}
@app.route("/savedata",methods=['GET', 'POST','DELETE'])
def savedata():
global image
print("trigerred")
taesd = request.json["taesd"]
savedata = request.json["savedata"]
if taesd == "false":
#print(savedata)
ff = int(savedata["ff"])
selectorsize = request.json["selectorsize"]
pixels = savedata["pxlsarray"]
if pixels != "":
for i in range(0,len(pixels)):
for j in range(0,len(pixels[i])):
pixels[i][j] = tuple(pixels[i][j])
array = np.array(pixels, dtype=np.uint8)
image = Image.fromarray(array)
image.save('erased.png')
image.save("out.png")
left = int(float(savedata["crpdims"]["left"]))
top = int(float(savedata["crpdims"]["top"]))
right = int(float(savedata["crpdims"]["right"]))
bottom = int(float(savedata["crpdims"]["bottom"]))
croped = image.crop((left,top,right,bottom))
try:
left = int(float(savedata["crpdimsref"]["left"]))
top = int(float(savedata["crpdimsref"]["top"]))
right = int(float(savedata["crpdimsref"]["right"]))
bottom = int(float(savedata["crpdimsref"]["bottom"]))
ref = image.crop((left,top,right,bottom))
except:
ref = image
ref.save("reference.png")
croped2 = croped.copy()
px = croped2.load()
for i in range(0,croped2.size[0]):
for j in range(0,croped2.size[1]):
try:
if px[i,j][3] <255:
px[i,j] = (255,255,255,255)
else:
px[i,j] = (0,0,0,255)
except:
px[i,j] = (0,0,0)
selectorsize = int(selectorsize)
bg = Image.new("RGB",(selectorsize,selectorsize),(0,0,0))
bg2 = Image.new("RGB",(selectorsize,selectorsize),(255,255,255))
add = (int(float(savedata["additionaldims"]["left"])),int(float(savedata["additionaldims"]["top"])),int(float(selectorsize-savedata["additionaldims"]["right"])),int(float(selectorsize-savedata["additionaldims"]["bottom"])))
bg.paste(croped,(add))
bg2.paste(croped2,(add))
###########################
toparr = []
leftarr = []
rightarr = []
bottomarr = []
topleftarr = []
toprightarr = []
bottomleftarr = []
bottomrightarr = []
whitepix = 0
px = bg2.load()
for i in range(0,bg2.size[0]):
for j in range(0,bg2.size[1]):
if px[i,j][0] == 255:
whitepix+=1
try:
if px[i,j][0] == 255 and 0<i<bg.size[0]-1 and 0<j<bg.size[1]-1:
if px[i,j+1][0] <255:
rightarr.append([i,j])
if px[i,j-1][0] <255:
leftarr.append([i,j])
if px[i+1,j][0] <255:
bottomarr.append([i,j])
if px[i-1,j][0] <255:
toparr.append([i,j])
if px[i-1,j-1][0] <255:
topleftarr.append([i,j])
if px[i-1,j+1][0] <255:
toprightarr.append([i,j])
if px[i+1,j+1][0] <255:
bottomrightarr.append([i,j])
if px[i+1,j-1][0] <255:
bottomleftarr.append([i,j])
except:
continue
for i in range(0,len(toparr)):
for k in range(0,ff):
try:
px[toparr[i][0]-k,toparr[i][1]] = (255,255,255)
except:
continue
for i in range(0,len(leftarr)):
for k in range(0,ff):
try:
px[leftarr[i][0],leftarr[i][1]-k] = (255,255,255)
except:
continue
for i in range(0,len(rightarr)):
for k in range(0,ff):
try:
px[rightarr[i][0],rightarr[i][1]+k] = (255,255,255)
except:
continue
for i in range(0,len(bottomarr)):
for k in range(0,ff):
try:
px[bottomarr[i][0]+k,bottomarr[i][1]] = (255,255,255)
except:
continue
for i in range(0,len(topleftarr)):
for k in range(0,ff):
try:
px[topleftarr[i][0]-k,topleftarr[i][1]-k] = (255,255,255)
except:
continue
for i in range(0,len(toprightarr)):
for k in range(0,ff):
try:
px[toprightarr[i][0]-k,toprightarr[i][1]+k] = (255,255,255)
except:
continue
for i in range(0,len(bottomleftarr)):
for k in range(0,ff):
try:
px[bottomleftarr[i][0]+k,bottomleftarr[i][1]-k] = (255,255,255)
except:
continue
for i in range(0,len(bottomrightarr)):
for k in range(0,ff):
try:
px[bottomrightarr[i][0]+k,bottomrightarr[i][1]+k] = (255,255,255)
except:
continue
#########################3
croped.save("cropped.png")
bg.save("image.png")
if whitepix == 0:
border = Image.new("RGB",(bg2.size[0],bg2.size[1]),(0,0,0))
bg2 = ImageOps.invert(bg2)
bg2 = bg2.resize((bg2.size[0]-ff*2,bg2.size[1]-ff*2))
border.paste(bg2,(ff,ff))
bg2 = border
bg2 = bg2.filter(ImageFilter.BoxBlur(ff-int(ff/2)))
bg2.save("mask.png")
width = int(float(savedata["additionaldims"]["left"])) + int(float(savedata["additionaldims"]["right"]))
height = int(float(savedata["additionaldims"]["top"])) + int(float(savedata["additionaldims"]["bottom"]))
data = {
"savedata":savedata
}
json_object = json.dumps(data, indent=4)
with open("data.json", "w") as outfile:
outfile.write(json_object)
#stopprocess()
taesds = "no"
flag = False
realflag = flag
with open("./lastimage.json","r") as filename:
status = json.load(filename)["done"]
if status == "y":
flag = True
print("done!!!")
else:
print("reading....")
if flag:
with open("./lastimage.json","r") as filename:
image = Image.open(json.load(filename)["lastimage"])
data = {
"lastimage":"",
"done":"n"
}
json_object = json.dumps(data, indent=4)
with open("./lastimage.json", "w") as outfile:
outfile.write(json_object)
try:
os.remove("./taesd.png")
except:
pass
taesds = "no"
realflag = flag
flag = False
else:
try:
image = Image.open("./taesd.png")
with open("data.json","r") as json_file:
savedata = json.load(json_file)["savedata"]
bg = Image.open("out.png").convert("RGBA")
msksmall = Image.open("mask.png").convert("L")
cropped = Image.open("image.png").convert("RGBA")
width = int(savedata["additionaldims"]["right"]) + int(savedata["additionaldims"]["left"]) + bg.size[0]
height = int(savedata["additionaldims"]["top"]) + int(savedata["additionaldims"]["bottom"]) + bg.size[1]
new = Image.new("RGBA",(width,height),(0,0,0,0))
lft = 0
tp = 0
image = Image.composite(image, cropped, msksmall)
if savedata["additionaldims"]["left"]>0:
lft = int(savedata["additionaldims"]["left"])
if savedata["additionaldims"]["top"]>0:
tp = int(savedata["additionaldims"]["top"])
new.paste(bg,(lft,tp))
lft = int(savedata["crpdims"]["left"])
tp = int(savedata["crpdims"]["top"])
new.paste(image,(lft,tp))
image = new
taesds = "no"
except:
image = Image.open("out.png")
taesds = "yes"
try:
width = image.size[0]
height = image.size[1]
buf = io.BytesIO()
image.save(buf, format='PNG')
byte_im = buf.getvalue()
byte_im = base64.b64encode(byte_im).decode('utf-8')
byte_im = f"data:image/png;base64,{byte_im}"
except:
byte_im = ""
width = ""
height = ""
#time.sleep(0.1)
return {"img":byte_im,"width":width,"height":height,"data":savedata,"flag":str(realflag),"taesd":taesds}
@app.route("/refresh",methods=['GET', 'POST','DELETE'])
def refresh():
flag = False
with open("./lastimage.json","r") as filename:
status = json.load(filename)["done"]
if status == "y":
flag = True
print("done!!!")
else:
print("reading....")
if flag:
with open("./lastimage.json","r") as filename:
image = Image.open(json.load(filename)["lastimage"])
data = {
"lastimage":"",
"done":"n"
}
json_object = json.dumps(data, indent=4)
with open("./lastimage.json", "w") as outfile:
outfile.write(json_object)
try:
os.remove("./taesd.png")
except:
pass
else:
try:
image = Image.open("./taesd.png")
except:
image = ""
try:
width = image.size[0]
height = image.size[1]
buf = io.BytesIO()
image.save(buf, format='PNG')
byte_im = buf.getvalue()
byte_im = base64.b64encode(byte_im).decode('utf-8')
byte_im = f"data:image/png;base64,{byte_im}"
except:
byte_im = ""
width = ""
height = ""
time.sleep(0.1)
return {"img":byte_im,"width":width,"height":height,"data":savedata,"flag":str(flag)}
if __name__ == "__main__":
webbrowser.open("http://localhost:5000")
app.run(debug=False)
-4
View File
@@ -1,4 +0,0 @@
{
"lastimage": "",
"done": "n"
}
-653
View File
@@ -1,653 +0,0 @@
import os
import sys
import asyncio
import traceback
import nodes
import folder_paths
import execution
import uuid
import urllib
import json
import glob
import struct
from PIL import Image, ImageOps
from PIL.PngImagePlugin import PngInfo
from io import BytesIO
try:
import aiohttp
from aiohttp import web
except ImportError:
print("Module 'aiohttp' not installed. Please install it via:")
print("pip install aiohttp")
print("or")
print("pip install -r requirements.txt")
sys.exit()
import mimetypes
from comfy.cli_args import args
import comfy.utils
import comfy.model_management
import subprocess
class BinaryEventTypes:
PREVIEW_IMAGE = 1
UNENCODED_PREVIEW_IMAGE = 2
async def send_socket_catch_exception(function, message):
try:
await function(message)
except (aiohttp.ClientError, aiohttp.ClientPayloadError, ConnectionResetError) as err:
print("send error:", err)
@web.middleware
async def cache_control(request: web.Request, handler):
response: web.Response = await handler(request)
if request.path.endswith('.js') or request.path.endswith('.css'):
response.headers.setdefault('Cache-Control', 'no-cache')
return response
def create_cors_middleware(allowed_origin: str):
@web.middleware
async def cors_middleware(request: web.Request, handler):
if request.method == "OPTIONS":
# Pre-flight request. Reply successfully:
response = web.Response()
else:
response = await handler(request)
response.headers['Access-Control-Allow-Origin'] = allowed_origin
response.headers['Access-Control-Allow-Methods'] = 'POST, GET, DELETE, PUT, OPTIONS'
response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
response.headers['Access-Control-Allow-Credentials'] = 'true'
return response
return cors_middleware
class PromptServer():
def __init__(self, loop):
PromptServer.instance = self
mimetypes.init()
mimetypes.types_map['.js'] = 'application/javascript; charset=utf-8'
self.supports = ["custom_nodes_from_web"]
self.prompt_queue = None
self.loop = loop
self.messages = asyncio.Queue()
self.number = 0
middlewares = [cache_control]
if args.enable_cors_header:
middlewares.append(create_cors_middleware(args.enable_cors_header))
self.app = web.Application(client_max_size=104857600, middlewares=middlewares)
self.sockets = dict()
self.web_root = os.path.join(os.path.dirname(
os.path.realpath(__file__)), "web")
routes = web.RouteTableDef()
self.routes = routes
self.last_node_id = None
self.client_id = None
self.on_prompt_handlers = []
@routes.get('/ws')
async def websocket_handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
sid = request.rel_url.query.get('clientId', '')
if sid:
# Reusing existing session, remove old
self.sockets.pop(sid, None)
else:
sid = uuid.uuid4().hex
self.sockets[sid] = ws
try:
# Send initial state to the new client
await self.send("status", { "status": self.get_queue_info(), 'sid': sid }, sid)
# On reconnect if we are the currently executing client send the current node
if self.client_id == sid and self.last_node_id is not None:
await self.send("executing", { "node": self.last_node_id }, sid)
async for msg in ws:
if msg.type == aiohttp.WSMsgType.ERROR:
print('ws connection closed with exception %s' % ws.exception())
finally:
self.sockets.pop(sid, None)
return ws
@routes.get("/")
async def get_root(request):
return web.FileResponse(os.path.join(self.web_root, "index.html"))
@routes.post("/canvas")
async def get_canvas(request):
try:
subprocess.run(["python", "index.py","--same","no","--path",folder_paths.get_folder_paths("custom_nodes")[0]+'/LCM_Inpaint-Outpaint_Comfy/CanvasTool'], cwd=folder_paths.get_folder_paths("custom_nodes")[0]+'/LCM_Inpaint-Outpaint_Comfy/CanvasTool')
except:
subprocess.run(["python", "index.py","--same","no","--path",folder_paths.get_folder_paths("custom_nodes")[0]+'\LCM_Inpaint-Outpaint_Comfy\CanvasTool'], cwd=folder_paths.get_folder_paths("custom_nodes")[0]+'\LCM_Inpaint-Outpaint_Comfy\CanvasTool',shell=true)
return web.FileResponse(os.path.join(self.web_root, "index.html"))
@routes.post("/canvassame")
async def get_canvas_same(request):
try:
subprocess.run(["python", "index.py","--same","yes","--path",folder_paths.get_folder_paths("custom_nodes")[0]+'/LCM_Inpaint-Outpaint_Comfy/CanvasTool'], cwd=folder_paths.get_folder_paths("custom_nodes")[0]+'/LCM_Inpaint-Outpaint_Comfy/CanvasTool')
except:
subprocess.run(["python", "index.py","--same","yes","--path",folder_paths.get_folder_paths("custom_nodes")[0]+'\LCM_Inpaint-Outpaint_Comfy\CanvasTool'], cwd=folder_paths.get_folder_paths("custom_nodes")[0]+'\LCM_Inpaint-Outpaint_Comfy\CanvasTool',shell=true)
return web.FileResponse(os.path.join(self.web_root, "index.html"))
@routes.get("/embeddings")
def get_embeddings(self):
embeddings = folder_paths.get_filename_list("embeddings")
return web.json_response(list(map(lambda a: os.path.splitext(a)[0], embeddings)))
@routes.get("/extensions")
async def get_extensions(request):
files = glob.glob(os.path.join(
glob.escape(self.web_root), 'extensions/**/*.js'), recursive=True)
extensions = list(map(lambda f: "/" + os.path.relpath(f, self.web_root).replace("\\", "/"), files))
for name, dir in nodes.EXTENSION_WEB_DIRS.items():
files = glob.glob(os.path.join(glob.escape(dir), '**/*.js'), recursive=True)
extensions.extend(list(map(lambda f: "/extensions/" + urllib.parse.quote(
name) + "/" + os.path.relpath(f, dir).replace("\\", "/"), files)))
return web.json_response(extensions)
def get_dir_by_type(dir_type):
if dir_type is None:
dir_type = "input"
if dir_type == "input":
type_dir = folder_paths.get_input_directory()
elif dir_type == "temp":
type_dir = folder_paths.get_temp_directory()
elif dir_type == "output":
type_dir = folder_paths.get_output_directory()
return type_dir, dir_type
def image_upload(post, image_save_function=None):
image = post.get("image")
overwrite = post.get("overwrite")
image_upload_type = post.get("type")
upload_dir, image_upload_type = get_dir_by_type(image_upload_type)
if image and image.file:
filename = image.filename
if not filename:
return web.Response(status=400)
subfolder = post.get("subfolder", "")
full_output_folder = os.path.join(upload_dir, os.path.normpath(subfolder))
filepath = os.path.abspath(os.path.join(full_output_folder, filename))
if os.path.commonpath((upload_dir, filepath)) != upload_dir:
return web.Response(status=400)
if not os.path.exists(full_output_folder):
os.makedirs(full_output_folder)
split = os.path.splitext(filename)
if overwrite is not None and (overwrite == "true" or overwrite == "1"):
pass
else:
i = 1
while os.path.exists(filepath):
filename = f"{split[0]} ({i}){split[1]}"
filepath = os.path.join(full_output_folder, filename)
i += 1
if image_save_function is not None:
image_save_function(image, post, filepath)
else:
with open(filepath, "wb") as f:
f.write(image.file.read())
return web.json_response({"name" : filename, "subfolder": subfolder, "type": image_upload_type})
else:
return web.Response(status=400)
@routes.post("/upload/image")
async def upload_image(request):
post = await request.post()
return image_upload(post)
@routes.post("/upload/mask")
async def upload_mask(request):
post = await request.post()
def image_save_function(image, post, filepath):
original_ref = json.loads(post.get("original_ref"))
filename, output_dir = folder_paths.annotated_filepath(original_ref['filename'])
# validation for security: prevent accessing arbitrary path
if filename[0] == '/' or '..' in filename:
return web.Response(status=400)
if output_dir is None:
type = original_ref.get("type", "output")
output_dir = folder_paths.get_directory_by_type(type)
if output_dir is None:
return web.Response(status=400)
if original_ref.get("subfolder", "") != "":
full_output_dir = os.path.join(output_dir, original_ref["subfolder"])
if os.path.commonpath((os.path.abspath(full_output_dir), output_dir)) != output_dir:
return web.Response(status=403)
output_dir = full_output_dir
file = os.path.join(output_dir, filename)
if os.path.isfile(file):
with Image.open(file) as original_pil:
metadata = PngInfo()
if hasattr(original_pil,'text'):
for key in original_pil.text:
metadata.add_text(key, original_pil.text[key])
original_pil = original_pil.convert('RGBA')
mask_pil = Image.open(image.file).convert('RGBA')
# alpha copy
new_alpha = mask_pil.getchannel('A')
original_pil.putalpha(new_alpha)
original_pil.save(filepath, compress_level=4, pnginfo=metadata)
return image_upload(post, image_save_function)
@routes.get("/view")
async def view_image(request):
if "filename" in request.rel_url.query:
filename = request.rel_url.query["filename"]
filename,output_dir = folder_paths.annotated_filepath(filename)
# validation for security: prevent accessing arbitrary path
if filename[0] == '/' or '..' in filename:
return web.Response(status=400)
if output_dir is None:
type = request.rel_url.query.get("type", "output")
output_dir = folder_paths.get_directory_by_type(type)
if output_dir is None:
return web.Response(status=400)
if "subfolder" in request.rel_url.query:
full_output_dir = os.path.join(output_dir, request.rel_url.query["subfolder"])
if os.path.commonpath((os.path.abspath(full_output_dir), output_dir)) != output_dir:
return web.Response(status=403)
output_dir = full_output_dir
filename = os.path.basename(filename)
file = os.path.join(output_dir, filename)
if os.path.isfile(file):
if 'preview' in request.rel_url.query:
with Image.open(file) as img:
preview_info = request.rel_url.query['preview'].split(';')
image_format = preview_info[0]
if image_format not in ['webp', 'jpeg'] or 'a' in request.rel_url.query.get('channel', ''):
image_format = 'webp'
quality = 90
if preview_info[-1].isdigit():
quality = int(preview_info[-1])
buffer = BytesIO()
if image_format in ['jpeg'] or request.rel_url.query.get('channel', '') == 'rgb':
img = img.convert("RGB")
img.save(buffer, format=image_format, quality=quality)
buffer.seek(0)
return web.Response(body=buffer.read(), content_type=f'image/{image_format}',
headers={"Content-Disposition": f"filename=\"{filename}\""})
if 'channel' not in request.rel_url.query:
channel = 'rgba'
else:
channel = request.rel_url.query["channel"]
if channel == 'rgb':
with Image.open(file) as img:
if img.mode == "RGBA":
r, g, b, a = img.split()
new_img = Image.merge('RGB', (r, g, b))
else:
new_img = img.convert("RGB")
buffer = BytesIO()
new_img.save(buffer, format='PNG')
buffer.seek(0)
return web.Response(body=buffer.read(), content_type='image/png',
headers={"Content-Disposition": f"filename=\"{filename}\""})
elif channel == 'a':
with Image.open(file) as img:
if img.mode == "RGBA":
_, _, _, a = img.split()
else:
a = Image.new('L', img.size, 255)
# alpha img
alpha_img = Image.new('RGBA', img.size)
alpha_img.putalpha(a)
alpha_buffer = BytesIO()
alpha_img.save(alpha_buffer, format='PNG')
alpha_buffer.seek(0)
return web.Response(body=alpha_buffer.read(), content_type='image/png',
headers={"Content-Disposition": f"filename=\"{filename}\""})
else:
return web.FileResponse(file, headers={"Content-Disposition": f"filename=\"{filename}\""})
return web.Response(status=404)
@routes.get("/view_metadata/{folder_name}")
async def view_metadata(request):
folder_name = request.match_info.get("folder_name", None)
if folder_name is None:
return web.Response(status=404)
if not "filename" in request.rel_url.query:
return web.Response(status=404)
filename = request.rel_url.query["filename"]
if not filename.endswith(".safetensors"):
return web.Response(status=404)
safetensors_path = folder_paths.get_full_path(folder_name, filename)
if safetensors_path is None:
return web.Response(status=404)
out = comfy.utils.safetensors_header(safetensors_path, max_size=1024*1024)
if out is None:
return web.Response(status=404)
dt = json.loads(out)
if not "__metadata__" in dt:
return web.Response(status=404)
return web.json_response(dt["__metadata__"])
@routes.get("/system_stats")
async def get_queue(request):
device = comfy.model_management.get_torch_device()
device_name = comfy.model_management.get_torch_device_name(device)
vram_total, torch_vram_total = comfy.model_management.get_total_memory(device, torch_total_too=True)
vram_free, torch_vram_free = comfy.model_management.get_free_memory(device, torch_free_too=True)
system_stats = {
"system": {
"os": os.name,
"python_version": sys.version,
"embedded_python": os.path.split(os.path.split(sys.executable)[0])[1] == "python_embeded"
},
"devices": [
{
"name": device_name,
"type": device.type,
"index": device.index,
"vram_total": vram_total,
"vram_free": vram_free,
"torch_vram_total": torch_vram_total,
"torch_vram_free": torch_vram_free,
}
]
}
return web.json_response(system_stats)
@routes.get("/prompt")
async def get_prompt(request):
return web.json_response(self.get_queue_info())
def node_info(node_class):
obj_class = nodes.NODE_CLASS_MAPPINGS[node_class]
info = {}
info['input'] = obj_class.INPUT_TYPES()
info['output'] = obj_class.RETURN_TYPES
info['output_is_list'] = obj_class.OUTPUT_IS_LIST if hasattr(obj_class, 'OUTPUT_IS_LIST') else [False] * len(obj_class.RETURN_TYPES)
info['output_name'] = obj_class.RETURN_NAMES if hasattr(obj_class, 'RETURN_NAMES') else info['output']
info['name'] = node_class
info['display_name'] = nodes.NODE_DISPLAY_NAME_MAPPINGS[node_class] if node_class in nodes.NODE_DISPLAY_NAME_MAPPINGS.keys() else node_class
info['description'] = obj_class.DESCRIPTION if hasattr(obj_class,'DESCRIPTION') else ''
info['category'] = 'sd'
if hasattr(obj_class, 'OUTPUT_NODE') and obj_class.OUTPUT_NODE == True:
info['output_node'] = True
else:
info['output_node'] = False
if hasattr(obj_class, 'CATEGORY'):
info['category'] = obj_class.CATEGORY
return info
@routes.get("/object_info")
async def get_object_info(request):
out = {}
for x in nodes.NODE_CLASS_MAPPINGS:
try:
out[x] = node_info(x)
except Exception as e:
print(f"[ERROR] An error occurred while retrieving information for the '{x}' node.", file=sys.stderr)
traceback.print_exc()
return web.json_response(out)
@routes.get("/object_info/{node_class}")
async def get_object_info_node(request):
node_class = request.match_info.get("node_class", None)
out = {}
if (node_class is not None) and (node_class in nodes.NODE_CLASS_MAPPINGS):
out[node_class] = node_info(node_class)
return web.json_response(out)
@routes.get("/history")
async def get_history(request):
return web.json_response(self.prompt_queue.get_history())
@routes.get("/history/{prompt_id}")
async def get_history(request):
prompt_id = request.match_info.get("prompt_id", None)
return web.json_response(self.prompt_queue.get_history(prompt_id=prompt_id))
@routes.get("/queue")
async def get_queue(request):
queue_info = {}
current_queue = self.prompt_queue.get_current_queue()
queue_info['queue_running'] = current_queue[0]
queue_info['queue_pending'] = current_queue[1]
return web.json_response(queue_info)
@routes.post("/prompt")
async def post_prompt(request):
print("got prompt")
resp_code = 200
out_string = ""
json_data = await request.json()
json_data = self.trigger_on_prompt(json_data)
if "number" in json_data:
number = float(json_data['number'])
else:
number = self.number
if "front" in json_data:
if json_data['front']:
number = -number
self.number += 1
if "prompt" in json_data:
prompt = json_data["prompt"]
valid = execution.validate_prompt(prompt)
extra_data = {}
if "extra_data" in json_data:
extra_data = json_data["extra_data"]
if "client_id" in json_data:
extra_data["client_id"] = json_data["client_id"]
if valid[0]:
prompt_id = str(uuid.uuid4())
outputs_to_execute = valid[2]
self.prompt_queue.put((number, prompt_id, prompt, extra_data, outputs_to_execute))
response = {"prompt_id": prompt_id, "number": number, "node_errors": valid[3]}
return web.json_response(response)
else:
print("invalid prompt:", valid[1])
return web.json_response({"error": valid[1], "node_errors": valid[3]}, status=400)
else:
return web.json_response({"error": "no prompt", "node_errors": []}, status=400)
@routes.post("/queue")
async def post_queue(request):
json_data = await request.json()
if "clear" in json_data:
if json_data["clear"]:
self.prompt_queue.wipe_queue()
if "delete" in json_data:
to_delete = json_data['delete']
for id_to_delete in to_delete:
delete_func = lambda a: a[1] == id_to_delete
self.prompt_queue.delete_queue_item(delete_func)
return web.Response(status=200)
@routes.post("/interrupt")
async def post_interrupt(request):
nodes.interrupt_processing()
return web.Response(status=200)
@routes.post("/history")
async def post_history(request):
json_data = await request.json()
if "clear" in json_data:
if json_data["clear"]:
self.prompt_queue.wipe_history()
if "delete" in json_data:
to_delete = json_data['delete']
for id_to_delete in to_delete:
self.prompt_queue.delete_history_item(id_to_delete)
return web.Response(status=200)
def add_routes(self):
self.app.add_routes(self.routes)
for name, dir in nodes.EXTENSION_WEB_DIRS.items():
self.app.add_routes([
web.static('/extensions/' + urllib.parse.quote(name), dir, follow_symlinks=True),
])
self.app.add_routes([
web.static('/', self.web_root, follow_symlinks=True),
])
def get_queue_info(self):
prompt_info = {}
exec_info = {}
exec_info['queue_remaining'] = self.prompt_queue.get_tasks_remaining()
prompt_info['exec_info'] = exec_info
return prompt_info
async def send(self, event, data, sid=None):
if event == BinaryEventTypes.UNENCODED_PREVIEW_IMAGE:
await self.send_image(data, sid=sid)
elif isinstance(data, (bytes, bytearray)):
await self.send_bytes(event, data, sid)
else:
await self.send_json(event, data, sid)
def encode_bytes(self, event, data):
if not isinstance(event, int):
raise RuntimeError(f"Binary event types must be integers, got {event}")
packed = struct.pack(">I", event)
message = bytearray(packed)
message.extend(data)
return message
async def send_image(self, image_data, sid=None):
image_type = image_data[0]
image = image_data[1]
max_size = image_data[2]
if max_size is not None:
if hasattr(Image, 'Resampling'):
resampling = Image.Resampling.BILINEAR
else:
resampling = Image.ANTIALIAS
image = ImageOps.contain(image, (max_size, max_size), resampling)
type_num = 1
if image_type == "JPEG":
type_num = 1
elif image_type == "PNG":
type_num = 2
bytesIO = BytesIO()
header = struct.pack(">I", type_num)
bytesIO.write(header)
image.save(bytesIO, format=image_type, quality=95, compress_level=4)
preview_bytes = bytesIO.getvalue()
await self.send_bytes(BinaryEventTypes.PREVIEW_IMAGE, preview_bytes, sid=sid)
async def send_bytes(self, event, data, sid=None):
message = self.encode_bytes(event, data)
if sid is None:
for ws in self.sockets.values():
await send_socket_catch_exception(ws.send_bytes, message)
elif sid in self.sockets:
await send_socket_catch_exception(self.sockets[sid].send_bytes, message)
async def send_json(self, event, data, sid=None):
message = {"type": event, "data": data}
if sid is None:
for ws in self.sockets.values():
await send_socket_catch_exception(ws.send_json, message)
elif sid in self.sockets:
await send_socket_catch_exception(self.sockets[sid].send_json, message)
def send_sync(self, event, data, sid=None):
self.loop.call_soon_threadsafe(
self.messages.put_nowait, (event, data, sid))
def queue_updated(self):
self.send_sync("status", { "status": self.get_queue_info() })
async def publish_loop(self):
while True:
msg = await self.messages.get()
await self.send(*msg)
async def start(self, address, port, verbose=True, call_on_start=None):
runner = web.AppRunner(self.app, access_log=None)
await runner.setup()
site = web.TCPSite(runner, address, port)
await site.start()
if address == '':
address = '0.0.0.0'
if verbose:
print("Starting server\n")
print("To see the GUI go to: http://{}:{}".format(address, port))
if call_on_start is not None:
call_on_start(address, port)
def add_on_prompt_handler(self, handler):
self.on_prompt_handlers.append(handler)
def trigger_on_prompt(self, json_data):
for handler in self.on_prompt_handlers:
try:
json_data = handler(json_data)
except Exception as e:
print(f"[ERROR] An error occurred during the on_prompt_handler processing")
traceback.print_exc()
return json_data
-4
View File
@@ -1,4 +0,0 @@
import shutil
shutil.copyfile('server.py', '../../../server.py')
shutil.copyfile('index.html', '../../../web/index.html')
Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 B

-409
View File
@@ -1,409 +0,0 @@
html{
background: linear-gradient(to top,rgb(29, 29, 29) 80%, rgb(5, 5, 5));
background-attachment: fixed;
background-repeat: no-repeat;
}
#settings,#settings2{
width: 100%;
height: 10%;
background: linear-gradient(to bottom,rgb(44, 44, 44) 80%, rgb(36, 36, 36),transparent);
position: absolute;
top: 0%;
left: 0%;
}
#moveimg{
position: absolute;
top: 30%;
left: 5%;
width: 10%;
height: 50%;
background-color: gray;
transform: translate(-50%,-50%);
font-weight: bolder;
font-family: Verdana, Geneva, Tahoma, sans-serif;
text-align: center;
cursor: pointer;
}
#setref,#undo{
position: absolute;
top: 65%;
left: 5%;
width: 10%;
height: 50%;
background-color: gray;
transform: translate(-50%,-50%);
font-weight: bolder;
font-family: Verdana, Geneva, Tahoma, sans-serif;
text-align: center;
cursor: pointer;
}
#undo{
left: 14%;
}
#resetimg{
position: absolute;
top: 50%;
left: 83%;
width: 10%;
height: 50%;
background-color: gray;
transform: translate(-50%,-50%);
font-weight: bolder;
font-family: Verdana, Geneva, Tahoma, sans-serif;
text-align: center;
cursor: pointer;
}
#eraseon{
position: absolute;
top: 30%;
left: 14%;
width: 10%;
height: 50%;
background-color: gray;
transform: translate(-50%,-50%);
font-weight: bolder;
font-family: Verdana, Geneva, Tahoma, sans-serif;
text-align: center;
cursor: pointer;
}
#drawon{
position: absolute;
top: 30%;
left: 23%;
width: 10%;
height: 50%;
background-color: gray;
transform: translate(-50%,-50%);
font-weight: bolder;
font-family: Verdana, Geneva, Tahoma, sans-serif;
text-align: center;
cursor: pointer;
}
#selectorsize{
position: absolute;
left: 39%;
top: 45%;
}
body{
color: white;
}
.txt{
width: 100%;
position: absolute;
top: 25%;
left: 50%;
transform: translate(-50%,-50%);
}
#container{
width: 100%;
height: 100%;
}
#saveexit{
position: absolute;
top: 50%;
left: 92%;
width: 10%;
height: 50%;
background-color: gray;
transform: translate(-50%,-50%);
font-weight: bolder;
font-family: Verdana, Geneva, Tahoma, sans-serif;
text-align: center;
visibility: hidden;
cursor: pointer;
}
#msg{
position: absolute;
width: 90%;
height: 90%;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
visibility: hidden;
font-size: 50px;
background-color: gray;
}
#saveexit:hover{
background-color: rgb(20, 20, 20);
}
#moveimg:hover{
background-color: rgb(20, 20, 20);
}
#eraseon:hover{
background-color: rgb(20, 20, 20);
}
#drawon:hover{
background-color: rgb(20, 20, 20);
}
input{
background-color: rgb(20, 20, 20);
border-radius: 5%;
outline: none;
caret-color: transparent;
color: white;
font-family: Verdana, Geneva, Tahoma, sans-serif;
border: 1px solid transparent;
text-align: center;
}
p{
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
#erasersize{
position: absolute;
left: 61%;
top: 45%;
}
#ff{
position: absolute;
left: 49%;
top: 45%;
}
#clr{
position: absolute;
left: 30%;
top: 40%;
}
#inprange{
position: absolute;
left: 30%;
top: 73%;
color: grey;
}
#source,#sourceunder{
position: fixed;
left: 0px;
top: 0px;
}
#selector{
width: 256px;
height: 256px;
background-color: transparent;
left: 0px;
top: 0px;
position: fixed;
border: 2px solid green;
transform: translate(-50%,-50%);
}
label{
position: fixed;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
}
#openimg{
position: fixed;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
opacity: 0;
}
label p{
width: 100%;
height: 100%;
position: absolute;
top: 50%;
transform: translateY(-15%);
font-size: 500%;
text-align: center;
}
#uploadcontainer{
width: 100%;
height: 100%;
position: fixed;
top: 0%;
opacity: 0;
background: linear-gradient(to bottom,black,rgb(20,20,20),black);
left: 0%;
}
#sourceimg{
display: none;
}
#lockbox{
position: absolute;
top: 61%;
left: 73.1%;
width: 10%;
height: 28%;
background-color: gray;
transform: translate(-50%,-50%);
font-weight: bolder;
font-family: Verdana, Geneva, Tahoma, sans-serif;
text-align: center;
cursor: pointer;
}
#lockbox p{
font-size: 15px;
top: 0%;
}
#lockbox:hover{
background-color: rgb(20, 20, 20);
}
#locktop, #lockleft, #lockright, #lockbottom{
position: absolute;
top: 40%;
width: 2.5%;
height: 30%;
background-color: gray;
transform: translate(-50%,-50%);
font-weight: bolder;
font-family: Verdana, Geneva, Tahoma, sans-serif;
text-align: center;
cursor: pointer;
font-size: 10px;
text-align: center;
}
#locktop{
left: 69.35%;
}
#lockleft{
left: 71.85%
}
#lockright{
left: 74.33%;
}
#lockbottom{
left: 76.8%;
}
#moveimg2{
position: absolute;
top: 50%;
left: 15%;
width: 10%;
height: 50%;
background-color: gray;
transform: translate(-50%,-50%);
font-weight: bolder;
font-family: Verdana, Geneva, Tahoma, sans-serif;
text-align: center;
cursor: pointer;
}
#moveimg2:hover{
background-color: rgb(20, 20, 20);
}
#openimgadd{
position: fixed;
top: 50%;
left: 90%;
}
#settings2{
visibility: hidden;
}
.moveimgclass,#done,#moveimg1{
position: absolute;
top: 50%;
width: 10%;
height: 50%;
background-color: gray;
transform: translate(-50%,-50%);
font-weight: bolder;
font-family: Verdana, Geneva, Tahoma, sans-serif;
text-align: center;
cursor: pointer;
z-index: 1;
}
.moveimgclass:hover{
background-color: rgb(20, 20, 20);
}
#done{
left: 95%;
}
#moveimg1{
left: 5%;
}
#uploadanotherimg,#openimgadd{
position: absolute;
width: 2%;
height: 40%;
top: 30%;
left: 65%;
}
#uploadanotherimg{
background-color: rgb(20, 20, 20);
}
#openimgadd{
opacity: 0;
}
.icontxt{
position: absolute;
top: -140%;
font-size: 50px;
}
.dropbtn {
background-color: transparent;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
text-align: center;
}
/* The container <div> - needed to position the dropdown content */
.dropdown {
position: relative;
display: inline-block;
transform: translate(-50%,-30%);
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
background-color: rgb(20,20,20);
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 3;
cursor: pointer;
}
/* Links inside the dropdown */
.dropdown-content a {
color: white;
padding: 12px 16px;
text-decoration: none;
display: block;
}
/* Change color of dropdown links on hover */
.dropdown-content a:hover {background-color: rgb(44, 44, 44)}
/* Show the dropdown menu on hover */
.dropdown:hover .dropdown-content {
display: block;
}
/* Change the background color of the dropdown button when the dropdown content is shown */
.dropdown:hover .dropbtn {
background-color: transparent;
}
#wfsdropdown{
left: 34%;
top: 5%;
}
#modelsdropdown{
left: 38%;
top: 5%;
}
File diff suppressed because it is too large Load Diff
-67
View File
@@ -1,67 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/static/index.css">
</head>
<body onwheel="changesize(event);" onmousemove="mousecoordinates(event);">
<script src="/static/index.js"></script>
<div id="container" onmouseenter="reset();" style="width: 100%;height: 100%;">
<div id="canvascontainer">
<img id="sourceimg" src={{byte_im}} width={{w}} height={{h}} style="visibility: hidden;" style="position: fixed;"/>
<canvas id="source" width={{w}} height={{h}} onclick="drawenable();" onmousemove="draw();" ></canvas>
</div>
<div id="moveimglistner" style="position: absolute; width: 100%;height: 100%;top: 0%;left: 0%;" onclick="moveimg(); " onmousemove="grabselector();"></div>
<div id="selector" onmousemove="selector();" onclick="snapshot();"></div>
<div id="settings">
<div id="setref" onclick="setreftoggle();"><p class="txt">Set Reference</p></div>
<div id="undo" onclick="undoimg();"><p class="txt">UNDO</p></div>
<div id="moveimg" onclick="moveimgenablefirst();"><p class="txt">Move Image</p></div>
<p id="label" style="position: absolute;top: 30%;left: 34%;">Box Size: </p>
<input type="text" id="selectorsize" onchange="changeselectorsize();" size="4">
<div id="saveexit" onclick="savejson()"><p class="txt">Generate</p></div>
<div id="eraseon" onclick="erasemodeon()"><p class="txt">Erase</p></div>
<div id="drawon" onclick="drawmodeon()"><p class="txt">Draw</p></div>
<p id="label2" style="position: absolute;top: 30%;left: 43%;">Fade Factor: </p>
<input id="ff" type="text" size="4" onchange="ffupdate();">
<p id="label3" style="position: absolute;top: 30%;left: 53%;">Eraser/Pencil Size: </p>
<input id="erasersize" type="text" size="4">
<input id="clr" type="color" size="3">
<input id="inprange" type="range" min="0" max="255" step="1">
<div id="lockbox" onclick="lockbox();"><p class="txt">Lock Box To Image</p></div>
<div id="lockleft" onclick="lockleft();"><p class="txt">Left</p></div>
<div id="lockright" onclick="lockright();"><p class="txt">Right</p></div>
<div id="lockbottom" onclick="lockbottom();"><p class="txt">Bottom</p></div>
<div id="locktop" onclick="locktop();"><p class="txt">Top</p></div>
<div id="resetimg" onclick="resetimg();"><p class="txt">Reset Image</p></div>
<label for="openimgadd" id="uploadanotherimg"><p class="icontxt">+</p></label>
<input id="openimgadd" type="file">
<div class="dropdown" id="wfsdropdown">
<button class="dropbtn" id="wfbutton">Select Workflow</button>
<div class="dropdown-content" id="wfscont">
</div>
</div>
<div class="dropdown" id="modelsdropdown">
<button class="dropbtn" id="modelbutton">Select Model</button>
<div class="dropdown-content" id="modelscont">
</div>
</div>
</div>
<div id="settings2">
<div id="moveimg1" onclick="moveimgenable();"><p class="txt">Move Image</p></div>
<div id="done" onclick="compimage();"><p class="txt">Done</p></div>
<label for="openimgadd" id="uploadanotherimg"><p class="icontxt">+</p></label>
</div>
<div id="uploadcontainer">
<label for="openimg" class="uploadstyle">
<p>Upload Image</p>
</label>
<input id="openimg" type="file">
</div>
</div>
<div id="msg"><p class="txt">Close the tab if not auto-closed</p></div>
</body>
</html>
@@ -1,146 +0,0 @@
{
"16": {
"inputs": {
"seed": 25670445128187
},
"class_type": "OutpaintCanvasTool"
},
"17": {
"inputs": {
"mode": "resize",
"supersample": "true",
"resampling": "bilinear",
"rescale_factor": 2,
"resize_width": [
"18",
0
],
"resize_height": [
"18",
1
],
"image": [
"16",
2
]
},
"class_type": "Image Resize"
},
"18": {
"inputs": {
"image": [
"16",
0
]
},
"class_type": "Get Image Size"
},
"19": {
"inputs": {
"images": [
"16",
0
]
},
"class_type": "PreviewImage"
},
"20": {
"inputs": {
"images": [
"16",
1
]
},
"class_type": "PreviewImage"
},
"21": {
"inputs": {
"images": [
"16",
2
]
},
"class_type": "PreviewImage"
},
"22": {
"inputs": {
"image": [
"23",
0
]
},
"class_type": "stitch"
},
"23": {
"inputs": {
"image": [
"28",
0
]
},
"class_type": "ImageOutputToComfyNodes"
},
"26": {
"inputs": {
"device": "GPU",
"tomesd_value": 0.6,
"ip_adapter": "enable",
"reference_only": "disable",
"ip_adapter_model": "ip-adapter_sd15.bin",
"model_name": "Juggernaut",
"controlnet_model": "cn_inpaint"
},
"class_type": "LCMLoraLoader_inpaint"
},
"28": {
"inputs": {
"seed": 834173561198935,
"text": "",
"steps": 4,
"width": [
"18",
0
],
"height": [
"18",
1
],
"cfg": 1.5,
"reference_style_fidelity": 0.1,
"batch": 1,
"strength": 0.45,
"prompt_weighting": "disable",
"controlnet_weight": 1,
"reference_only": "disable",
"ip_adapter": "enable",
"ipadapter_scale": 0.25,
"mask": [
"16",
1
],
"image": [
"16",
0
],
"reference_image": [
"17",
0
],
"pipe": [
"26",
0
]
},
"class_type": "LCMLora_inpaint"
},
"29": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"22",
0
]
},
"class_type": "SaveImage_Canvas"
}
}
@@ -1,146 +0,0 @@
{
"16": {
"inputs": {
"seed": 25670445128187
},
"class_type": "OutpaintCanvasTool"
},
"17": {
"inputs": {
"mode": "resize",
"supersample": "true",
"resampling": "bilinear",
"rescale_factor": 2,
"resize_width": [
"18",
0
],
"resize_height": [
"18",
1
],
"image": [
"16",
2
]
},
"class_type": "Image Resize"
},
"18": {
"inputs": {
"image": [
"16",
0
]
},
"class_type": "Get Image Size"
},
"19": {
"inputs": {
"images": [
"16",
0
]
},
"class_type": "PreviewImage"
},
"20": {
"inputs": {
"images": [
"16",
1
]
},
"class_type": "PreviewImage"
},
"21": {
"inputs": {
"images": [
"16",
2
]
},
"class_type": "PreviewImage"
},
"22": {
"inputs": {
"image": [
"23",
0
]
},
"class_type": "stitch"
},
"23": {
"inputs": {
"image": [
"28",
0
]
},
"class_type": "ImageOutputToComfyNodes"
},
"26": {
"inputs": {
"device": "GPU",
"tomesd_value": 0.6,
"ip_adapter": "disable",
"reference_only": "enable",
"ip_adapter_model": "ip-adapter_sd15.bin",
"model_name": "Juggernaut",
"controlnet_model": "cn_inpaint"
},
"class_type": "LCMLoraLoader_inpaint"
},
"28": {
"inputs": {
"seed": 834173561198935,
"text": "",
"steps": 8,
"width": [
"18",
0
],
"height": [
"18",
1
],
"cfg": 1.5,
"reference_style_fidelity": 0.3,
"batch": 1,
"strength": 0.45,
"prompt_weighting": "disable",
"controlnet_weight": 1,
"reference_only": "enable",
"ip_adapter": "disable",
"ipadapter_scale": 0.25,
"mask": [
"16",
1
],
"image": [
"16",
0
],
"reference_image": [
"17",
0
],
"pipe": [
"26",
0
]
},
"class_type": "LCMLora_inpaint"
},
"29": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"22",
0
]
},
"class_type": "SaveImage_Canvas"
}
}
@@ -1,146 +0,0 @@
{
"16": {
"inputs": {
"seed": 25670445128187
},
"class_type": "OutpaintCanvasTool"
},
"17": {
"inputs": {
"mode": "resize",
"supersample": "true",
"resampling": "bilinear",
"rescale_factor": 2,
"resize_width": [
"18",
0
],
"resize_height": [
"18",
1
],
"image": [
"16",
2
]
},
"class_type": "Image Resize"
},
"18": {
"inputs": {
"image": [
"16",
0
]
},
"class_type": "Get Image Size"
},
"19": {
"inputs": {
"images": [
"16",
0
]
},
"class_type": "PreviewImage"
},
"20": {
"inputs": {
"images": [
"16",
1
]
},
"class_type": "PreviewImage"
},
"21": {
"inputs": {
"images": [
"16",
2
]
},
"class_type": "PreviewImage"
},
"22": {
"inputs": {
"image": [
"23",
0
]
},
"class_type": "stitch"
},
"23": {
"inputs": {
"image": [
"28",
0
]
},
"class_type": "ImageOutputToComfyNodes"
},
"26": {
"inputs": {
"device": "GPU",
"tomesd_value": 0.6,
"ip_adapter": "enable",
"reference_only": "disable",
"ip_adapter_model": "ip-adapter_sd15.bin",
"model_name": "Juggernaut",
"controlnet_model": "cn_inpaint"
},
"class_type": "LCMLoraLoader_inpaint"
},
"28": {
"inputs": {
"seed": 834173561198935,
"text": "",
"steps": 4,
"width": [
"18",
0
],
"height": [
"18",
1
],
"cfg": 1.5,
"reference_style_fidelity": 0.1,
"batch": 1,
"strength": 1,
"prompt_weighting": "disable",
"controlnet_weight": 1,
"reference_only": "disable",
"ip_adapter": "enable",
"ipadapter_scale": 0.25,
"mask": [
"16",
1
],
"image": [
"16",
0
],
"reference_image": [
"17",
0
],
"pipe": [
"26",
0
]
},
"class_type": "LCMLora_inpaint"
},
"29": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"22",
0
]
},
"class_type": "SaveImage_Canvas"
}
}
@@ -1,146 +0,0 @@
{
"16": {
"inputs": {
"seed": 25670445128187
},
"class_type": "OutpaintCanvasTool"
},
"17": {
"inputs": {
"mode": "resize",
"supersample": "true",
"resampling": "bilinear",
"rescale_factor": 2,
"resize_width": [
"18",
0
],
"resize_height": [
"18",
1
],
"image": [
"16",
2
]
},
"class_type": "Image Resize"
},
"18": {
"inputs": {
"image": [
"16",
0
]
},
"class_type": "Get Image Size"
},
"19": {
"inputs": {
"images": [
"16",
0
]
},
"class_type": "PreviewImage"
},
"20": {
"inputs": {
"images": [
"16",
1
]
},
"class_type": "PreviewImage"
},
"21": {
"inputs": {
"images": [
"16",
2
]
},
"class_type": "PreviewImage"
},
"22": {
"inputs": {
"image": [
"23",
0
]
},
"class_type": "stitch"
},
"23": {
"inputs": {
"image": [
"28",
0
]
},
"class_type": "ImageOutputToComfyNodes"
},
"26": {
"inputs": {
"device": "GPU",
"tomesd_value": 0.6,
"ip_adapter": "enable",
"reference_only": "enable",
"ip_adapter_model": "ip-adapter_sd15.bin",
"model_name": "Juggernaut",
"controlnet_model": "cn_inpaint"
},
"class_type": "LCMLoraLoader_inpaint"
},
"28": {
"inputs": {
"seed": 834173561198935,
"text": "",
"steps": 4,
"width": [
"18",
0
],
"height": [
"18",
1
],
"cfg": 1.5,
"reference_style_fidelity": 0.1,
"batch": 1,
"strength": 1,
"prompt_weighting": "disable",
"controlnet_weight": 1,
"reference_only": "enable",
"ip_adapter": "enable",
"ipadapter_scale": 0.25,
"mask": [
"16",
1
],
"image": [
"16",
0
],
"reference_image": [
"17",
0
],
"pipe": [
"26",
0
]
},
"class_type": "LCMLora_inpaint"
},
"29": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"22",
0
]
},
"class_type": "SaveImage_Canvas"
}
}
-146
View File
@@ -1,146 +0,0 @@
{
"16": {
"inputs": {
"seed": 25670445128187
},
"class_type": "OutpaintCanvasTool"
},
"17": {
"inputs": {
"mode": "resize",
"supersample": "true",
"resampling": "bilinear",
"rescale_factor": 2,
"resize_width": [
"18",
0
],
"resize_height": [
"18",
1
],
"image": [
"16",
2
]
},
"class_type": "Image Resize"
},
"18": {
"inputs": {
"image": [
"16",
0
]
},
"class_type": "Get Image Size"
},
"19": {
"inputs": {
"images": [
"16",
0
]
},
"class_type": "PreviewImage"
},
"20": {
"inputs": {
"images": [
"16",
1
]
},
"class_type": "PreviewImage"
},
"21": {
"inputs": {
"images": [
"16",
2
]
},
"class_type": "PreviewImage"
},
"22": {
"inputs": {
"image": [
"23",
0
]
},
"class_type": "stitch"
},
"23": {
"inputs": {
"image": [
"28",
0
]
},
"class_type": "ImageOutputToComfyNodes"
},
"26": {
"inputs": {
"device": "GPU",
"tomesd_value": 0.6,
"ip_adapter": "disable",
"reference_only": "enable",
"ip_adapter_model": "ip-adapter_sd15.bin",
"model_name": "Juggernaut",
"controlnet_model": "cn_inpaint"
},
"class_type": "LCMLoraLoader_inpaint"
},
"28": {
"inputs": {
"seed": 834173561198935,
"text": "",
"steps": 4,
"width": [
"18",
0
],
"height": [
"18",
1
],
"cfg": 1.5,
"reference_style_fidelity": 0.1,
"batch": 1,
"strength": 1,
"prompt_weighting": "disable",
"controlnet_weight": 1,
"reference_only": "enable",
"ip_adapter": "disable",
"ipadapter_scale": 0.2,
"mask": [
"16",
1
],
"image": [
"16",
0
],
"reference_image": [
"17",
0
],
"pipe": [
"26",
0
]
},
"class_type": "LCMLora_inpaint"
},
"29": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"22",
0
]
},
"class_type": "SaveImage_Canvas"
}
}
-146
View File
@@ -1,146 +0,0 @@
{
"16": {
"inputs": {
"seed": 25670445128187
},
"class_type": "OutpaintCanvasTool"
},
"17": {
"inputs": {
"mode": "resize",
"supersample": "true",
"resampling": "bilinear",
"rescale_factor": 2,
"resize_width": [
"18",
0
],
"resize_height": [
"18",
1
],
"image": [
"16",
2
]
},
"class_type": "Image Resize"
},
"18": {
"inputs": {
"image": [
"16",
0
]
},
"class_type": "Get Image Size"
},
"19": {
"inputs": {
"images": [
"16",
0
]
},
"class_type": "PreviewImage"
},
"20": {
"inputs": {
"images": [
"16",
1
]
},
"class_type": "PreviewImage"
},
"21": {
"inputs": {
"images": [
"16",
2
]
},
"class_type": "PreviewImage"
},
"22": {
"inputs": {
"image": [
"23",
0
]
},
"class_type": "stitch"
},
"23": {
"inputs": {
"image": [
"28",
0
]
},
"class_type": "ImageOutputToComfyNodes"
},
"26": {
"inputs": {
"device": "GPU",
"tomesd_value": 0.6,
"ip_adapter": "disable",
"reference_only": "enable",
"ip_adapter_model": "ip-adapter_sd15.bin",
"model_name": "Juggernaut",
"controlnet_model": "cn_inpaint"
},
"class_type": "LCMLoraLoader_inpaint"
},
"28": {
"inputs": {
"seed": 834173561198935,
"text": "",
"steps": 4,
"width": [
"18",
0
],
"height": [
"18",
1
],
"cfg": 1.5,
"reference_style_fidelity": 0.1,
"batch": 1,
"strength": 1,
"prompt_weighting": "disable",
"controlnet_weight": 1,
"reference_only": "enable",
"ip_adapter": "disable",
"ipadapter_scale": 0.2,
"mask": [
"16",
1
],
"image": [
"16",
0
],
"reference_image": [
"17",
0
],
"pipe": [
"26",
0
]
},
"class_type": "LCMLora_inpaint"
},
"29": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"22",
0
]
},
"class_type": "SaveImage_Canvas"
}
}