@@ -377,16 +377,17 @@ def sort_files(files: List[str], sort_method: str) -> List[str]:
377377 return sorted (files )
378378
379379class IFLoadImagess :
380+ _color_channels = ["alpha" , "red" , "green" , "blue" ]
381+
380382 def __init__ (self ):
381- self .path_cache = {} # Cache for path mapping
383+ self .path_cache = {}
382384
383385 @classmethod
384386 def INPUT_TYPES (s ):
385387 input_dir = folder_paths .get_input_directory ()
386- # Count available thumbnails
387388 available_images = len ([f for f in os .listdir (input_dir )
388389 if f .startswith (ImageManager .THUMBNAIL_PREFIX )])
389- available_images = max (1 , available_images ) # Ensure at least 1
390+ available_images = max (1 , available_images )
390391
391392 files = [f for f in os .listdir (input_dir )
392393 if f .startswith (ImageManager .THUMBNAIL_PREFIX )]
@@ -396,7 +397,7 @@ def INPUT_TYPES(s):
396397 "image" : (sorted (files ), {"image_upload" : True }),
397398 "input_path" : ("STRING" , {"default" : "" }),
398399 "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 }),
400401 "load_limit" : (["10" , "100" , "1000" , "10000" , "100000" ], {"default" : "1000" }),
401402 "image_selected" : ("BOOLEAN" , {"default" : False }),
402403 "available_image_count" : ("INT" , {
@@ -408,19 +409,20 @@ def INPUT_TYPES(s):
408409 "include_subfolders" : ("BOOLEAN" , {"default" : True }),
409410 "sort_method" : (["alphabetical" , "numerical" , "date_created" , "date_modified" ],),
410411 "filter_type" : (["none" , "png" , "jpg" , "jpeg" , "webp" , "gif" , "bmp" ],),
412+ "channel" : (s ._color_channels , {"default" : "alpha" }),
411413 }
412414 }
413415
414416 RETURN_TYPES = ("IMAGE" , "MASK" , "STRING" , "STRING" , "STRING" , "INT" )
415417 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
417419 FUNCTION = "load_images"
418420 CATEGORY = "ImpactFrames💥🎞️"
419421
420422 @classmethod
421423 def IS_CHANGED (cls , image , input_path = "" , start_index = 0 , stop_index = 0 , max_images = 1 ,
422424 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" ):
424426 """
425427 Properly handle all input parameters and return NaN to force updates
426428 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
444446 def load_images (self , image = "" , input_path = "" , start_index = 0 , stop_index = 10 ,
445447 load_limit = "1000" , image_selected = False , available_image_count = 0 ,
446448 include_subfolders = True , sort_method = "numerical" ,
447- filter_type = "none" , image_name = "" , unique_id = None ):
449+ filter_type = "none" , channel = "alpha" ):
448450 try :
449451 # Process input path
450452 abs_path = os .path .abspath (input_path if os .path .isabs (input_path )
451453 else os .path .join (folder_paths .get_input_directory (), input_path ))
452454
453- # Get all valid images first
455+ # Get all valid images
454456 all_files = ImageManager .get_image_files (abs_path , include_subfolders , filter_type )
455457 if not all_files :
456458 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,
478480 start_index = image_order [image ]
479481 num_images = 1
480482
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-
486483 # Process selected range
487484 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
491487 images = []
492488 masks = []
493489 paths = []
494490 filenames = []
495491 count_strs = []
496492 count_ints = []
497493
498- for idx , ( file_path , thumb_name ) in enumerate (zip ( selected_files , selected_thumbnails ) ):
494+ for idx , file_path in enumerate (selected_files ):
499495 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' )
516512
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 )
524529
525530 except Exception as e :
526531 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,
530535 img_tensor , mask = self .load_placeholder ()
531536 return ([img_tensor ], [mask ], ["" ], ["" ], ["0/0" ], [0 ])
532537
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 )
548539
549540 except Exception as e :
550541 logger .error (f"Error in load_images: { e } " , exc_info = True )
@@ -555,9 +546,9 @@ def load_placeholder(self):
555546 """Creates and returns a placeholder image tensor and mask"""
556547 img = Image .new ('RGB' , (512 , 512 ), color = (73 , 109 , 137 ))
557548 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 ]
559550 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]
561552 return image_tensor , mask
562553
563554 def process_single_image (self , image_path : str ):
0 commit comments