
    
3j&                         S SK r S SKrS SKrS SKrS SKJr  S SKJr  S SK	J
r
  SSKJr   " S S5      r " S	 S
5      rS SKr " S S5      r\\\/rg)    N)args)Image)PngInfo   )logc                   T    \ rS rSrSr\S 5       rSrSrSr	SS jr
S rS	 rSS jrSrg
)MTB_StackImages   z2Stack the input images horizontally or vertically.c                 4    SSSS040/ SQSS04SSSS	.4S
.S.$ )NverticalBOOLEANdefaultF)errorsmallestlargestr   TzOutput RGB instead of RGBAr   tooltip)match_method
output_rgbrequiredoptional clss    H/home/wildlama/comfy/ComfyUI/custom_nodes/comfy_mtb/nodes/image_utils.pyINPUT_TYPESMTB_StackImages.INPUT_TYPES   sJ     $i)U1C%DE 5(!
  $1MN	
 	
    IMAGEstackmtb/image utilsc                   ^^ U(       d  [        S5      e[        UR                  5       5      n[        R                  " S[        U5       SU(       a  SOS 35        US   R                  nU Vs/ s H#  nU R                  UR                  U5      5      PM%     nn[        S U 5       5      n	U Vs/ s H  nU R                  Xy5      PM     nnUS:w  a  U(       aZ  U Vs/ s H  owR                  S	   PM     n
nUS
:X  a  [        U
5      O
[        U
5      nU Vs/ s H  nU R                  X{S9PM     nnOU Vs/ s H  owR                  S   PM     nnUS
:X  a  [        U5      O
[        U5      nU Vs/ s H  nU R                  X}S9PM     nnOvU(       a8  US   R                  S	   m[        U4S jU 5       5      (       a  [        S5      eO7US   R                  S   m[        U4S jU 5       5      (       a  [        S5      eU(       a  SOS	n[        R                   " XS9nU(       a  US S 2S S 2S S 2S S24   nU4$ s  snf s  snf s  snf s  snf s  snf s  snf )Nz%At least one tensor must be provided.z	Stacking z	 tensors 
verticallyhorizontallyr   c              3   >   #    U  H  oR                   S    v   M     g7f)r   Nshape).0tensors     r   	<genexpr>(MTB_StackImages.stack.<locals>.<genexpr>5   s     N;M\\!_;Ms   r   r   r   )width   )heightc              3   F   >#    U  H  oR                   S    T:g  v   M     g7f)r   Nr(   )r*   r+   r.   s     r   r,   r-   T   s       ;MLLOu,;M   !z;All tensors must have the same width for vertical stacking.c              3   F   >#    U  H  oR                   S    T:g  v   M     g7f)r/   Nr(   )r*   r+   r0   s     r   r,   r-   ]   s       <N&LLOv-<Nr2   z>All tensors must have the same height for horizontal stacking.dim   )
ValueErrorlistvaluesr   debuglendevicenormalize_to_rgbatomaxduplicate_framesr)   minresize_tensoranytorchcat)selfr   r   r   kwargstensorstarget_devicer+   normalized_tensorsmax_batch_sizewidthstarget_widthheightstarget_heightr5   stacked_tensorr0   r.   s                   @@r   r"   MTB_StackImages.stack$   s   DEEv}}'		G~Y'|^<>	

  
)) "
! ""699]#;<! 	 

 N;MNN -
, !!&9, 	 
 7"8JK8Jf,,q/8JK#/:#=CK3v; 
 #5&"4 &&v&B"4 # &" :LL9Kv<<?9KL $z1 LW  #5&"4 &&v&D"4 # &"
 *1-33A6 ;M   %1  ,A.44Q7 <N   %3 
 a#5?+Aq!RaRK8N  y

 L& M&s$   /*H?1II	I9I3Ic                     UR                   u      p#US:X  a  U$ US:X  aE  [        R                  " UR                   SS S-   UR                  S9n[        R                  " X4SS9$ [        S5      e)	z+Normalize tensor to have 4 channels (RGBA).   r6   N)r/   )r<   r4   zKTensor has an unsupported number of channels: expected 3 (RGB) or 4 (RGBA).)r)   rD   onesr<   rE   r7   )rF   r+   _channelsalpha_channels        r   r=   !MTB_StackImages.normalize_to_rgban   st    "LL1aq=M]!JJSb!D(M 99f4"==0 r   c                     UR                   S   nX2:  a=  X#-  nUR                  USSS5      nX#-  nUS:  a  [        R                  " XQSU 4SS9nU$ U$ )z:Duplicate frames in tensor to match the target batch size.r   r/   Nr4   )r)   repeatrD   rE   )rF   r+   target_batch_sizecurrent_batch_sizeduplication_factorsduplicated_tensorremaining_framess          r   r@    MTB_StackImages.duplicate_frames   ss    #\\!_1'8'N &.A1a K0E!#$)II&/@0@(AB%! %$Mr   Nc                 :   UR                   SS u  pEUb  X%:w  a  X%-  n[        XF-  5      nUnOUb  X4:w  a  X4-  n[        XV-  5      nUnOU$ [        R                  R                  R                  UR                  SSSS5      Xx4SSS9n	U	R                  SSSS5      $ )zJResize tensor to specified width or height while maintaining aspect ratio.r/   r6   r   r   bilinearF)sizemodealign_corners)r)   intrD   nn
functionalinterpolatepermute)
rF   r+   r.   r0   current_heightcurrent_widthscale_factor
new_height	new_widthresizeds
             r   rB   MTB_StackImages.resize_tensor   s    (.Qq(9%!7 0L^:;JIF$<!2LM89IJM((%%11NN1aA&(	 2 
 q!Q**r   r   )r   T)NN)__name__
__module____qualname____firstlineno____doc__classmethodr   RETURN_TYPESFUNCTIONCATEGORYr"   r=   r@   rB   __static_attributes__r   r   r   r	   r	      s>    <
 
 LH HH!T$+r   r	   c                   >    \ rS rSrSr\S 5       rSrSrSr	S
S jr
S	rg)MTB_PickFromBatch   zNPick a specific number of images from a batch.

either from the start or end.
c                 ,    SSS/SS04SSS04S.SS	0S
.$ )Nr    endstartr   INTr/   )imagefrom_directioncountmask)MASKr   r   r   s    r   r   MTB_PickFromBatch.INPUT_TYPES   s@     $$)7#3i5I"J)Q0 		
 		
r   )r!   r   pick_from_batchr#   Nc                     UR                  S5      n[        X55      nS nUS:X  a  X* S  nUb  XC* S  nXv4$ US U nUb  US U nXv4$ )Nr   r   )rd   rA   )rF   r   r   r   r   
batch_sizeselected_masksselected_tensorss           r   r   !MTB_PickFromBatch.pick_from_batch   sx    ZZ]
 E&U"$VW~!%fg !11	  %Ve}!%fu 11r   r   )N)rs   rt   ru   rv   rw   rx   r   ry   rz   r{   r   r|   r   r   r   r~   r~      s1    
 

 

 %L H H2r   r~   c                   J    \ rS rSrS r\S 5       rSrSrSr	Sr
   SS	 jrS
rg)MTB_SaveImage   c                 b    [         R                  " 5       U l        SU l        SU l        SU l        g )Noutput rS   )folder_pathsget_output_directory
output_dirtypeprefix_appendcompress_level)rF   s    r   __init__MTB_SaveImage.__init__   s)    &;;=	r   c                 *    SSS04SSSS.4S.S	S
S.S.$ )Nr!   r   zThe images to save.STRINGComfyUIzThe prefix for the file to save. This may include formatting information such as %date:yyyy-MM-dd% or %Empty Latent Image.width% to include values from nodes.r   )imagesfilename_prefixPROMPTEXTRA_PNGINFO)promptextra_pnginfo)r   hiddenr   r   s    r   r   MTB_SaveImage.INPUT_TYPES   sA     #Y0E$FG#, $D$	 "*OL
 	
r   r    save_imagesr#   a+  Saves the input images to your ComfyUI output directory.
    This behaves exactly like the native SaveImage node but isn't an output node.
    The reason I made this is to allow 'inlining' image save in loops for instance,
    using the native node there wouldn't run for each iteration of the loop.Nc           	         X R                   -  n[        R                  " UU R                  US   R                  S   US   R                  S   5      u  pVpxn[        5       n	[        U5       GHn  u  pSUR                  5       R                  5       -  n[        R                  " [        R                  " USS5      R                  [        R                  5      5      nS n[        R                   (       dg  [#        5       nUb&  UR%                  S[&        R(                  " U5      5        Ub1  U H+  nUR%                  U[&        R(                  " XO   5      5        M-     UR+                  S[-        U
5      5      nU SUS S	3nUR/                  [0        R2                  R5                  UU5      UU R6                  S
9  U	R9                  UXR:                  S.5        US-  nGMq     SU	0U4S.$ )Nr   r/   g     o@   r   z%batch_num%rV   05z_.png)pnginfor   )filename	subfolderr   r   )uiresult)r   r   get_save_image_pathr   r)   r8   	enumeratecpunumpyr   	fromarraynpclipastypeuint8r   disable_metadatar   add_textjsondumpsreplacestrsaveospathjoinr   appendr   )rF   r   r   r   r   full_output_folderr   counterr   resultsbatch_numberr   iimgmetadataxfilename_with_batch_numfiles                     r   r   MTB_SaveImage.save_images   s    	---,,q	"q	"	 	Jg/ &#,V#4L		))++A//"''!Q"4";";BHH"EFCH(("9%%%h

60BC ,* ))!TZZ8H-IJ + '/&6&6s<0'# ..a|5ADHH/6 #22  
 NN!	99M qLG1 $54  )fY??r   )r   r   r   r   )r   NN)rs   rt   ru   rv   r   rx   r   ry   rz   r{   DESCRIPTIONr   r|   r   r   r   r   r      sG      
 
 LH !HPK "+@r   r   )r   r   r   r   rD   comfy.cli_argsr   PILr   PIL.PngImagePluginr   r   r	   r~   r   r   	__nodes__r   r   r   <module>r      sX     	     & X+ X+v(2 (2V M@ M@` /?	r   