Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4e8ce0cfe | ||
|
|
ad8b29a75e | ||
|
|
264cb3eaba | ||
|
|
9bad06bc83 | ||
|
|
0e632a7b7b | ||
|
|
e277386ad5 | ||
|
|
c9f6b37874 | ||
|
|
11847c4a7c | ||
|
|
97fddde11f | ||
|
|
c14ca10510 | ||
|
|
59accb9b08 | ||
|
|
716be3778d | ||
|
|
f4d734a246 | ||
|
|
ca24f65792 | ||
|
|
c4dd20c870 | ||
|
|
eb72274c15 | ||
|
|
ee74488cb4 | ||
|
|
04645121a9 | ||
|
|
2ffeca1217 | ||
|
|
c70df9b2e5 | ||
|
|
140b8f3866 | ||
|
|
b5182dcff4 | ||
|
|
584dd5f8d4 | ||
|
|
f1d302d6e7 | ||
|
|
fadec607a8 | ||
|
|
a9f2c45d7f |
@@ -7,14 +7,19 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "pyproject.toml"
|
- "pyproject.toml"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish-node:
|
publish-node:
|
||||||
name: Publish Custom Node to registry
|
name: Publish Custom Node to registry
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.repository_owner == 'if-ai' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Publish Custom Node
|
- name: Publish Custom Node
|
||||||
uses: Comfy-Org/publish-node-action@main
|
uses: Comfy-Org/publish-node-action@v1
|
||||||
with:
|
with:
|
||||||
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }} ## Add your own personal access token to your Github Repository secrets and reference it here.
|
## Add your own personal access token to your Github Repository secrets and reference it here.
|
||||||
|
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
|
||||||
|
|||||||
+100
-72
@@ -377,16 +377,17 @@ class ImageManager:
|
|||||||
return sorted(files)
|
return sorted(files)
|
||||||
|
|
||||||
class IFLoadImagess:
|
class IFLoadImagess:
|
||||||
|
_color_channels = ["alpha", "red", "green", "blue"]
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.path_cache = {} # Cache for path mapping
|
self.path_cache = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
input_dir = folder_paths.get_input_directory()
|
input_dir = folder_paths.get_input_directory()
|
||||||
# Count available thumbnails
|
|
||||||
available_images = len([f for f in os.listdir(input_dir)
|
available_images = len([f for f in os.listdir(input_dir)
|
||||||
if f.startswith(ImageManager.THUMBNAIL_PREFIX)])
|
if f.startswith(ImageManager.THUMBNAIL_PREFIX)])
|
||||||
available_images = max(1, available_images) # Ensure at least 1
|
available_images = max(1, available_images)
|
||||||
|
|
||||||
files = [f for f in os.listdir(input_dir)
|
files = [f for f in os.listdir(input_dir)
|
||||||
if f.startswith(ImageManager.THUMBNAIL_PREFIX)]
|
if f.startswith(ImageManager.THUMBNAIL_PREFIX)]
|
||||||
@@ -396,7 +397,7 @@ class IFLoadImagess:
|
|||||||
"image": (sorted(files), {"image_upload": True}),
|
"image": (sorted(files), {"image_upload": True}),
|
||||||
"input_path": ("STRING", {"default": ""}),
|
"input_path": ("STRING", {"default": ""}),
|
||||||
"start_index": ("INT", {"default": 0, "min": 0, "max": 9999}),
|
"start_index": ("INT", {"default": 0, "min": 0, "max": 9999}),
|
||||||
"stop_index": ("INT", {"default": 10, "min": 1, "max": 9999}), # Changed to stop_index
|
"stop_index": ("INT", {"default": 10, "min": 1, "max": 9999}),
|
||||||
"load_limit": (["10", "100", "1000", "10000", "100000"], {"default": "1000"}),
|
"load_limit": (["10", "100", "1000", "10000", "100000"], {"default": "1000"}),
|
||||||
"image_selected": ("BOOLEAN", {"default": False}),
|
"image_selected": ("BOOLEAN", {"default": False}),
|
||||||
"available_image_count": ("INT", {
|
"available_image_count": ("INT", {
|
||||||
@@ -408,19 +409,21 @@ class IFLoadImagess:
|
|||||||
"include_subfolders": ("BOOLEAN", {"default": True}),
|
"include_subfolders": ("BOOLEAN", {"default": True}),
|
||||||
"sort_method": (["alphabetical", "numerical", "date_created", "date_modified"],),
|
"sort_method": (["alphabetical", "numerical", "date_created", "date_modified"],),
|
||||||
"filter_type": (["none", "png", "jpg", "jpeg", "webp", "gif", "bmp"],),
|
"filter_type": (["none", "png", "jpg", "jpeg", "webp", "gif", "bmp"],),
|
||||||
|
"channel": (s._color_channels, {"default": "alpha"}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("IMAGE", "MASK", "STRING", "STRING", "STRING", "INT")
|
RETURN_TYPES = ("IMAGE", "MASK", "STRING", "STRING", "STRING", "INT", "IMAGE", "MASK")
|
||||||
RETURN_NAMES = ("images", "masks", "image_paths", "filenames", "count_str", "count_int")
|
RETURN_NAMES = ("images", "masks", "image_paths", "filenames", "count_str", "count_int", "images_batch", "masks_batch")
|
||||||
OUTPUT_IS_LIST = (True, True, True, True, True, True)
|
OUTPUT_IS_LIST = (True, True, True, True, True, True, False, False)
|
||||||
FUNCTION = "load_images"
|
FUNCTION = "load_images"
|
||||||
CATEGORY = "ImpactFrames💥🎞️"
|
CATEGORY = "ImpactFrames💥🎞️/images"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def IS_CHANGED(cls, image, input_path="", start_index=0, max_images=1,
|
def IS_CHANGED(cls, image, input_path="", start_index=0, stop_index=0, max_images=1,
|
||||||
include_subfolders=True, sort_method="numerical",
|
include_subfolders=True, sort_method="numerical", image_selected=False,
|
||||||
filter_type="none", image_name="", unique_id=None):
|
filter_type="none", image_name="", unique_id=None, load_limit="1000",
|
||||||
|
available_image_count=0, channel="alpha" ):
|
||||||
"""
|
"""
|
||||||
Properly handle all input parameters and return NaN to force updates
|
Properly handle all input parameters and return NaN to force updates
|
||||||
This matches the input parameters from INPUT_TYPES
|
This matches the input parameters from INPUT_TYPES
|
||||||
@@ -442,20 +445,21 @@ class IFLoadImagess:
|
|||||||
return float("NaN")
|
return float("NaN")
|
||||||
|
|
||||||
def load_images(self, image="", input_path="", start_index=0, stop_index=10,
|
def load_images(self, image="", input_path="", start_index=0, stop_index=10,
|
||||||
load_limit="1000", image_selected=False, available_image_count=0,
|
load_limit="1000", image_selected=False, available_image_count=0,
|
||||||
include_subfolders=True, sort_method="numerical",
|
include_subfolders=True, sort_method="numerical",
|
||||||
filter_type="none", image_name="", unique_id=None):
|
filter_type="none", channel="alpha"):
|
||||||
try:
|
try:
|
||||||
# Process input path
|
# Process input path
|
||||||
abs_path = os.path.abspath(input_path if os.path.isabs(input_path)
|
abs_path = os.path.abspath(input_path if os.path.isabs(input_path)
|
||||||
else os.path.join(folder_paths.get_input_directory(), input_path))
|
else os.path.join(folder_paths.get_input_directory(), input_path))
|
||||||
|
|
||||||
# Get all valid images first
|
# Get all valid images
|
||||||
all_files = ImageManager.get_image_files(abs_path, include_subfolders, filter_type)
|
all_files = ImageManager.get_image_files(abs_path, include_subfolders, filter_type)
|
||||||
if not all_files:
|
if not all_files:
|
||||||
logger.warning(f"No valid images found in {abs_path}")
|
logger.warning(f"No valid images found in {abs_path}")
|
||||||
img_tensor, mask = self.load_placeholder()
|
img_tensor, mask = self.load_placeholder()
|
||||||
return ([img_tensor], [mask], [""], [""], ["0/0"], [0])
|
return ([img_tensor], [mask], [""], [""], ["0/0"], [0],
|
||||||
|
img_tensor.unsqueeze(0), mask.unsqueeze(0))
|
||||||
|
|
||||||
# Sort files
|
# Sort files
|
||||||
all_files = ImageManager.sort_files(all_files, sort_method)
|
all_files = ImageManager.sort_files(all_files, sort_method)
|
||||||
@@ -478,49 +482,80 @@ class IFLoadImagess:
|
|||||||
start_index = image_order[image]
|
start_index = image_order[image]
|
||||||
num_images = 1
|
num_images = 1
|
||||||
|
|
||||||
# Create path mapping
|
|
||||||
self.path_cache = {
|
|
||||||
thumb: orig for thumb, orig in zip(all_thumbnails, all_files[start_index:start_index + num_images])
|
|
||||||
}
|
|
||||||
|
|
||||||
# Process selected range
|
# Process selected range
|
||||||
selected_files = all_files[start_index:start_index + num_images]
|
selected_files = all_files[start_index:start_index + num_images]
|
||||||
selected_thumbnails = all_thumbnails[:num_images]
|
|
||||||
|
# Lists to store outputs
|
||||||
# Process selected files
|
|
||||||
images = []
|
images = []
|
||||||
masks = []
|
masks = []
|
||||||
paths = []
|
paths = []
|
||||||
filenames = []
|
filenames = []
|
||||||
count_strs = []
|
count_strs = []
|
||||||
count_ints = []
|
count_ints = []
|
||||||
|
|
||||||
for idx, (file_path, thumb_name) in enumerate(zip(selected_files, selected_thumbnails)):
|
# Track max dimensions for resizing
|
||||||
|
max_height = 0
|
||||||
|
max_width = 0
|
||||||
|
|
||||||
|
# First pass to determine max dimensions
|
||||||
|
for file_path in selected_files:
|
||||||
try:
|
try:
|
||||||
with Image.open(file_path) as img:
|
with Image.open(file_path) as img:
|
||||||
img = ImageOps.exif_transpose(img)
|
img = ImageOps.exif_transpose(img)
|
||||||
|
max_height = max(max_height, img.height)
|
||||||
|
max_width = max(max_width, img.width)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error checking dimensions of {file_path}: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Second pass to load and resize images
|
||||||
|
for idx, file_path in enumerate(selected_files):
|
||||||
|
try:
|
||||||
|
img = Image.open(file_path)
|
||||||
|
img = ImageOps.exif_transpose(img)
|
||||||
|
|
||||||
|
if img.mode == 'I':
|
||||||
|
img = img.point(lambda i: i * (1 / 255))
|
||||||
|
|
||||||
|
# Resize to match max dimensions
|
||||||
|
image = img.convert('RGB')
|
||||||
|
if image.size != (max_width, max_height):
|
||||||
|
image = image.resize((max_width, max_height), Image.Resampling.LANCZOS)
|
||||||
|
|
||||||
|
# Convert to numpy array and normalize
|
||||||
|
image_array = np.array(image).astype(np.float32) / 255.0
|
||||||
|
image_tensor = torch.from_numpy(image_array).unsqueeze(0) # [1, H, W, 3]
|
||||||
|
images.append(image_tensor)
|
||||||
|
|
||||||
|
# Handle mask based on selected channel
|
||||||
|
if img.mode not in ('RGB', 'L'):
|
||||||
|
img = img.convert('RGBA')
|
||||||
|
|
||||||
if img.mode == 'I':
|
c = channel[0].upper()
|
||||||
img = img.point(lambda i: i * (1 / 255))
|
if c in img.getbands():
|
||||||
image = img.convert('RGB')
|
mask = np.array(img.getchannel(c)).astype(np.float32) / 255.0
|
||||||
|
mask = torch.from_numpy(mask)
|
||||||
image_array = np.array(image).astype(np.float32) / 255.0
|
if c == 'A':
|
||||||
image_tensor = torch.from_numpy(image_array)[None,]
|
mask = 1. - mask
|
||||||
|
else:
|
||||||
if 'A' in img.getbands():
|
mask = torch.zeros((max_height, max_width),
|
||||||
mask = np.array(img.getchannel('A')).astype(np.float32) / 255.0
|
dtype=torch.float32, device="cpu")
|
||||||
mask = 1. - torch.from_numpy(mask)
|
|
||||||
else:
|
# Resize mask if needed
|
||||||
mask = torch.zeros((image_array.shape[0], image_array.shape[1]),
|
if mask.shape != (max_height, max_width):
|
||||||
dtype=torch.float32, device="cpu")
|
mask = torch.nn.functional.interpolate(
|
||||||
|
mask.unsqueeze(0).unsqueeze(0),
|
||||||
images.append(image_tensor)
|
size=(max_height, max_width),
|
||||||
masks.append(mask.unsqueeze(0))
|
mode='bilinear',
|
||||||
paths.append(file_path)
|
align_corners=False
|
||||||
filenames.append(os.path.basename(file_path))
|
).squeeze(0).squeeze(0)
|
||||||
count_str = f"{start_index + idx + 1}/{total_files}" # Update count to show global position
|
|
||||||
count_strs.append(count_str)
|
masks.append(mask.unsqueeze(0)) # Add batch dimension to mask [1, H, W]
|
||||||
count_ints.append(start_index + idx + 1)
|
|
||||||
|
paths.append(file_path)
|
||||||
|
filenames.append(os.path.basename(file_path))
|
||||||
|
count_strs.append(f"{start_index + idx + 1}/{total_files}")
|
||||||
|
count_ints.append(start_index + idx + 1)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error processing image {file_path}: {e}")
|
logger.error(f"Error processing image {file_path}: {e}")
|
||||||
@@ -528,36 +563,29 @@ class IFLoadImagess:
|
|||||||
|
|
||||||
if not images:
|
if not images:
|
||||||
img_tensor, mask = self.load_placeholder()
|
img_tensor, mask = self.load_placeholder()
|
||||||
return ([img_tensor], [mask], [""], [""], ["0/0"], [0])
|
return ([img_tensor], [mask], [""], [""], ["0/0"], [0],
|
||||||
|
img_tensor.unsqueeze(0), mask.unsqueeze(0))
|
||||||
|
|
||||||
ui_data = {
|
# Create batched version - now all images are the same size
|
||||||
"images": all_thumbnails,
|
images_batch = torch.cat(images, dim=0) # [B, H, W, 3]
|
||||||
"current_thumbnails": selected_thumbnails,
|
masks_batch = torch.cat(masks, dim=0) # [B, H, W]
|
||||||
"total_images": total_files,
|
|
||||||
"path_mapping": self.path_cache,
|
return (images, masks, paths, filenames, count_strs, count_ints,
|
||||||
"available_image_count": total_files,
|
images_batch, masks_batch)
|
||||||
"image_order": image_order,
|
|
||||||
"start_index": start_index,
|
|
||||||
"stop_index": start_index + num_images
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"ui": {"values": ui_data},
|
|
||||||
"result": (images, masks, paths, filenames, count_strs, count_ints)
|
|
||||||
}
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in load_images: {e}", exc_info=True)
|
logger.error(f"Error in load_images: {e}", exc_info=True)
|
||||||
img_tensor, mask = self.load_placeholder()
|
img_tensor, mask = self.load_placeholder()
|
||||||
return ([img_tensor], [mask], [""], [""], ["error"], [0])
|
return ([img_tensor], [mask], [""], [""], ["error"], [0],
|
||||||
|
img_tensor.unsqueeze(0), mask.unsqueeze(0))
|
||||||
|
|
||||||
def load_placeholder(self):
|
def load_placeholder(self):
|
||||||
"""Creates and returns a placeholder image tensor and mask"""
|
"""Creates and returns a placeholder image tensor and mask"""
|
||||||
img = Image.new('RGB', (512, 512), color=(73, 109, 137))
|
img = Image.new('RGB', (512, 512), color=(73, 109, 137))
|
||||||
image_array = np.array(img).astype(np.float32) / 255.0
|
image_array = np.array(img).astype(np.float32) / 255.0
|
||||||
image_tensor = torch.from_numpy(image_array)[None,]
|
image_tensor = torch.from_numpy(image_array) # [H, W, 3]
|
||||||
mask = torch.zeros((1, image_array.shape[0], image_array.shape[1]),
|
mask = torch.zeros((image_array.shape[0], image_array.shape[1]),
|
||||||
dtype=torch.float32, device="cpu")
|
dtype=torch.float32, device="cpu") # [H, W]
|
||||||
return image_tensor, mask
|
return image_tensor, mask
|
||||||
|
|
||||||
def process_single_image(self, image_path: str):
|
def process_single_image(self, image_path: str):
|
||||||
@@ -588,7 +616,7 @@ class IFLoadImagess:
|
|||||||
img_tensor, mask = self.load_placeholder()
|
img_tensor, mask = self.load_placeholder()
|
||||||
return ([img_tensor], [mask], [""], [""], ["error"], [0])
|
return ([img_tensor], [mask], [""], [""], ["error"], [0])
|
||||||
|
|
||||||
@PromptServer.instance.routes.post("/ifai/backup_input")
|
@PromptServer.instance.routes.post("/IF_img/backup_input")
|
||||||
async def backup_input_folder(request):
|
async def backup_input_folder(request):
|
||||||
try:
|
try:
|
||||||
success, message = ImageManager.backup_input_folder()
|
success, message = ImageManager.backup_input_folder()
|
||||||
@@ -603,7 +631,7 @@ async def backup_input_folder(request):
|
|||||||
"error": str(e)
|
"error": str(e)
|
||||||
}, status=500)
|
}, status=500)
|
||||||
|
|
||||||
@PromptServer.instance.routes.post("/ifai/restore_input")
|
@PromptServer.instance.routes.post("/IF_img/restore_input")
|
||||||
async def restore_input_folder(request):
|
async def restore_input_folder(request):
|
||||||
try:
|
try:
|
||||||
success, message = ImageManager.restore_input_folder()
|
success, message = ImageManager.restore_input_folder()
|
||||||
@@ -618,7 +646,7 @@ async def restore_input_folder(request):
|
|||||||
"error": str(e)
|
"error": str(e)
|
||||||
}, status=500)
|
}, status=500)
|
||||||
|
|
||||||
@PromptServer.instance.routes.post("/ifai/refresh_previews")
|
@PromptServer.instance.routes.post("/IF_img/refresh_previews")
|
||||||
async def refresh_previews(request):
|
async def refresh_previews(request):
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
@@ -691,7 +719,7 @@ async def refresh_previews(request):
|
|||||||
}, status=500)
|
}, status=500)
|
||||||
|
|
||||||
# Add route for widget refresh
|
# Add route for widget refresh
|
||||||
@PromptServer.instance.routes.post("/ifai/refresh_widgets")
|
@PromptServer.instance.routes.post("/IF_img/refresh_widgets")
|
||||||
async def refresh_widgets(request):
|
async def refresh_widgets(request):
|
||||||
try:
|
try:
|
||||||
input_dir = folder_paths.get_input_directory()
|
input_dir = folder_paths.get_input_directory()
|
||||||
@@ -716,4 +744,4 @@ NODE_CLASS_MAPPINGS = {
|
|||||||
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||||
"IF_LoadImagesS": "IF Load Images S 🖼️"
|
"IF_LoadImagesS": "IF Load Images S 🖼️"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
Here’s the revised README section with the video tutorial link added:
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# ComfyUI_IF_AI_LoadImages
|
# ComfyUI_IF_AI_LoadImages
|
||||||
|
|
||||||
This tool enables you to load images from arbitrary folder selections, display previews of the images within subfolders, and output a list of images so you can work with multiple images simultaneously.
|
This tool enables you to load images from arbitrary folder selections, display previews of the images within subfolders, and output a list of images so you can work with multiple images simultaneously.
|
||||||
@@ -14,16 +18,20 @@ This tool enables you to load images from arbitrary folder selections, display p
|
|||||||
8. To use a single selected image, switch the option to true and queue the node (execute the workflow).
|
8. To use a single selected image, switch the option to true and queue the node (execute the workflow).
|
||||||
|
|
||||||
> **Note:** This is a workaround solution, so it may feel a bit clunky but functions effectively.
|
> **Note:** This is a workaround solution, so it may feel a bit clunky but functions effectively.
|
||||||
>
|
|
||||||
|
[](https://www.youtube.com/watch?v=6ylkSoJ-Tnw)
|
||||||
|
*[Watch the video tutorial here](https://www.youtube.com/watch?v=6ylkSoJ-Tnw)*
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
- [x] Fix image extension filters
|
||||||
- [ ] Add a counter to enable loops.
|
- [ ] Fix Masks from mask editor
|
||||||
- [ ] Add support for video files.
|
- [ ] Fix single image upload
|
||||||
|
- [ ] Add a counter to enable loops
|
||||||
|
- [ ] Add support for video files
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
|
|||||||
+25
-25
@@ -1,25 +1,25 @@
|
|||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import folder_paths
|
import folder_paths
|
||||||
|
|
||||||
from .IFLoadImagesNodeS import IFLoadImagess
|
from .IFLoadImagesNodeS import IFLoadImagess
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
NODE_CLASS_MAPPINGS = {
|
||||||
"IF_LoadImagesS": IFLoadImagess,
|
"IF_LoadImagesS": IFLoadImagess,
|
||||||
}
|
}
|
||||||
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||||
"IF_LoadImagesS": "IF Load Images S 🖼️",
|
"IF_LoadImagesS": "IF Load Images S 🖼️",
|
||||||
}
|
}
|
||||||
|
|
||||||
WEB_DIRECTORY = "./web"
|
WEB_DIRECTORY = "./web"
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"NODE_CLASS_MAPPINGS",
|
"NODE_CLASS_MAPPINGS",
|
||||||
"NODE_DISPLAY_NAME_MAPPINGS",
|
"NODE_DISPLAY_NAME_MAPPINGS",
|
||||||
"WEB_DIRECTORY",
|
"WEB_DIRECTORY",
|
||||||
]
|
]
|
||||||
|
|||||||
+5
-5
@@ -1,9 +1,9 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "comfyui_if_ai_loadimages"
|
name = "comfyui_if_ai_loadimages"
|
||||||
description = "It Load Images with subfolders form arbitrary folders previous on node outputs lists- convinient selection via file browser"
|
description = "It Load Images with subfolders form arbitrary folders previous on node outputs lists- convinient selection via file browser"
|
||||||
version = "1.0.1"
|
version = "1.0.7"
|
||||||
license = { file = "LICENSE.txt" }
|
license = { file = "MIT License" }
|
||||||
dependencies = ["pillow"]
|
dependencies = ["pillow", "numpy"]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Repository = "https://github.com/if-ai/ComfyUI_IF_AI_LoadImages"
|
Repository = "https://github.com/if-ai/ComfyUI_IF_AI_LoadImages"
|
||||||
@@ -11,5 +11,5 @@ Repository = "https://github.com/if-ai/ComfyUI_IF_AI_LoadImages"
|
|||||||
|
|
||||||
[tool.comfy]
|
[tool.comfy]
|
||||||
PublisherId = "impactframes"
|
PublisherId = "impactframes"
|
||||||
DisplayName = "ComfyUI_IF_LoadImages"
|
DisplayName = "IF_LoadImages"
|
||||||
Icon = ""
|
Icon = "https://impactframes.ai/System/Icons/48x48/if.png"
|
||||||
|
|||||||
+2
-2
@@ -1,2 +1,2 @@
|
|||||||
|
pillow
|
||||||
|
numpy
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ app.registerExtension({
|
|||||||
const backupBtn = this.addWidget("button", "backup_input", "Backup Input 💾",
|
const backupBtn = this.addWidget("button", "backup_input", "Backup Input 💾",
|
||||||
async () => {
|
async () => {
|
||||||
try {
|
try {
|
||||||
const response = await api.fetchApi("/if_ai/backup_input", {
|
const response = await api.fetchApi("/IF_img/backup_input", {
|
||||||
method: "POST"
|
method: "POST"
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ app.registerExtension({
|
|||||||
const restoreBtn = this.addWidget("button", "restore_input", "Restore Input ♻️",
|
const restoreBtn = this.addWidget("button", "restore_input", "Restore Input ♻️",
|
||||||
async () => {
|
async () => {
|
||||||
try {
|
try {
|
||||||
const response = await api.fetchApi("/if_ai/restore_input", {
|
const response = await api.fetchApi("/IF_img/restore_input", {
|
||||||
method: "POST"
|
method: "POST"
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ app.registerExtension({
|
|||||||
load_limit: parseInt(this.widgets.find(w => w.name === "load_limit")?.value || "1000")
|
load_limit: parseInt(this.widgets.find(w => w.name === "load_limit")?.value || "1000")
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await api.fetchApi("/if_ai/refresh_previews", {
|
const response = await api.fetchApi("/IF_img/refresh_previews", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify(options)
|
body: JSON.stringify(options)
|
||||||
@@ -342,7 +342,7 @@ app.registerExtension({
|
|||||||
nodeType.prototype.backupInputFolder = async function() {
|
nodeType.prototype.backupInputFolder = async function() {
|
||||||
try {
|
try {
|
||||||
this.showLoader();
|
this.showLoader();
|
||||||
const response = await fetch("/if_ai/backup_input", {
|
const response = await fetch("/IF_img/backup_input", {
|
||||||
method: "POST"
|
method: "POST"
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -365,7 +365,7 @@ app.registerExtension({
|
|||||||
nodeType.prototype.restoreInputFolder = async function() {
|
nodeType.prototype.restoreInputFolder = async function() {
|
||||||
try {
|
try {
|
||||||
this.showLoader();
|
this.showLoader();
|
||||||
const response = await fetch("/if_ai/restore_input", {
|
const response = await fetch("/IF_img/restore_input", {
|
||||||
method: "POST"
|
method: "POST"
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -400,7 +400,7 @@ app.registerExtension({
|
|||||||
|
|
||||||
this.showLoader();
|
this.showLoader();
|
||||||
|
|
||||||
const response = await fetch("/if_ai/refresh_previews", {
|
const response = await fetch("/IF_img/refresh_previews", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
|
|||||||
Reference in New Issue
Block a user