Add preview and file browser features
Features: - Added OUTPUT_NODE for real-time image preview - Implemented Browse button with JavaScript widget - Enhanced path input with placeholder and default value - Updated README with new feature documentation Changes: - random_image_picker.py: Added OUTPUT_NODE, improved INPUT_TYPES - web/random_image_picker.js: New custom widget for file/folder selection - README.md: Updated documentation with new features - .gitignore: Added web directory ignore patterns
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
|
||||
# Virtual environments
|
||||
venv/
|
||||
env/
|
||||
ENV/
|
||||
|
||||
# IDEs
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Project specific
|
||||
*.log
|
||||
|
||||
@@ -9,6 +9,8 @@ A ComfyUI custom node that provides flexible image loading with support for both
|
||||
- **Subfolder Support**: Option to include subfolders in the search
|
||||
- **Resolution Output**: Automatically outputs image width and height
|
||||
- **Reproducible Random**: Seed control for consistent random selection
|
||||
- **🆕 Image Preview**: Real-time preview of loaded images in the UI
|
||||
- **🆕 File Browser**: Convenient "Browse..." button for file/folder selection
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -20,6 +22,16 @@ A ComfyUI custom node that provides flexible image loading with support for both
|
||||
|
||||
2. Restart ComfyUI
|
||||
|
||||
3. The node will appear in the "image" category as "Random Image Picker"
|
||||
|
||||
## Usage Tips
|
||||
|
||||
- **Using the Browse Button**: Click "Browse..." to open your system's file/folder selector
|
||||
- Note: Due to browser security limitations, you may need to manually enter the full path
|
||||
- **Default Path**: The input field defaults to your ComfyUI input directory
|
||||
- **Path Format**: Use forward slashes `/` or double backslashes `\\` on Windows
|
||||
- **Preview**: The loaded image automatically appears in the node's preview area
|
||||
|
||||
## Usage
|
||||
|
||||
### Node Inputs
|
||||
@@ -27,10 +39,13 @@ A ComfyUI custom node that provides flexible image loading with support for both
|
||||
- **path** (STRING):
|
||||
- In Single mode: Full path to an image file
|
||||
- In Folder mode: Full path to a folder containing images
|
||||
- 🆕 **Browse Button**: Click "Browse..." to select files/folders using your file explorer
|
||||
- Default: ComfyUI input directory
|
||||
|
||||
- **folder_mode** (BOOLEAN):
|
||||
- `OFF` (Single): Load the specified image file
|
||||
- `ON` (Folder): Randomly select an image from the folder
|
||||
- Note: The browse dialog changes based on this setting
|
||||
|
||||
- **include_subfolders** (BOOLEAN):
|
||||
- `OFF`: Only scan the specified folder
|
||||
@@ -42,7 +57,7 @@ A ComfyUI custom node that provides flexible image loading with support for both
|
||||
|
||||
### Node Outputs
|
||||
|
||||
- **IMAGE**: The loaded image in ComfyUI tensor format
|
||||
- **IMAGE**: The loaded image in ComfyUI tensor format (with real-time preview)
|
||||
- **width** (INT): Image width in pixels
|
||||
- **height** (INT): Image height in pixels
|
||||
|
||||
@@ -89,6 +104,8 @@ Randomly selects one image from `D:/images/` and all its subfolders
|
||||
- Output tensor format: `[batch, height, width, channels]`
|
||||
- Pixel values normalized to 0.0-1.0 range
|
||||
- Uses PyTorch tensors for ComfyUI compatibility
|
||||
- Real-time preview in ComfyUI UI (OUTPUT_NODE enabled)
|
||||
- Custom JavaScript widget for enhanced file selection
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+27
-4
@@ -20,12 +20,34 @@ class RandomImagePicker:
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
# Get default input directory from ComfyUI
|
||||
try:
|
||||
default_path = folder_paths.get_input_directory()
|
||||
except:
|
||||
default_path = ""
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"path": ("STRING", {"default": "", "multiline": False}),
|
||||
"folder_mode": ("BOOLEAN", {"default": False, "label_on": "Folder", "label_off": "Single"}),
|
||||
"include_subfolders": ("BOOLEAN", {"default": False, "label_on": "ON", "label_off": "OFF"}),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"path": ("STRING", {
|
||||
"default": default_path,
|
||||
"multiline": False,
|
||||
"placeholder": "Path to image file or folder"
|
||||
}),
|
||||
"folder_mode": ("BOOLEAN", {
|
||||
"default": False,
|
||||
"label_on": "Folder",
|
||||
"label_off": "Single"
|
||||
}),
|
||||
"include_subfolders": ("BOOLEAN", {
|
||||
"default": False,
|
||||
"label_on": "ON",
|
||||
"label_off": "OFF"
|
||||
}),
|
||||
"seed": ("INT", {
|
||||
"default": 0,
|
||||
"min": 0,
|
||||
"max": 0xffffffffffffffff
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -33,6 +55,7 @@ class RandomImagePicker:
|
||||
RETURN_NAMES = ("IMAGE", "width", "height")
|
||||
FUNCTION = "load_image"
|
||||
CATEGORY = "image"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
@staticmethod
|
||||
def get_image_files(directory: str, include_subfolders: bool = False) -> List[str]:
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
|
||||
app.registerExtension({
|
||||
name: "Comfy.RandomImagePicker",
|
||||
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (nodeData.name === "RandomImagePicker") {
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
||||
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
const result = onNodeCreated?.apply(this, arguments);
|
||||
|
||||
// Add file browser button
|
||||
const pathWidget = this.widgets.find(w => w.name === "path");
|
||||
if (pathWidget) {
|
||||
// Add button to open file dialog
|
||||
const button = this.addWidget("button", "Browse...", null, () => {
|
||||
// Create file input element
|
||||
const input = document.createElement("input");
|
||||
|
||||
// Get folder_mode widget value
|
||||
const folderModeWidget = this.widgets.find(w => w.name === "folder_mode");
|
||||
const isFolderMode = folderModeWidget?.value || false;
|
||||
|
||||
if (isFolderMode) {
|
||||
// Folder selection
|
||||
input.type = "file";
|
||||
input.webkitdirectory = true;
|
||||
input.directory = true;
|
||||
} else {
|
||||
// File selection
|
||||
input.type = "file";
|
||||
input.accept = "image/png, image/jpeg, image/webp, image/bmp, image/gif";
|
||||
}
|
||||
|
||||
input.onchange = (e) => {
|
||||
if (e.target.files && e.target.files[0]) {
|
||||
if (isFolderMode) {
|
||||
// Get folder path from first file
|
||||
const firstFile = e.target.files[0];
|
||||
const fullPath = firstFile.webkitRelativePath || firstFile.name;
|
||||
const folderPath = fullPath.split('/')[0];
|
||||
pathWidget.value = folderPath;
|
||||
} else {
|
||||
// Get file path
|
||||
const file = e.target.files[0];
|
||||
// Note: For security reasons, browsers don't expose full file paths
|
||||
// We can only get the file name, not the full path
|
||||
// Users will need to manually enter the full path or use relative paths
|
||||
pathWidget.value = file.name;
|
||||
|
||||
// Show info message
|
||||
console.log("Note: Due to browser security, full path is not available. Please enter the complete path manually.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
input.click();
|
||||
});
|
||||
|
||||
// Add helper text
|
||||
this.addWidget("text", "helper", "Tip: Enter full path or use ComfyUI input folder", () => {}, {
|
||||
serialize: false
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user