@@ -377,16 +377,17 @@ def sort_files(files: List[str], sort_method: str) -> List[str]:
377
377
return sorted (files )
378
378
379
379
class IFLoadImagess :
380
+ _color_channels = ["alpha" , "red" , "green" , "blue" ]
381
+
380
382
def __init__ (self ):
381
- self .path_cache = {} # Cache for path mapping
383
+ self .path_cache = {}
382
384
383
385
@classmethod
384
386
def INPUT_TYPES (s ):
385
387
input_dir = folder_paths .get_input_directory ()
386
- # Count available thumbnails
387
388
available_images = len ([f for f in os .listdir (input_dir )
388
389
if f .startswith (ImageManager .THUMBNAIL_PREFIX )])
389
- available_images = max (1 , available_images ) # Ensure at least 1
390
+ available_images = max (1 , available_images )
390
391
391
392
files = [f for f in os .listdir (input_dir )
392
393
if f .startswith (ImageManager .THUMBNAIL_PREFIX )]
@@ -396,7 +397,7 @@ def INPUT_TYPES(s):
396
397
"image" : (sorted (files ), {"image_upload" : True }),
397
398
"input_path" : ("STRING" , {"default" : "" }),
398
399
"start_index" : ("INT" , {"default" : 0 , "min" : 0 , "max" : 9999 }),
399
- "stop_index" : ("INT" , {"default" : 10 , "min" : 1 , "max" : 9999 }), # Changed to stop_index
400
+ "stop_index" : ("INT" , {"default" : 10 , "min" : 1 , "max" : 9999 }),
400
401
"load_limit" : (["10" , "100" , "1000" , "10000" , "100000" ], {"default" : "1000" }),
401
402
"image_selected" : ("BOOLEAN" , {"default" : False }),
402
403
"available_image_count" : ("INT" , {
@@ -408,19 +409,20 @@ def INPUT_TYPES(s):
408
409
"include_subfolders" : ("BOOLEAN" , {"default" : True }),
409
410
"sort_method" : (["alphabetical" , "numerical" , "date_created" , "date_modified" ],),
410
411
"filter_type" : (["none" , "png" , "jpg" , "jpeg" , "webp" , "gif" , "bmp" ],),
412
+ "channel" : (s ._color_channels , {"default" : "alpha" }),
411
413
}
412
414
}
413
415
414
416
RETURN_TYPES = ("IMAGE" , "MASK" , "STRING" , "STRING" , "STRING" , "INT" )
415
417
RETURN_NAMES = ("images" , "masks" , "image_paths" , "filenames" , "count_str" , "count_int" )
416
- OUTPUT_IS_LIST = (True , True , True , True , True , True )
418
+ OUTPUT_IS_LIST = (True , True , True , True , True , True ) # Keep as list outputs
417
419
FUNCTION = "load_images"
418
420
CATEGORY = "ImpactFrames💥🎞️"
419
421
420
422
@classmethod
421
423
def IS_CHANGED (cls , image , input_path = "" , start_index = 0 , stop_index = 0 , max_images = 1 ,
422
424
include_subfolders = True , sort_method = "numerical" , image_selected = False ,
423
- filter_type = "none" , image_name = "" , unique_id = None , load_limit = "1000" , available_image_count = 0 ):
425
+ filter_type = "none" , image_name = "" , unique_id = None , load_limit = "1000" , available_image_count = 0 , channel = "alpha" ):
424
426
"""
425
427
Properly handle all input parameters and return NaN to force updates
426
428
This matches the input parameters from INPUT_TYPES
@@ -444,13 +446,13 @@ def IS_CHANGED(cls, image, input_path="", start_index=0, stop_index=0, max_image
444
446
def load_images (self , image = "" , input_path = "" , start_index = 0 , stop_index = 10 ,
445
447
load_limit = "1000" , image_selected = False , available_image_count = 0 ,
446
448
include_subfolders = True , sort_method = "numerical" ,
447
- filter_type = "none" , image_name = "" , unique_id = None ):
449
+ filter_type = "none" , channel = "alpha" ):
448
450
try :
449
451
# Process input path
450
452
abs_path = os .path .abspath (input_path if os .path .isabs (input_path )
451
453
else os .path .join (folder_paths .get_input_directory (), input_path ))
452
454
453
- # Get all valid images first
455
+ # Get all valid images
454
456
all_files = ImageManager .get_image_files (abs_path , include_subfolders , filter_type )
455
457
if not all_files :
456
458
logger .warning (f"No valid images found in { abs_path } " )
@@ -478,49 +480,52 @@ def load_images(self, image="", input_path="", start_index=0, stop_index=10,
478
480
start_index = image_order [image ]
479
481
num_images = 1
480
482
481
- # Create path mapping
482
- self .path_cache = {
483
- thumb : orig for thumb , orig in zip (all_thumbnails , all_files [start_index :start_index + num_images ])
484
- }
485
-
486
483
# Process selected range
487
484
selected_files = all_files [start_index :start_index + num_images ]
488
- selected_thumbnails = all_thumbnails [:num_images ]
489
-
490
- # Process selected files
485
+
486
+ # Lists to store outputs
491
487
images = []
492
488
masks = []
493
489
paths = []
494
490
filenames = []
495
491
count_strs = []
496
492
count_ints = []
497
493
498
- for idx , ( file_path , thumb_name ) in enumerate (zip ( selected_files , selected_thumbnails ) ):
494
+ for idx , file_path in enumerate (selected_files ):
499
495
try :
500
- with Image .open (file_path ) as img :
501
- img = ImageOps .exif_transpose (img )
502
-
503
- if img .mode == 'I' :
504
- img = img .point (lambda i : i * (1 / 255 ))
505
- image = img .convert ('RGB' )
506
-
507
- image_array = np . array ( image ). astype ( np . float32 ) / 255.0
508
- image_tensor = torch . from_numpy ( image_array )[ None ,]
509
-
510
- if 'A' in img . getbands ():
511
- mask = np . array ( img . getchannel ( 'A' )). astype ( np . float32 ) / 255.0
512
- mask = 1. - torch . from_numpy ( mask )
513
- else :
514
- mask = torch . zeros (( image_array . shape [ 0 ], image_array . shape [ 1 ]),
515
- dtype = torch . float32 , device = "cpu" )
496
+ img = Image .open (file_path )
497
+ img = ImageOps .exif_transpose (img )
498
+
499
+ if img .mode == 'I' :
500
+ img = img .point (lambda i : i * (1 / 255 ))
501
+ image = img .convert ('RGB' )
502
+
503
+ # Convert to numpy array and normalize
504
+ image_array = np . array ( image ). astype ( np . float32 ) / 255.0
505
+ # Correct order: [1, H, W, 3]
506
+ image_tensor = torch . from_numpy ( image_array ). unsqueeze ( 0 )
507
+ images . append ( image_tensor )
508
+
509
+ # Handle mask based on selected channel
510
+ if img . mode not in ( 'RGB' , 'L' ):
511
+ img = img . convert ( 'RGBA' )
516
512
517
- images .append (image_tensor )
518
- masks .append (mask .unsqueeze (0 ))
519
- paths .append (file_path )
520
- filenames .append (os .path .basename (file_path ))
521
- count_str = f"{ start_index + idx + 1 } /{ total_files } " # Update count to show global position
522
- count_strs .append (count_str )
523
- count_ints .append (start_index + idx + 1 )
513
+ c = channel [0 ].upper ()
514
+ if c in img .getbands ():
515
+ mask = np .array (img .getchannel (c )).astype (np .float32 ) / 255.0
516
+ mask = torch .from_numpy (mask )
517
+ if c == 'A' :
518
+ mask = 1. - mask
519
+ else :
520
+ mask = torch .zeros ((image_array .shape [0 ], image_array .shape [1 ]),
521
+ dtype = torch .float32 , device = "cpu" )
522
+
523
+ masks .append (mask .unsqueeze (0 )) # Add batch dimension to mask [1, H, W]
524
+
525
+ paths .append (file_path )
526
+ filenames .append (os .path .basename (file_path ))
527
+ count_strs .append (f"{ start_index + idx + 1 } /{ total_files } " )
528
+ count_ints .append (start_index + idx + 1 )
524
529
525
530
except Exception as e :
526
531
logger .error (f"Error processing image { file_path } : { e } " )
@@ -530,21 +535,7 @@ def load_images(self, image="", input_path="", start_index=0, stop_index=10,
530
535
img_tensor , mask = self .load_placeholder ()
531
536
return ([img_tensor ], [mask ], ["" ], ["" ], ["0/0" ], [0 ])
532
537
533
- ui_data = {
534
- "images" : all_thumbnails ,
535
- "current_thumbnails" : selected_thumbnails ,
536
- "total_images" : total_files ,
537
- "path_mapping" : self .path_cache ,
538
- "available_image_count" : total_files ,
539
- "image_order" : image_order ,
540
- "start_index" : start_index ,
541
- "stop_index" : start_index + num_images
542
- }
543
-
544
- return {
545
- "ui" : {"values" : ui_data },
546
- "result" : (images , masks , paths , filenames , count_strs , count_ints )
547
- }
538
+ return (images , masks , paths , filenames , count_strs , count_ints )
548
539
549
540
except Exception as e :
550
541
logger .error (f"Error in load_images: { e } " , exc_info = True )
@@ -555,9 +546,9 @@ def load_placeholder(self):
555
546
"""Creates and returns a placeholder image tensor and mask"""
556
547
img = Image .new ('RGB' , (512 , 512 ), color = (73 , 109 , 137 ))
557
548
image_array = np .array (img ).astype (np .float32 ) / 255.0
558
- image_tensor = torch .from_numpy (image_array )[ None , ]
549
+ image_tensor = torch .from_numpy (image_array ). unsqueeze ( 0 ) # [1, H, W, 3 ]
559
550
mask = torch .zeros ((1 , image_array .shape [0 ], image_array .shape [1 ]),
560
- dtype = torch .float32 , device = "cpu" )
551
+ dtype = torch .float32 , device = "cpu" ) # [1, H, W]
561
552
return image_tensor , mask
562
553
563
554
def process_single_image (self , image_path : str ):
0 commit comments