Initial release: Skycoder Tools v1.0.0
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Skycoder
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,36 @@
|
||||
# 🛠️ ComfyUI Skycoder Tools
|
||||
|
||||
[](https://github.com/skycoder/comfyui-skycoder-tools/releases)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
|
||||
A comprehensive collection of useful custom nodes for ComfyUI workflows. Designed to enhance productivity and extend ComfyUI's capabilities with practical, everyday tools.
|
||||
|
||||
## 🚀 Current Tools
|
||||
|
||||
### 📁 Directory Image Tools
|
||||
- **DirectoryImageLoader**: Load images from a directory by index
|
||||
- **DirectoryImageInfo**: Get detailed information about images in a directory
|
||||
|
||||
*More tools coming soon! This is just the beginning of the Skycoder Tools collection.*
|
||||
|
||||
## 🎯 Features
|
||||
|
||||
- **Modular Design**: Each tool category is organized in separate modules
|
||||
- **Easy Extension**: Simple structure for adding new tools
|
||||
- **Robust Error Handling**: Graceful fallbacks and detailed error messages
|
||||
- **Professional Quality**: Production-ready code with comprehensive testing
|
||||
- **Community Focused**: Built for and by the ComfyUI community
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
### Via ComfyUI Manager (Recommended)
|
||||
1. Open ComfyUI Manager
|
||||
2. Go to "Install Custom Nodes"
|
||||
3. Search for "Skycoder Tools"
|
||||
4. Click Install and restart ComfyUI
|
||||
|
||||
### Manual Installation
|
||||
```bash
|
||||
cd ComfyUI/custom_nodes
|
||||
git clone https://github.com/skycoder/comfyui-skycoder-tools.git
|
||||
# Restart ComfyUI
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
ComfyUI Skycoder Tools
|
||||
A collection of useful custom nodes for ComfyUI workflows
|
||||
"""
|
||||
|
||||
from .nodes.directory_image_loader import NODE_CLASS_MAPPINGS as DIR_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as DIR_DISPLAY_MAPPINGS
|
||||
|
||||
# Kombiniere alle Node-Mappings (für zukünftige Erweiterungen)
|
||||
NODE_CLASS_MAPPINGS = {}
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {}
|
||||
|
||||
# Directory Image Loader Nodes
|
||||
NODE_CLASS_MAPPINGS.update(DIR_MAPPINGS)
|
||||
NODE_DISPLAY_NAME_MAPPINGS.update(DIR_DISPLAY_MAPPINGS)
|
||||
|
||||
# Exportiere alle Node-Mappings für ComfyUI
|
||||
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
|
||||
|
||||
# Metadaten
|
||||
__version__ = "1.0.0"
|
||||
__author__ = "Skycoder"
|
||||
__description__ = "A collection of useful custom nodes for ComfyUI workflows"
|
||||
__license__ = "MIT"
|
||||
|
||||
# ComfyUI Manager Metadaten
|
||||
WEB_DIRECTORY = "./web"
|
||||
|
||||
print(f"🛠️ Skycoder Tools v{__version__} loaded successfully!")
|
||||
print(f"📦 Loaded nodes: {len(NODE_CLASS_MAPPINGS)} nodes available")
|
||||
@@ -0,0 +1,142 @@
|
||||
{
|
||||
"last_node_id": 4,
|
||||
"last_link_id": 3,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "DirectoryImageInfo",
|
||||
"pos": [50, 50],
|
||||
"size": [300, 150],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "info",
|
||||
"type": "STRING",
|
||||
"links": [3],
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "count",
|
||||
"type": "INT",
|
||||
"links": [],
|
||||
"slot_index": 1
|
||||
}
|
||||
],
|
||||
"properties": {},
|
||||
"widgets_values": [
|
||||
"/path/to/your/images"
|
||||
],
|
||||
"title": "📊 Check Directory"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "DirectoryImageLoader",
|
||||
"pos": [50, 250],
|
||||
"size": [300, 150],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [1],
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "filename",
|
||||
"type": "STRING",
|
||||
"links": [2],
|
||||
"slot_index": 1
|
||||
}
|
||||
],
|
||||
"properties": {},
|
||||
"widgets_values": [
|
||||
"/path/to/your/images",
|
||||
0
|
||||
],
|
||||
"title": "📁 Load Image by Index"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "PreviewImage",
|
||||
"pos": [400, 250],
|
||||
"size": [300, 300],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"properties": {},
|
||||
"title": "🖼️ Preview"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "ShowText",
|
||||
"pos": [400, 50],
|
||||
"size": [300, 200],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 2
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"properties": {},
|
||||
"title": "📝 Filename Display"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "ShowText",
|
||||
"pos": [750, 50],
|
||||
"size": [300, 200],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"link": 3
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"properties": {},
|
||||
"title": "ℹ️ Directory Info"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[1, 2, 0, 3, 0, "IMAGE"],
|
||||
[2, 2, 1, 4, 0, "STRING"],
|
||||
[3, 1, 0, 5, 0, "STRING"]
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"title": "🛠️ Skycoder Tools Example",
|
||||
"bounding": [25, -25, 1050, 650],
|
||||
"color": "#3f789e"
|
||||
}
|
||||
],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1,
|
||||
"offset": [0, 0]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
"""
|
||||
Skycoder Tools - Node Collection
|
||||
"""
|
||||
# Dies ist eine leere __init__.py für das nodes Verzeichnis
|
||||
@@ -0,0 +1,162 @@
|
||||
import os
|
||||
import torch
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
|
||||
class DirectoryImageLoader:
|
||||
"""
|
||||
ComfyUI Node zum Laden von Bildern aus einem Verzeichnis basierend auf Index
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"directory_path": ("STRING", {
|
||||
"default": "",
|
||||
"multiline": False,
|
||||
"placeholder": "Pfad zum Bildverzeichnis"
|
||||
}),
|
||||
"index": ("INT", {
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 999999,
|
||||
"step": 1
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE", "STRING")
|
||||
RETURN_NAMES = ("image", "filename")
|
||||
FUNCTION = "load_image_by_index"
|
||||
CATEGORY = "image/io"
|
||||
|
||||
# Unterstützte Bildformate
|
||||
SUPPORTED_FORMATS = {'.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.tif', '.webp', '.gif'}
|
||||
|
||||
def load_image_by_index(self, directory_path, index):
|
||||
"""
|
||||
Lädt ein Bild basierend auf dem Index aus dem angegebenen Verzeichnis
|
||||
"""
|
||||
try:
|
||||
# Prüfen ob Verzeichnis existiert
|
||||
if not os.path.exists(directory_path):
|
||||
raise ValueError(f"Verzeichnis nicht gefunden: {directory_path}")
|
||||
|
||||
if not os.path.isdir(directory_path):
|
||||
raise ValueError(f"Pfad ist kein Verzeichnis: {directory_path}")
|
||||
|
||||
# Alle Bilddateien im Verzeichnis finden und sortieren
|
||||
image_files = []
|
||||
for filename in os.listdir(directory_path):
|
||||
if any(filename.lower().endswith(ext) for ext in self.SUPPORTED_FORMATS):
|
||||
image_files.append(filename)
|
||||
|
||||
# Sortieren für konsistente Reihenfolge
|
||||
image_files.sort()
|
||||
|
||||
if not image_files:
|
||||
raise ValueError(f"Keine Bilddateien im Verzeichnis gefunden: {directory_path}")
|
||||
|
||||
# Index prüfen
|
||||
if index >= len(image_files):
|
||||
raise ValueError(f"Index {index} außerhalb des Bereichs. Verfügbare Bilder: 0-{len(image_files)-1}")
|
||||
|
||||
# Dateiname und vollständigen Pfad ermitteln
|
||||
filename = image_files[index]
|
||||
full_path = os.path.join(directory_path, filename)
|
||||
|
||||
# Bild laden
|
||||
image = Image.open(full_path)
|
||||
|
||||
# Zu RGB konvertieren falls nötig
|
||||
if image.mode != 'RGB':
|
||||
image = image.convert('RGB')
|
||||
|
||||
# Zu numpy array konvertieren
|
||||
image_array = np.array(image).astype(np.float32) / 255.0
|
||||
|
||||
# Zu torch tensor konvertieren und Dimensionen anpassen für ComfyUI (batch, height, width, channels)
|
||||
image_tensor = torch.from_numpy(image_array)[None,]
|
||||
|
||||
return (image_tensor, filename)
|
||||
|
||||
except Exception as e:
|
||||
# Fallback: schwarzes Bild erstellen bei Fehlern
|
||||
print(f"Fehler beim Laden des Bildes: {str(e)}")
|
||||
|
||||
# Schwarzes 512x512 Bild erstellen
|
||||
black_image = torch.zeros((1, 512, 512, 3), dtype=torch.float32)
|
||||
error_filename = f"ERROR: {str(e)}"
|
||||
|
||||
return (black_image, error_filename)
|
||||
|
||||
|
||||
class DirectoryImageInfo:
|
||||
"""
|
||||
Hilfsfunktion um Informationen über Bilder in einem Verzeichnis zu erhalten
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"directory_path": ("STRING", {
|
||||
"default": "",
|
||||
"multiline": False,
|
||||
"placeholder": "Pfad zum Bildverzeichnis"
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "INT")
|
||||
RETURN_NAMES = ("info", "count")
|
||||
FUNCTION = "get_directory_info"
|
||||
CATEGORY = "image/io"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def get_directory_info(self, directory_path):
|
||||
"""
|
||||
Gibt Informationen über das Bildverzeichnis zurück
|
||||
"""
|
||||
try:
|
||||
if not os.path.exists(directory_path) or not os.path.isdir(directory_path):
|
||||
return ("Verzeichnis nicht gefunden oder ungültig", 0)
|
||||
|
||||
# Bilddateien zählen
|
||||
supported_formats = {'.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.tif', '.webp', '.gif'}
|
||||
image_files = []
|
||||
|
||||
for filename in os.listdir(directory_path):
|
||||
if any(filename.lower().endswith(ext) for ext in supported_formats):
|
||||
image_files.append(filename)
|
||||
|
||||
image_files.sort()
|
||||
count = len(image_files)
|
||||
|
||||
if count == 0:
|
||||
info = "Keine Bilddateien gefunden"
|
||||
else:
|
||||
info = f"Gefunden: {count} Bilder\n"
|
||||
info += f"Erste 5 Dateien:\n"
|
||||
for i, filename in enumerate(image_files[:5]):
|
||||
info += f" [{i}] {filename}\n"
|
||||
if count > 5:
|
||||
info += f" ... und {count-5} weitere"
|
||||
|
||||
return (info, count)
|
||||
|
||||
except Exception as e:
|
||||
return (f"Fehler: {str(e)}", 0)
|
||||
|
||||
|
||||
# Node Registrierung für ComfyUI
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"DirectoryImageLoader": DirectoryImageLoader,
|
||||
"DirectoryImageInfo": DirectoryImageInfo
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"DirectoryImageLoader": "📁 Directory Image Loader",
|
||||
"DirectoryImageInfo": "ℹ️ Directory Image Info"
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=45", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "comfyui-skycoder-tools"
|
||||
version = "1.0.0"
|
||||
description = "A collection of useful custom nodes for ComfyUI workflows"
|
||||
authors = [
|
||||
{name = "Skycoder", email = "skycoder@example.com"}
|
||||
]
|
||||
license = {text = "MIT"}
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
]
|
||||
keywords = ["comfyui", "image-processing", "custom-nodes", "ai", "tools", "workflow"]
|
||||
|
||||
dependencies = [
|
||||
"Pillow>=8.0.0",
|
||||
"torch>=1.9.0",
|
||||
"numpy>=1.21.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/skycoder/comfyui-skycoder-tools"
|
||||
Repository = "https://github.com/skycoder/comfyui-skycoder-tools"
|
||||
Issues = "https://github.com/skycoder/comfyui-skycoder-tools/issues"
|
||||
Discussions = "https://github.com/skycoder/comfyui-skycoder-tools/discussions"
|
||||
Reference in New Issue
Block a user