feature: multi document

This commit is contained in:
zombieyang
2024-07-21 16:55:37 +08:00
parent 95395e14d0
commit bbb2541bca
11 changed files with 453 additions and 326 deletions
+23 -25
View File
@@ -65,33 +65,36 @@ def registerSDHTTPEndpoints(sdppp, app):
return {'name': name}
def registerSocketEvents(sdppp, sio):
# only emit by web instance
# only emit by sd webui instance
@sio.event
async def c_get_image(sid, data={}):
if not sdppp.has_ps_instance():
return
photoshopInstance = sdppp.get_ps_instance()
layer = data['layer_id']
document = data['document']
layer = data['layer']
use_layer_bounds = data['use_layer_bounds']
sd_elem_id = data['sd']['elem_id']
id = photoshopInstance.layer_name_to_id(layer)
bounds_id = photoshopInstance.layer_name_to_id(use_layer_bounds, id)
# id = photoshopInstance.layer_name_to_id(layer)
# bounds_id = photoshopInstance.layer_name_to_id(use_layer_bounds, id)
upload_name, opacity = await photoshopInstance.get_image(layer_id=id, bounds_id=bounds_id)
upload_name, opacity = await photoshopInstance.get_image(
document_identify=document, layer_identify=layer, bound_layer_identify=use_layer_bounds
)
res = consumeImageCache(upload_name)
addImageCache(res, sd_elem_id)
return {}
# only emit by web instance
# only emit by sd webui instance
@sio.event
async def c_send_image(sid, data={}):
if not sdppp.has_ps_instance():
return
photoshopInstance = sdppp.get_ps_instance()
document = data['document']
layer = data['layer']
layer_id = photoshopInstance.layer_name_to_id(layer)
image_urls = data['sd']['image_urls']
def load_image(image_url):
@@ -101,23 +104,7 @@ def registerSocketEvents(sdppp, sio):
raise Exception('Invalid image url')
return addImageCache(image_url)
image_ids = [load_image(image_url) for image_url in image_urls]
await photoshopInstance.send_images(layer_id=layer_id, image_ids=image_ids)
# only emit by web instance
@sio.event
async def c_get_layers(sid, data = {}):
if not sdppp.has_ps_instance():
return {}
instance = sdppp.get_ps_instance()
layer_strs = instance.get_base_layers()
bounds_strs = instance.get_bounds_layers()
set_layer_strs = instance.get_set_layers()
return {
'layer_strs': layer_strs,
'bound_strs': bounds_strs,
'set_layer_strs': set_layer_strs,
}
await photoshopInstance.send_images(document_identify=document, layer_identify=layer, image_ids=image_ids)
# only emit by photoshop instance
@sio.event
@@ -166,9 +153,20 @@ def registerSocketEvents(sdppp, sio):
@sio.event
async def c_progress(sid, data):
photoshop_sid = sdppp.get_ps_instance().sid
instance = sdppp.get_ps_instance()
if instance is None:
return
photoshop_sid = instance.sid
await sio.emit('c_progress', {
'progress': data['progress'],
'sid': sid
}, to=photoshop_sid)
@sio.event
async def c_get_documents(sid, data = {}):
instance = sdppp.get_ps_instance()
if instance is None:
return {}
photoshop_sid = instance.sid
return await sio.call('c_get_documents', data, to=photoshop_sid)
+29 -35
View File
@@ -39,37 +39,34 @@ def define_comfyui_nodes(sdppp):
class GetImageFromPhotoshopLayerNode:
@classmethod
def VALIDATE_INPUTS(s, layer):
def VALIDATE_INPUTS(s):
return validate_sdppp()
@classmethod
def IS_CHANGED(self, layer, use_layer_bounds):
def IS_CHANGED(self, layer_or_group, use_layer_bounds):
if not sdppp.has_ps_instance():
return np.random.rand()
else:
photoshopInstance = sdppp.get_ps_instance()
id = photoshopInstance.layer_name_to_id(layer)
bounds_id = photoshopInstance.layer_name_to_id(use_layer_bounds, id)
start = time.time()
is_changed, history_state_id = call_async_func_in_server_thread(photoshopInstance.check_layer_bounds_combo_changed(id, bounds_id))
print(1)
is_changed, history_state_id = call_async_func_in_server_thread(
photoshopInstance.check_layer_bounds_combo_changed(layer, use_layer_bounds)
)
print(2)
if is_changed and history_state_id is None:
return np.random.rand()
photoshopInstance.update_comfyui_last_value(id, bounds_id, history_state_id)
print(3)
photoshopInstance.update_comfyui_last_value(layer, use_layer_bounds, history_state_id)
return history_state_id
@classmethod
def INPUT_TYPES(cls):
if validate_sdppp() is not True:
layer_strs = []
bounds_strs = []
else:
layer_strs = sdppp.get_ps_instance().get_base_layers()
bounds_strs = sdppp.get_ps_instance().get_bounds_layers()
return {
"required": {
"layer": (layer_strs, {"default": layer_strs[0] if len(layer_strs) > 0 else None}),
"use_layer_bounds": (bounds_strs, {"default": bounds_strs[0] if len(bounds_strs) > 0 else None}),
"required": {},
"optional": {
"document": ([], {"default": None}),
"layer_or_group": ([], {"default": None}),
"use_layer_bounds": ([], {"default": None}),
}
}
@@ -78,16 +75,14 @@ def define_comfyui_nodes(sdppp):
FUNCTION = "get_image"
CATEGORY = "Photoshop"
def get_image(self, layer, use_layer_bounds):
def get_image(self, document, layer_or_group, use_layer_bounds):
if validate_sdppp() is not True:
raise ValueError('Photoshop is not connected')
photoshopInstance = sdppp.get_ps_instance()
id = photoshopInstance.layer_name_to_id(layer)
bounds_id = photoshopInstance.layer_name_to_id(use_layer_bounds, id)
start = time.time()
image_id, layer_opacity = call_async_func_in_server_thread(photoshopInstance.get_image(layer_id=id, bounds_id=bounds_id))
image_id, layer_opacity = call_async_func_in_server_thread(
photoshopInstance.get_image(document_identify=document, layer_identify=layer_or_group, bound_layer_identify=use_layer_bounds)
)
loadImage = LoadImage()
(output_image, output_mask) = loadImage.load_image(image_id)
@@ -96,20 +91,17 @@ def define_comfyui_nodes(sdppp):
class SendImageToPhotoshopLayerNode:
@classmethod
def VALIDATE_INPUTS(s, images):
def VALIDATE_INPUTS(s):
return validate_sdppp()
@classmethod
def INPUT_TYPES(cls):
if validate_sdppp() is not True:
layer_strs = []
else:
layer_strs = sdppp.get_ps_instance().get_set_layers()
return {
"required": {
"required": {},
"optional": {
"images": ("IMAGE", ),
"layer": (layer_strs, {"default": layer_strs[0] if len(layer_strs) > 0 else None}),
"document": ([], {"default": None}),
"layer_or_group": ([], {"default": None}),
}
}
@@ -118,7 +110,7 @@ def define_comfyui_nodes(sdppp):
CATEGORY = "Photoshop"
OUTPUT_NODE = True
def send_image(self, images, layer):
def send_image(self, images, document, layer_or_group):
if validate_sdppp() is not True:
raise ValueError('Photoshop is not connected')
photoshopInstance = sdppp.get_ps_instance()
@@ -128,8 +120,10 @@ def define_comfyui_nodes(sdppp):
i = 255. * image.cpu().numpy()
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
image_ids.append(addImageCache(img))
layer_id = photoshopInstance.layer_name_to_id(layer)
call_async_func_in_server_thread(photoshopInstance.send_images(image_ids=image_ids, layer_id=layer_id), True)
call_async_func_in_server_thread(photoshopInstance.send_images(
image_ids=image_ids, document_identify=document, layer_identify=layer_or_group
), True)
return (None,)
@@ -174,4 +168,4 @@ def define_comfyui_nodes(sdppp):
'SendImageToPhotoshopLayerNode': SendImageToPhotoshopLayerNode,
'ImageTimesOpacity': ImageTimesOpacity,
'MaskTimesOpacity': MaskTimesOpacity,
}
}
+13 -52
View File
@@ -1,74 +1,35 @@
import time
class PhotoshopInstance:
SPECIAL_LAYER_NEW_LAYER = '### New Layer ###'
SPECIAL_LAYER_USE_CANVAS = '### Use Canvas ###'
SPECIAL_LAYER_USE_SELECTION = '### Use Selection ###'
SPECIAL_LAYER_SAME_AS_LAYER = '### Same as Layer ###'
SPECIAL_LAYER_NAME_TO_ID = {
SPECIAL_LAYER_USE_CANVAS: 0,
SPECIAL_LAYER_USE_SELECTION: -1,
SPECIAL_LAYER_NEW_LAYER: -2,
SPECIAL_LAYER_SAME_AS_LAYER: -3
}
def __init__(self, sdppp, sid):
self.sdppp = sdppp
self.sid = sid
self.layers = []
self.reset_change_tracker()
def get_layers(self):
return list(map(lambda layer: f"{layer['name']} (id:{layer['id']})", self.layers))
def get_base_layers(self):
raw_layer_strs = self.get_layers()
layer_strs = list(raw_layer_strs)
layer_strs.insert(0, self.SPECIAL_LAYER_USE_CANVAS)
return layer_strs
def get_bounds_layers(self):
bounds_strs = list(self.get_layers())
bounds_strs.insert(0, self.SPECIAL_LAYER_USE_CANVAS)
bounds_strs.insert(1, self.SPECIAL_LAYER_USE_SELECTION)
bounds_strs.insert(1, self.SPECIAL_LAYER_SAME_AS_LAYER)
return bounds_strs
def get_set_layers(self):
raw_layer_strs = self.get_layers()
set_layer_strs = list(raw_layer_strs)
set_layer_strs.insert(0, self.SPECIAL_LAYER_NEW_LAYER)
return set_layer_strs
def layer_name_to_id(self, layer_name, refrence_id=None):
id = 0
if layer_name == self.SPECIAL_LAYER_SAME_AS_LAYER:
id = refrence_id
elif self.SPECIAL_LAYER_NAME_TO_ID.get(layer_name, None) is not None:
id = self.SPECIAL_LAYER_NAME_TO_ID[layer_name]
else:
layer_name_and_id_split = layer_name.split('(id:')
id = int(layer_name_and_id_split.pop().strip()[:-1])
return id
async def get_image(self, layer_id, bounds_id=False):
result = await self.sdppp.sio.call('get_image', data={'layer_id': layer_id, 'use_layer_bounds': bounds_id}, to=self.sid)
async def get_image(self, document_identify, layer_identify, bound_layer_identify):
result = await self.sdppp.sio.call('s_get_image', data={
'document_identify': document_identify, 'layer_identify': layer_identify, 'bound_layer_identify': bound_layer_identify
}, to=self.sid)
if not result:
return None, None
if 'error' in result:
raise Exception('sdppp PS side error:' + result['error'])
history_state_id = await self._update_layer_bounds_history_state_id(layer_id, bounds_id)
await self._update_history_state_id_after_internal_change(history_state_id)
# history_state_id = await self._update_layer_bounds_history_state_id(layer_id, bounds_id)
# await self._update_history_state_id_after_internal_change(history_state_id)
return result['upload_name'], result['layer_opacity']
async def send_images(self, image_ids, layer_id=""):
result = await self.sdppp.sio.call('send_images', data={'image_ids': image_ids, 'layer_id': layer_id}, to=self.sid)
await self._update_history_state_id_after_internal_change()
async def send_images(self, image_ids, document_identify, layer_identify):
result = await self.sdppp.sio.call('s_send_images', data={
'image_ids': image_ids, 'document_identify': document_identify, 'layer_identify': layer_identify
}, to=self.sid)
# await self._update_history_state_id_after_internal_change()
return result
async def get_active_history_state_id(self):
result = await self.sdppp.sio.call('get_active_history_state_id', data={}, to=self.sid)
result = await self.sdppp.sio.call('s_get_active_history_state_id', data={}, to=self.sid)
if result is None:
return 0
if 'error' in result:
@@ -118,4 +79,4 @@ class PhotoshopInstance:
layer_bounds_combo = f"{layer}{use_layer_bounds}"
latest_state_id = await self.get_active_history_state_id()
self.change_tracker[layer_bounds_combo] = latest_state_id
return latest_state_id
return latest_state_id
+1 -1
View File
@@ -44,7 +44,7 @@ class SDPPP:
elif qsobj['type'] == 'photoshop':
if len(self.photoshop_instances) > 0:
raise socketio.exceptions.ConnectionRefusedError('only 1 instance is allowed now')
raise socketio.exceptions.ConnectionRefusedError('only 1 instance is allowed now, or try to restart comfyUI')
self.photoshop_instances[sid] = PhotoshopInstance(self, sid)
elif qsobj['type'] == 'comfyui':